Skip to content

Commit 96d9d07

Browse files
committed
Introduce totp_enabled_for_admin config option
1 parent 965708f commit 96d9d07

File tree

2 files changed

+28
-5
lines changed

2 files changed

+28
-5
lines changed

schemas/qwc-db-auth.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@
116116
"description": "Enable two factor authentication using TOTP. Default: false",
117117
"type": "boolean"
118118
},
119+
"totp_enabled_for_admin": {
120+
"description": "Whether to enable two-factor authentication using TOTP for admin. Default: false",
121+
"type": "boolean"
122+
},
119123
"totp_issuer_name": {
120124
"description": "Issuer name for QR code URI. Default: 'QWC Services'",
121125
"type": "string"

src/db_auth.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ def __init__(self, tenant, mail, app):
9090
self.post_param_login = config.get('post_param_login', False)
9191
self.max_login_attempts = config.get('max_login_attempts', 20)
9292
self.totp_enabled = config.get('totp_enabled', False)
93+
self.totp_enabled_for_admin = config.get('totp_enabled_for_admin', False)
9394
self.totp_issuer_name = config.get('totp_issuer_name', 'QWC Services')
9495

9596
db_engine = DatabaseEngine()
@@ -200,7 +201,7 @@ def login(self):
200201
# add initial password history entry if missing
201202
self.create_password_history(db_session, user)
202203

203-
if self.totp_enabled:
204+
if self.__totp_is_enabled(user):
204205
session['login_uid'] = user.id
205206
session['target_url'] = target_url
206207
if user.totp_secret:
@@ -254,6 +255,12 @@ def verify_login(self):
254255
abort(401)
255256
abort(401)
256257

258+
def __totp_is_enabled(self, user):
259+
""" Returns whether totp is enabled for the specified user
260+
:param user User: The user
261+
"""
262+
return self.totp_enabled or (user and user.name == self.DEFAULT_ADMIN_USER and self.totp_enabled_for_admin)
263+
257264
def verify(self):
258265
"""Handle submit of form for TOTP verification token."""
259266
# create session for ConfigDB
@@ -267,7 +274,7 @@ def __verify(self, db_session, submit=True):
267274
:param bool submit: Whether form was submitted
268275
(False if shown after login form)
269276
"""
270-
if not self.totp_enabled or 'login_uid' not in session:
277+
if 'login_uid' not in session:
271278
self.logger.warning("TOTP not enabled or not in login process")
272279
return redirect(url_for('login'))
273280

@@ -276,6 +283,10 @@ def __verify(self, db_session, submit=True):
276283
self.logger.warning("user not found")
277284
return redirect(url_for('login'))
278285

286+
if not self.__totp_is_enabled(user):
287+
self.logger.warning("TOTP not enabled or not in login process")
288+
return redirect(url_for('login'))
289+
279290
form = VerifyForm(meta=wft_locales())
280291
form.logo = self.login_logo
281292
form.background = self.login_background
@@ -323,7 +334,7 @@ def __setup_totp(self, db_session, submit=True):
323334
:param bool submit: Whether form was submitted
324335
(False if shown after login form)
325336
"""
326-
if not self.totp_enabled or 'login_uid' not in session:
337+
if 'login_uid' not in session:
327338
self.logger.warning("TOTP not enabled or not in login process")
328339
return redirect(url_for('login'))
329340

@@ -332,6 +343,10 @@ def __setup_totp(self, db_session, submit=True):
332343
# user not found
333344
return redirect(url_for('login'))
334345

346+
if not self.__totp_is_enabled(user):
347+
self.logger.warning("TOTP not enabled or not in login process")
348+
return redirect(url_for('login'))
349+
335350
totp_secret = session.get('totp_secret', None)
336351
if totp_secret is None:
337352
# generate new secret
@@ -386,7 +401,7 @@ def __setup_totp(self, db_session, submit=True):
386401

387402
def qrcode(self):
388403
"""Return TOTP QR code."""
389-
if not self.totp_enabled or 'login_uid' not in session:
404+
if 'login_uid' not in session:
390405
self.logger.warning("TOTP not enabled or not in login process")
391406
abort(404)
392407

@@ -412,6 +427,10 @@ def qrcode(self):
412427
# user not found
413428
abort(404)
414429

430+
if not self.__totp_is_enabled(user):
431+
self.logger.warning("TOTP not enabled or not in login process")
432+
return redirect(url_for('login'))
433+
415434
# generate TOTP URI
416435
email = user.email or user.name
417436
uri = pyotp.totp.TOTP(totp_secret).provisioning_uri(
@@ -687,7 +706,7 @@ def __user_is_authorized(self, user, password):
687706
elif user.check_password(password):
688707
# valid credentials
689708
if user.failed_sign_in_count < self.max_login_attempts:
690-
if not self.totp_enabled:
709+
if not self.__totp_is_enabled(user):
691710
# update last sign in timestamp and reset failed attempts
692711
# counter
693712
user.last_sign_in_at = datetime.datetime.now(datetime.UTC)

0 commit comments

Comments
 (0)