Is it considered safe to store a refresh_token in a cookie if the cookie is marked HTTP-only and is only transmitted over HTTPS?
We are creating a solution with a frontend SPA (VueJS) and the backend is Asp.Net Core. Every page in the solution is provided trough the Vue-SPA. The initial first-page is served up with a simple controller action with Asp.Net Core. The loginpage is served up with Vue, using vue-router. Based on if there is an access_token present in the local storage or not the user is considered logged in. When this access_token expires or is invalid, we want to use a refresh token to get a new access token. What we ended up doing was storing the refresh_token in a cookie that is sent back to the “DotNet Core Backend” when asking for a new access token. Here is a description of how the application works:
The loginpage POST the username and password to the backend API
The controller-action uses the Auth0-Authentication nuget-package and authenticates the user, adding the offline_access-scope. If success it adds the users auth0id and the refresh_token to the users claims. The cookie-path is set to ‘/account’, so it is only sent to the server when accessing something under the ‘/account’-path. The action method sets the cookie and returns a 200 OK with an access_token.
Now the Vue-client stores the access_token in localstorage and the user is logged in.
Whenever the Vue-client accesses the backend API we set the access_token (Bearer token) and the API receives the token and does its thing. And we see that the cookie is not sent when the path is ‘/api’-something.
When the token expires we intercept the 401 and do a GET on ‘/account/accessToken’. Now on we see that the cookie is sent to the server, and on the server we can find the refresh_token in the users claims. Again, using the Auth0-Authentication nuget-package we can ask for a new access token providing the refresh token. If the refresh_token is not revoked, we get a new access_token and returns that to the client, and the client retries the initial request with the new access token.
If we serverside see that the refresh_token is invalid (ex. has been revoked) we wipe the cookie, and redirect the user to the loginpage, and the user will have to sign in again.
With this solution we can customize the loginpage as we want, the user stays on our domain, in comparison to when using the hosted loginpage. We have also found a way to re-authenticate users without using the hosted loginpage and the renewAuth-method with the silent callback.
Since we are talking about security here, I would like to get some feedback and thoughts from someone more seasoned in security than myself.
Is this considered a safe and viable solution? Are there any security issues to be aware of?
Thanks to Auth0 for a great product.