I saw a setup recently where frontend and resource servers were hosted on subdomains of the same second level domain. E.g. ui.example.com and api.example.com. It had an interesting authentication flow that seemed like a variant of the refresh_token oauth grant type, but using a session instead of an explicit refresh_token. I was wondering about the security implications of it, as it seemed smooth and I was considering replicating something like it for my own projects.

I'm assuming from their url structure that api.example.com was actually a gateway that routed to different services, but I don't think that's relevant to the underlying security of the thing.

The flow went something like this:

  1. user opens ui.example.com/protected
  2. ui displays a small splash screen and makes POST call to api.example.com/iam/oauth/token with a grant_type of "session"
  3. This fails as there is no session cookie present
  4. ui redirects user to ui.example.com/login
  5. ajax call is made to api.example.com/iam/passwordlogin with creds the user entered
  6. credentials are validated and a session is created. The response sets a Secure;HttpOnly;SameSite=Strict cookie with the session id.
  7. user is redirected back to ui.example.com/protected again and this time the call to api.example.com/iam/oauth/token with a grant_type of "session" succeeds, it responds with a very short-lived JWT in the response body which the UI keeps in memory and uses to call other resources on api.example.com via the Authorization header.
  8. When the ui is about to make other calls to api.example.com, for example api.example.com/myresource/, it checks the JWT in memory and if it is expired/about to expire/missing it makes another call to the api.example.com/iam/oauth/token with the grant_type of session to retrieve a new one. It stores that new one in memory and uses it to make the call.

This seems like an interesting variant on the refresh_token flow to me, using the existing session in a cookie instead of passing an explicit refresh token. It makes the process particularly smooth for the UI, while still allowing the api.example.com/iam/oauth endpoints to offer all the other grant_types needed for other kinds of clients other than the first party browser client. I'm assuming that the reason they didn't want to just pass the session token all the time was to simplify CSRF protections for the api and to allow an api to only need authentication via the Authorization header. Only the service that is accessed at api.example.com/iam/ needs to know about cookies.

I was going to replicate it for a project I'm working on, but couldn't think if there were any security considerations that hadn't already been mitigated. For example, CSRF is mitigated by it being a samesite=strict cookie for the session token. XSS is always a concern, but the access token is stored in memory on the client and very short-lived and javascript cannot access the session token.

Other than it being quite non-standard using cookies for a variant on the refresh_token grant_type, am I missing something that would make this inherently insecure and therefore not a pattern I should make use of?

2 Answers 2


This approach isn't fatally flawed as far as I can tell, but it's less secure than the refresh_token grant type.

  • According to the OAuth specification, the refresh token should be rotated after every use, so that the authorization server can detect misuse of the token at least in some cases. The scheme you describe doesn't seem to have that.
  • The specification recommends that the refresh token should be bound to a specific client through cryptography. Again, your scheme doesn't seem to implement this.
  • As you've pointed out yourself, there's a risk of CSRF attacks against the authorization server, unless you take extra steps to restrict the session cookie to the same site. The problem with this is that it isn't obvious. In typical web applications, you can have a anti-CSRF token and be fine. Now you also have to worry about the security implications of cookie settings for the authorization server.

If you fixed those problems, you would essentially re-implement the refresh_token grant type, which isn't a great idea. Major OAuth implementations have already been vetted to fix all kinds of security issues, while you'd have to start more or less from scratch.

  • Thanks for your reply. I think the refresh token rotation is an interesting one. It would be hard to implement in this case because it literally is the session token.
    – Packager
    Apr 22, 2023 at 20:24
  • The advantage of this approach is that the first party web UI has a much simpler flow to use. But maybe seen as the oauth server probably still needs to implement the other flows anyway for other clients that’s not worth it. The main attraction to me was that it makes the SPA authentication easier to handle because it is essentially just using session authentication with a special endpoint for retrieving a token. It doesn’t have to bother with oauth.
    – Packager
    Apr 22, 2023 at 20:28

The auth server api.example.com/iam/oauth/token and the resource server api.example.com/myresource/ are the same entity here so, there is no delegation of authority. The one who is giving you the resource is also the one who is authorizing you. But in most cases auth server is a separate entity and may not be on the same domain either so, cross-sharing cookies is not an option and you will need a refresh token.

Another thing is, you don't want auth server to read session cookies issued by the resource server. This can be solved by having a separate subdomain for the auth server like auth.example.com. Even if you put them under different sub-domains, the auth server cannot revoke cookies without re-implementing Oauth 2.0 Token Revocation but can revoke refresh token. So, as long as the client SPA has unexpired cookies, it can request new access token. In your flow, it is almost equivalent here to use cookies in place of refresh token.

You must log in to answer this question.

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