Where to store the refresh token on the Client?

Solution 1:

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.

Solution 2:

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.

Solution 3:

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.

You can set up the CORS policy correctly so that the requests to /refresh_token are accepted only from authorized servers.

If the client and server are served from the same machine, you can set the flag sameSite as true in the Cookie and include an anti-CSRF token.

Solution 4:

OAuth defines four grant types: authorization code, implicit, resource owner password credentials, and client credentials. It also provides an extension mechanism for defining additional grant types.

__ RFC 6749 - The OAuth 2.0 Authorization Framework


The Authorization Code process is inherently designed to be used with a secure client, eg. a server, that is guarded enough to hold the Client Secret within. If your client is secure enough to hold that secret, just put the Refresh Token in the same secure storage as your Client Secret.

This is not the case with applications that are hosted in User-Agent (UA). For those, the specification suggests using Implicit grant type which presents the Access Token after the Redirection URI in a fragment after # sign. Given that you are receiving the token in the User-Agent directly, it is inherently an insecure method and there is nothing you can do about it except following that User-Agent's security rules.

You may restrict the usage of your application to specific User-Agents but that can easily be tampered with. You may store your tokens in a cookie, but that also can be accessed if the UA does not respect common security norms. You can store your tokens in local storage if it is implemented and provided by the UA, yet again if it respects the norms.

The key to these implicit indirect authorizations is the trust in UA; otherwise, the safest grant type is authorization code because it requires a safely and securely stored secret on a controlled environment (application's server).

If you have no choice but using the implicit call, just go with your guts and trust the user uses a safe UA that follows security protocols; any way you are not responsible for user's poor choice of UA.