Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mfa timeout function needs non-anonymous user #3816

Open
half-of-a-glazier opened this issue May 15, 2024 · 5 comments
Open

Mfa timeout function needs non-anonymous user #3816

half-of-a-glazier opened this issue May 15, 2024 · 5 comments

Comments

@half-of-a-glazier
Copy link
Contributor

I'm trying to set a timeout between initial login and mfa.
This function in allauth.account.reauthentication that looks like it's intended for this:

def did_recently_authenticate(request):
    if request.user.is_anonymous:
        return False
    if not get_adapter().get_reauthentication_methods(request.user):
        # TODO: This user only has social accounts attached. Now, ideally, you
        # would want to reauthenticate over at the social account provider. For
        # now, this is not implemented. Although definitely suboptimal, this
        # method is currently used for reauthentication checks over at MFA, and,
        # users that delegate the security of their account to an external
        # provider like Google typically use MFA over there anyway.
        return True
    authenticated_at = request.session.get(AUTHENTICATED_AT_SESSION_KEY)
    if not authenticated_at:
        return False
    return time.time() - authenticated_at < app_settings.REAUTHENTICATION_TIMEOUT`

I overrode AuthenticateView and implemented did_recently_authenticate to add the timeout check before proceeding with the mfa validation. But since the user is anonymous even after the first stage of login, the function returns False before any of the logic is run.

Is the user supposed to be anonymous? Is it better to use request.session.get(AUTHENTICATION_METHODS_SESSION_KEY, []) and calculate the timeout from the last login? Do I need to create custom logic or is this feature included in allauth?

@pennersr
Copy link
Owner

Is the user supposed to be anonymous?

Yes. If you have not passed all checks (email verification if mandatory, 2FA if enabled, ...) request.user remains an anonymous user. That is done intentionally -- it would be really insecure if that would not be the case, as any third-party code typically checks for request.user.is_authenticated and assumes that is sufficient, which is not the case.

I must admit, I don't fully understand what you are trying to accomplish:

set a timeout between initial login and mfa

This is not clear to me.

@half-of-a-glazier
Copy link
Contributor Author

When the mfa form is filled out it should check how long ago the login form was submitted. If it's longer than x seconds, it should timeout and restart the login process.

@pennersr
Copy link
Owner

What's the difference with what you are aiming for, versus what settings.ACCOUNT_REAUTHENTICATION_TIMEOUT is already doing?

@half-of-a-glazier
Copy link
Contributor Author

ACCOUNT_REAUTHENTICATION_TIMEOUT (default: 300)
Before asking the user to reauthenticate, we check if a successful (re)authentication happened within the amount of seconds specified here, and if that is the case, the new reauthentication flow is silently skipped.

This is what should happen:

  1. User is logged out
  2. User submits the login form with username/password and is redirected to mfa form
  3. User waits 5 minutes
  4. User submits mfa form
  5. Since 5 minutes is longer than the mfa-timeout limit, user is redirected to login stage 1.

settings.ACCOUNT_REAUTHENTICATION_TIMEOUT doesn't enforce this timeout because the user hasn't completed a successful authentication yet.

@pennersr
Copy link
Owner

I see. In that case:

This function in allauth.account.reauthentication that looks like it's intended for this:

It's not -- the user did not (fully) authenticate yet, so reauthentication is not applicable. In order to support this, I think a general mechanism is needed to add timeouts to class LoginStage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants