0

I have implemented OAuth2 for a web app. Everything is stored in the session, and I am switching this to a database. This makes sense for the subject and roles, but it also includes the temporary values like state and the redirect uri that are only required during the OAuth process. Does it make sense to use a db for those? I don't know sessions well enough to know if it is guaranteed to keep the same session during a response.redirect. It seems possible the browser submits the redirect request and the load balancer sends the request to a different server than where we started, in which case the session data won't be there and we'll need the database to get state, etc. I've read a lot of articles and questions on this topic but they don't quite answer me.

Edit: The OAuth flow:

  1. Client (browser) tries to access webapp resource (eg. /resource)
  2. Webapp sends redirect back to browser and browser redirects to OAuth authorization server to retrieve authorization code
  3. OAuth server tells browser to redirect back to the webapp with code
  4. Webapp exchanges auth code for token
  5. ... more stuff

In step 2, the webapp needs to save a random "state" string and the original uri the client wanted to access (/resource). The state is included in the redirect to the authorization server. In step 3, the auth server includes the state value in the request to the webapp. The webapp verifies the state is the same one it saved in step 2. After all these steps complete, the webapp finally serves the originally requested resource (/resource). I am wondering how state and original resource / uri are saved in a typical oauth flow. These are only needed during the authentication.

4
  • Welcome to the community. Name exactly what you would store in the DB and why. Then we can analyze it Feb 23 at 16:58
  • Sure thing. I added additional information.
    – Ryan
    Feb 23 at 19:04
  • It's similar to PKCE. I don't understand sessions very well. If I have several servers running, it seems possible that the user will be redirected to a different server on every request, meaning the session information won't be there. In that case the session var is out, right?
    – Ryan
    Feb 23 at 19:42
  • You'll probably want to use a DB entry. (I guess you've got a reverse proxy/load balancer?) Feb 23 at 21:19

1 Answer 1

1

As an alternative to storing the state in a database on the server, you can also write it into a "relay state cookie" and send it back to the user agent. The response that the web app sends in step 2 would then look like

HTTP/1.1 302 Found
Set-Cookie: relay_state_<xxx>=GET%20/resource; Expires=<in 5 minutes>
Location: https://authorization.server/authorize?scope=...&state=<xxx>

where <xxx> stands for the "random state string".

In step 3, when the user agent receives the authorization code, it includes the relay state cookie in the request to the web app (because the same-site behavior of the cookie is "lax"):

GET /callback?code=<authorization code>&state=<xxx> HTTP/1.1
Cookie: relay_state_<xxx>=GET%20/resource

and after the web app has exchanged the authorization code for an access token (step 4) and issued a session cookie, it can redirect the user agent back to the URL from the relay state cookie:

HTTP/1.1 302 Found
Set-Cookie: relay_state_<xxx>=; Expires=Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: web_app_session=...; HttpOnly
Location: /resource

With the redirection to the resource, the relay state cookie is deleted again. If it does not come to that (for example, no valid authorization code was issued), the cookie expires after 5 minutes.

Variants of this technique are necessary if the relay state consists of a POST rather than a GET request, or if the fragment part of the /resource#section4 URL shall also be preserved.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .