-
Notifications
You must be signed in to change notification settings - Fork 92
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
Auth0 state parameter not always passed through #73
Comments
The state parameter is not meant to work across multiple browser tabs. |
I think you've mis-understood this. I don't want the state parameter to be shared between browser tabs, I want the state parameter not to be affected by multiple parallel requests. |
Sorry for the fast reply. We've been a bit behind on issue here so I wasn't sure if it was still relevant. I haven't looked in-depth here but the reason this typically fails is that a second long request overwrites the state value from the first login request, causing a mismatch. Can you help me understand what the use case is for what you are describing here? This doesn't sound like something that a user would typically do or something we need to investigate a fix for. Thank you! |
When you load a web page in iOS safari, sometimes it pre-emptively requests some of the URLs you've requested previously for the same page. This seems to happen especially when the app is listed as a standalone app. If both requests require authentication, they both redirect to auth0. When the requests complete authentication (often transparent due to SSO) one has the correct state parameter and the other does not. Whether or not you think this is a common use case (for us it is critical, but maybe we're unique), it is a bug and suggests some pretty lax attention to detail in the code. The state parameter should not be global, it should belong to the individual request, and the fact that the two requests interact in this way makes me seriously doubt that the implementation is robust and secure. |
I think we can work through your issue together without statements like this. What I'm not understanding here is why you would need to initiate two parallel login requests for the same application in the same browser. The state is not "global," it's tied to your login request but the login request is tied to your browser. I'm not sure why allowing login to happen twice is critical but it's certainly possible that I'm missing something specific to your implementation. It's worth it to note that state storage and checking is handled entirely within Passport.js. The only thing we do with state is ensure that it's used if not indicated otherwise. If you can share the code for your complete login and callback routes (with anything sensitive redacted), I'd be happy to take a look and see if something jumps out at me. I think I have something mis-configured in my session handling as I'm not able to pass anything in with |
The point is that I'm not able to prevent the browser making two parallel requests to restricted resources, I either have to redirect both of them through the auth flow, or reject one of them as access denied. The bug I'm reporting isn't specifically in passport, but I couldn't find anywhere else to report it to auth0. The problem is auth0's OAuth implementation that should always pass through the state parameter, which should be tied to the individual authentication flow, not the user's browser in general. |
Just to make sure we're on the same page, since I'm still not totally clear what we can do to address this. When the strategy is instantiated, you can turn state on: var strategy = new Auth0Strategy(
{
domain: process.env.AUTH0_DOMAIN,
clientID: process.env.AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
callbackURL: process.env.AUTH0_CALLBACK_URL,
state: true
},
function (accessToken, refreshToken, extraParams, profile, done) {
// ...
return done(null, profile);
}
); ... and the state will be generated, stored, passed, and validated automatically. If you leave With state on, the expected (and confirmed) behavior is:
You can pass in var strategy = new Auth0Strategy(
{
domain: process.env.AUTH0_DOMAIN,
clientID: process.env.AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
callbackURL: process.env.AUTH0_CALLBACK_URL,
state: false
},
function (accessToken, refreshToken, extraParams, profile, done) {
// ...
return done(null, profile);
}
); ... and steps 4 and 6 above will succeed, instead of throwing an error. This is all default Passport behavior, except for As for a custom state ... I'm not able to get Passport to use that no matter what I do. Can you share the code you're using to set that? Any way I look at it ... where and how the state is stored is managed by Passport so I'm still not clear how this is a bug or problem with our OAuth implementation. I absolutely could be wrong but, at this point, I'm not seeing it. I'm not even sure how you would be able to store and verify a state value for an auth process in a specific tab. |
If you set the state manually, e.g.
passport.authenticate('auth0', {state: 'some_state})
and then log in twice in parallel, the first request will correctly get the state passed through. The subsequent requests will all get a new random looking string, something like:g6Fo2SBZNjR2SndFQkZGQVAxS0s2MFVfVUxXQVB0MkNSdjRia6N0aWTZMmdhRm8yU0JOTTNWUlJtZEZVVFpqYVdKdlZWSTNVRmg1TTBSSmNWUTBMVU5qY0dVMFVno2NpZNkgcURNVUtTWkk5M0JlaVpJQ1A2RVZ0bk9tMUt4YTJDZlM
The specific steps to reproduce are:
The text was updated successfully, but these errors were encountered: