Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to store the refresh token on the Client?

My SPA application uses the following architecture (source):

enter image description here

This assumes that my client application knows about the refresh token, because I need it to request a new access token if no user credentials (e.g. email/password) are present.

My question: Where do I store the refresh token in my client-side application? There are lots of questions/answers about this topic on SO, but regarding the refresh token the answer are not clear.

Access token and refresh token shouldn't be stored in the local/session storage, because they are not a place for any sensitive data. Hence I would store the access token in a httpOnly cookie (even though there is CSRF) and I need it for most of my requests to the Resource Server anyway.

But what about the refresh token? I cannot store it in a cookie, because (1) it would be send with every request to my Resource Server as well which makes it vulnerable to CSRF too and (2) it would send expose both access/refresh token with an identical attack vector.

There are three solutions I could think of:


1) Storing the refresh token in an in-memory JavaScript variable, which has two drawbacks:

  • a) It's vulnerable to XSS (but may be not as obvious as local/session storage
  • b) It looses the "session" if a user closes the browser tab

Especially the latter drawback makes will turn out as a bad UX.


2) Storing the access token in session storage and sending it via a Bearer access_token authorization header to my resource server. Then I can use httpOnly cookies for the refresh token. This has one drawback that I can think of:

  • a) The refresh token is exposed to CSRF with every request made to the Resource Server.

3) Keep both tokens in httpOnly cookies which has the mentioned drawback that both tokens are exposed to the same attack vector.


Maybe there is another way or more than my mentioned drawbacks (please let me know), but in the end everything boils down to where do I keep my refresh token on the client-side? Is it httpOnly cookie or an in-memory JS variable? If it is the former, where do I put my access token then?

Would be super happy to get any clues about how to do this the best way from people who are familiar with the topic.

like image 846
Robin Wieruch Avatar asked Aug 26 '19 00:08

Robin Wieruch


People also ask

Where should I store the refresh token?

You Can Store Refresh Token In Local Storage Storing tokens in browser local storage provides persistence across page refreshes and browser tabs; however, if malicious users managed to run JavaScript in the SPA using a cross-site scripting (XSS) attack, they could retrieve the tokens stored in local storage.

Should we store refresh token database?

Do not store or use OAuth access tokens or refresh tokens on web or mobile clients. OAuth access tokens and refresh tokens should be encrypted and stored in a secure database. Your application should use a strong encryption standard such as AES.

How do I refresh my client token?

To use the refresh token, make a POST request to the service's token endpoint with grant_type=refresh_token , and include the refresh token as well as the client credentials if required.

Where are OAuth access tokens stored?

Tokens received from OAuth providers are stored in a Client Access Token Store. You can configure client access token stores under the Libraries > OAuth2 Stores node in the Policy Studio tree view.


2 Answers

You can store encrypted tokens securely in HttpOnly cookies.

https://medium.com/@sadnub/simple-and-secure-api-authentication-for-spas-e46bcea592ad

If you worry about long-living Refresh Token. You can skip storing it and not use it at all. Just keep Access Token in memory and do silent sign-in when Access Token expires.

Don't use Implicit flow because it's obsolete.

The most secure way of authentication for SPA is Authorization Code with PKCE.

In general, it's better to use existing libraries based on oidc-client than building something on your own.

like image 199
Vlad DX Avatar answered Oct 13 '22 01:10

Vlad DX


You can store both tokens, access and refresh, as cookie. But refresh token must have special path (e.g. /refresh). So refresh token will be sent only for request to /refresh url, not for every request like access token.

like image 42
yaches Avatar answered Oct 13 '22 01:10

yaches