My web app (the OAuth2 client) authorizes users by making a request to a separate authorization server using the OAuth2 framework. For each user login my app generates a state value which is eventually validated against the Authorization Response.
My problem is that users are bookmarking the page for the Authorization Server as a shortcut to get into my web app, since that's where the credentials are entered. The Authorization server is happy to handle this as a "new" request, however The state on the bookmarked request is no longer valid in my app since it no longer correlates to a request originated in my app. My app is currently producing an error message, despite a perfectly-valid verification of credentials, which is very upsetting to users.
I've researched how this is done for other apps and noticed a difference. For some sites this is not a problem (like Stack Overflow!), but other sites, like Auth0, produce an error message:
You may have pressed the back button, refreshed during login, opened too many login dialogs, or there is some issue with cookies, since we couldn't find your session. Try logging in again from the application and if the problem persists please contact the administrator.
My product manager wants me to implement the "Stack Overflow behavior", and accept the login in order to have a better user experience; but my inclination is that Auth0 is actually more secure in making sure that the request originated from my app.
My question is what is the correct way to handle this, hopefully satisfying both the security needs and the usability needs. In other words, assuming that Stack Overflow is not being insecure, how does it work that is different than how Auth0 is working?
Update: Stack Overflow technical support has responded:
Our dev has looked this over and really appreciate the report! The “state” that we pass to OAuth2 endpoints is validated and is not perpetually re-useable - bookmarking it will only work for an hour before the state is considered invalid. In addition, it’s nontrivial to get hold of one of these URLs unless the user’s machine/browser is compromised or the HTTPS connection is compromised allowing a MITM attack - the risk of CSRF here is very low.
That said, we’re going to make a change here to ensure the state is single-use only to remove any cause for doubt. I don’t have an ETA for the fix, but I’ll leave this ticket open until we do.