question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allowing multiple authentication flows in parallel (e.g., in different tabs)

See original GitHub issue

Is your feature request related to a problem? Please describe.

We currently use authlib.integrations.flask_client to authenticate users against Auth0, where they can log in via different connection types (e.g., GitHub, Google, etc.). But users sometimes initiate multiple authentication flows in parallel, as by command- or control-clicking multiple links, each of which opens in a new tab. Even if the user logs in successfully to each of those tabs, each tab (except for the most recently opened one) ultimately errs with:

authlib.integrations.base_client.errors.MismatchingStateError: 
mismatching_state: CSRF Warning! State not equal in request and response

That seems to be the result of Authlib using a single session key (e.g., _name_authlib_state_) to implement CSRF protection, per https://github.com/lepture/authlib/blob/master/authlib/integrations/flask_client/integration.py#L15-L21.

Because each tab has a new value for state, previously opened tabs’ state values are clobbered in Flask’s session.

Describe the solution you’d like

Might it make sense to use unique session keys instead so that tabs don’t share (and clobber each other’s) state? Similarly for _name_authlib_redirect_uri_ and _name_authlib_nonce_? E.g., instead of, in pseudocode,

session["_name_authlib_state_"] = "ABC"
session["_name_authlib_redirect_uri_"] = "https://example.com/callback"
session["_name_authlib_nonce_"] = "XYZ"

perhaps an approach along these lines, whereby the key includes the unique state value?

session["_name_authlib_ABC_"] = {
    "redirect_uri": "https://example.com/callback",
    "nonce": "XYZ"
}

Describe alternatives you’ve considered

Instead of authlib.integrations.flask_client, should we perhaps use requests_client.OAuth2Session instead to achieve this behavior? Would we need to validate state, redirect_uri, and nonce ourselves, though, and also validate the ID token returned from Auth0?

Is a simpler approach already possible perhaps?

Additional context

If a user opens multiple tabs because they’ve command- or control-clicked multiple links (each of which requires authentication), it’s indeed intentional that we want them to authenticate in each of those tabs (especially since their choice of connection type on Auth0’s end might differ per tab). We wouldn’t want one tab, upon encountering a MismatchingStateError, simply to check whether the user has logged in via another tab and allow the user to proceed.

Thank you!

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:18 (9 by maintainers)

github_iconTop GitHub Comments

6reactions
lepturecommented, Dec 25, 2020

This has been fixed in master branch. It will be released in v1.0.

1reaction
dmalancommented, Nov 26, 2020

@dmalan With your fix, there will be a problem for cookie based session. Because the session key is so random, we can’t clear the session properly. The cookie string will be larger and larger.

  1. End user visit the login url
  2. server will set some data into session and then redirect to GitHub, Twitter, Google etc.
  3. End user just closes the tab, he doesn’t want to authorize
  4. those data will be in session without cleanup

Definitely possible, though probably not a common case? And sounds like a job for garbage collection, no? Old keys (prefixed with, e.g., _cs50_authlib_) in session could simply be deleted after N minutes, triggered by subsequent calls into the library?

@dmalan I would suggest you create a blank login page, all login required pages will be redirect to this login page.

  1. Anonymous user visit /docs/protected-page
  2. Redirect to /account/login
  3. On /account/login there is a button, click this button to login with third party.

This might indeed decrease the probability of state being clobbered, since a user would now have to click a button in multiple tabs. But the risk would still remain, and that definitely feels like a net negative UX-wise? And cookie size could be mitigated with server-side sessions, a la https://flask-session.readthedocs.io/en/latest/?

Thank you for considering!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Authorization Code Flow - Concurrent Requests from Multiple ...
Each request will start a new session and a new Auth Code Flow, with new state param, that will be saved in this...
Read more >
What's new in Active Directory Federation Services
Example to set two different auth providers for two different applications. Application A to use Azure MFA as additional auth provider: Copy.
Read more >
Server Administration Guide - Keycloak
Service Provider Interfaces (SPI) - A number of SPIs to enable customizing various aspects of the server. Authentication flows, user ...
Read more >
Web Authentication: An API for accessing Public Key ... - W3C
Note that this is an example flow and does not limit the scope of how the API ... Other specifications mimicking the WebAuthn...
Read more >
Authenticating | Kubernetes
service account tokens for service accounts; at least one other method for user authentication. When multiple authenticator modules are enabled, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found