diff --git a/mfa/methods/totp.py b/mfa/methods/totp.py index 3d605f7..8d1240d 100644 --- a/mfa/methods/totp.py +++ b/mfa/methods/totp.py @@ -30,7 +30,8 @@ def authenticate_complete(state, user, request_data): keys = user.mfakey_set.filter(method=name) for key in keys: totp = pyotp.TOTP(key.secret) - if totp.verify(request_data) and request_data != key.last_code: + if (totp.verify(request_data, valid_window=settings.TOTP_VALID_WINDOW) + and request_data != key.last_code): key.last_code = request_data key.save() return diff --git a/mfa/settings.py b/mfa/settings.py index 27102c9..1c1c006 100644 --- a/mfa/settings.py +++ b/mfa/settings.py @@ -9,3 +9,7 @@ # Available authentication methods in order of relevance METHODS = getattr(settings, 'MFA_METHODS', ['FIDO2', 'TOTP', 'recovery']) + +# `valid_window` parameter passed to PyOTP's verify method +# See https://pyauth.github.io/pyotp/#pyotp.totp.TOTP.verify +TOTP_VALID_WINDOW = getattr(settings, 'MFA_TOTP_VALID_WINDOW', 0)