You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This can happen if the user clicks many times on a button or link that triggers authorization, if they open said links in many different tabs, or if silent authentication on render is implemented and the user reloads a page many times.
State is always saved in session as a string, always under a fixed key. That means that if a second auth request is made before the callback for a first request has been received, the state for the first request is overwritten and when it's callback eventually is received, it fails with the csrf error because of the missing first state.
Possible solutions
I can think of two approaches to address this:
Define session['omniauth.state'] as an array. That way, new_state would push to it, and stored_state would find, delete and return the state if it's present in the array.
Use the state as key instead of value of the session stored state. That would also prevent collision/overwrite of stage, and it would also allow saving of other related state if you wanted (like a return_url to be used after a successful callback for example). This seems to be the approach used/recommenbed by Auth0, as seen in their documentation and in their Client Side SDK:
I think the first approach is a bit simpler, but the second one comes with the added benefit of being able to associate a payload with the state, and the auth request by proxy, I don't know if that is something that would be of interest to this project.
The text was updated successfully, but these errors were encountered:
difernandez
changed the title
Possible race condition with multiple authorization requests
Possible race condition with multiple authorization requests causes CSRF error
Feb 5, 2025
Description
When multiple authorize requests are made in quick succession, some times a CSRF error appears:
This can happen if the user clicks many times on a button or link that triggers authorization, if they open said links in many different tabs, or if silent authentication on render is implemented and the user reloads a page many times.
As far as I can tell, the problem comes from how the state is saved to storage:
State is always saved in
session
as a string, always under a fixed key. That means that if a second auth request is made before the callback for a first request has been received, the state for the first request is overwritten and when it's callback eventually is received, it fails with the csrf error because of the missing first state.Possible solutions
I can think of two approaches to address this:
session['omniauth.state']
as an array. That way,new_state
would push to it, andstored_state
would find, delete and return the state if it's present in the array.state
as key instead of value of the session stored state. That would also prevent collision/overwrite of stage, and it would also allow saving of other related state if you wanted (like areturn_url
to be used after a successful callback for example). This seems to be the approach used/recommenbed by Auth0, as seen in their documentation and in their Client Side SDK:I think the first approach is a bit simpler, but the second one comes with the added benefit of being able to associate a payload with the
state
, and the auth request by proxy, I don't know if that is something that would be of interest to this project.The text was updated successfully, but these errors were encountered: