Skip to content

Commit 93c8e4d

Browse files
feat: Make password hashing parameters configurable (#2332)
* Make password hashing parameters configurable * black linting fixes --------- Co-authored-by: Daniel Vaz Gaspar <danielvazgaspar@gmail.com>
1 parent b1befb7 commit 93c8e4d

File tree

8 files changed

+96
-10
lines changed

8 files changed

+96
-10
lines changed

bin/hash_db_password.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@
3838

3939
for user in users:
4040
log.info("Hashing password for {0}".format(user.username))
41-
user.password = generate_password_hash(user.password)
41+
user.password = generate_password_hash(
42+
password=user.password,
43+
method=app.config.get('FAB_PASSWORD_HASH_METHOD', 'scrypt'),
44+
salt_length=app.config.get('FAB_PASSWORD_HASH_SALT_LENGTH', 16),
45+
)
4246
try:
4347
db.session.merge(user)
4448
db.session.commit()

docs/config.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,16 @@ Use config.py to configure the following parameters. By default it will use SQLL
325325
| | validation for AUTH database users. | No |
326326
| | Default is False. | |
327327
+----------------------------------------+--------------------------------------------+-----------+
328+
| FAB_PASSWORD_HASH_METHOD | Sets the password hashing method. For the | |
329+
| | supported parameters see | |
330+
| | `generate_password_hash`_. | No |
331+
| | Default: ``'scrypt'``. | |
332+
+----------------------------------------+--------------------------------------------+-----------+
333+
| FAB_PASSWORD_HASH_SALT_LENGTH | Sets the password hashing salt length. | No |
334+
| | Default: ``16``. | |
335+
+----------------------------------------+--------------------------------------------+-----------+
336+
337+
.. _generate_password_hash: https://werkzeug.palletsprojects.com/en/stable/utils/#werkzeug.security.generate_password_hash
328338

329339
Note
330340
----

flask_appbuilder/security/manager.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,15 @@ def reset_password(self, userid, password):
950950
The clear text password to reset and save hashed on the db
951951
"""
952952
user = self.get_user_by_id(userid)
953-
user.password = generate_password_hash(password)
953+
user.password = generate_password_hash(
954+
password=password,
955+
method=self.appbuilder.get_app.config.get(
956+
"FAB_PASSWORD_HASH_METHOD", "scrypt"
957+
),
958+
salt_length=self.appbuilder.get_app.config.get(
959+
"FAB_PASSWORD_HASH_SALT_LENGTH", 16
960+
),
961+
)
954962
self.update_user(user)
955963

956964
def update_user_auth_stat(self, user, success=True):

flask_appbuilder/security/mongoengine/manager.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,15 @@ def add_register_user(
9494
if hashed_password:
9595
register_user.password = hashed_password
9696
else:
97-
register_user.password = generate_password_hash(password)
97+
register_user.password = generate_password_hash(
98+
password=password,
99+
method=self.appbuilder.get_app.config.get(
100+
"FAB_PASSWORD_HASH_METHOD", "scrypt"
101+
),
102+
salt_length=self.appbuilder.get_app.config.get(
103+
"FAB_PASSWORD_HASH_SALT_LENGTH", 16
104+
),
105+
)
98106
register_user.registration_hash = str(uuid.uuid1())
99107
register_user.save()
100108
return register_user
@@ -141,7 +149,15 @@ def add_user(
141149
if hashed_password:
142150
user.password = hashed_password
143151
else:
144-
user.password = generate_password_hash(password)
152+
user.password = generate_password_hash(
153+
password=password,
154+
method=self.appbuilder.get_app.config.get(
155+
"FAB_PASSWORD_HASH_METHOD", "scrypt"
156+
),
157+
salt_length=self.appbuilder.get_app.config.get(
158+
"FAB_PASSWORD_HASH_SALT_LENGTH", 16
159+
),
160+
)
145161
user.save()
146162
log.info(c.LOGMSG_INF_SEC_ADD_USER, username)
147163
return user

flask_appbuilder/security/sqla/apis/user/api.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,26 @@ def pre_update(self, item):
6969
item.changed_on = datetime.now()
7070
item.changed_by_fk = g.user.id
7171
if item.password:
72-
item.password = generate_password_hash(item.password)
72+
item.password = generate_password_hash(
73+
password=item.password,
74+
method=self.appbuilder.get_app.config.get(
75+
"FAB_PASSWORD_HASH_METHOD", "scrypt"
76+
),
77+
salt_length=self.appbuilder.get_app.config.get(
78+
"FAB_PASSWORD_HASH_SALT_LENGTH", 16
79+
),
80+
)
7381

7482
def pre_add(self, item):
75-
item.password = generate_password_hash(item.password)
83+
item.password = generate_password_hash(
84+
password=item.password,
85+
method=self.appbuilder.get_app.config.get(
86+
"FAB_PASSWORD_HASH_METHOD", "scrypt"
87+
),
88+
salt_length=self.appbuilder.get_app.config.get(
89+
"FAB_PASSWORD_HASH_SALT_LENGTH", 16
90+
),
91+
)
7692

7793
@expose("/", methods=["POST"])
7894
@protect()

flask_appbuilder/security/sqla/manager.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,15 @@ def add_register_user(
141141
if hashed_password:
142142
register_user.password = hashed_password
143143
else:
144-
register_user.password = generate_password_hash(password)
144+
register_user.password = generate_password_hash(
145+
password=password,
146+
method=self.appbuilder.get_app.config.get(
147+
"FAB_PASSWORD_HASH_METHOD", "scrypt"
148+
),
149+
salt_length=self.appbuilder.get_app.config.get(
150+
"FAB_PASSWORD_HASH_SALT_LENGTH", 16
151+
),
152+
)
145153
register_user.registration_hash = str(uuid.uuid1())
146154
try:
147155
self.get_session.add(register_user)
@@ -234,7 +242,15 @@ def add_user(
234242
if hashed_password:
235243
user.password = hashed_password
236244
else:
237-
user.password = generate_password_hash(password)
245+
user.password = generate_password_hash(
246+
password=password,
247+
method=self.appbuilder.get_app.config.get(
248+
"FAB_PASSWORD_HASH_METHOD", "scrypt"
249+
),
250+
salt_length=self.appbuilder.get_app.config.get(
251+
"FAB_PASSWORD_HASH_SALT_LENGTH", 16
252+
),
253+
)
238254
self.get_session.add(user)
239255
self.get_session.commit()
240256
log.info(c.LOGMSG_INF_SEC_ADD_USER, username)

flask_appbuilder/security/views.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,15 @@ def pre_update(self, item: Any) -> None:
446446
item.changed_by_fk = g.user.id
447447

448448
def pre_add(self, item: Any) -> None:
449-
item.password = generate_password_hash(item.password)
449+
item.password = generate_password_hash(
450+
password=item.password,
451+
method=self.appbuilder.get_app.config.get(
452+
"FAB_PASSWORD_HASH_METHOD", "scrypt"
453+
),
454+
salt_length=self.appbuilder.get_app.config.get(
455+
"FAB_PASSWORD_HASH_SALT_LENGTH", 16
456+
),
457+
)
450458

451459

452460
class UserStatsChartView(DirectByChartView):

tests/test_security_api.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,15 @@ def _create_test_user(
5151
user.username = username
5252
user.email = email
5353
user.roles = roles
54-
user.password = generate_password_hash(password)
54+
user.password = generate_password_hash(
55+
password=password,
56+
method=self.appbuilder.get_app.config.get(
57+
"FAB_PASSWORD_HASH_METHOD", "scrypt"
58+
),
59+
salt_length=self.appbuilder.get_app.config.get(
60+
"FAB_PASSWORD_HASH_SALT_LENGTH", 16
61+
),
62+
)
5563
self.session.commit()
5664
return user
5765

0 commit comments

Comments
 (0)