user19187727
user19187727

Reputation: 189

Access Tokens, Refresh Tokens, And User Data

I am using a JWT authentication scheme for my app. I did some research about how to store and use access and refresh tokens, and I have several questions that I couldn't really find an answer to. For the app, I am using React for the frontend and .NET 6 Web API for the backened.

Question 1: Storing what where?
Based on the research I did, local storage is not a good place to store a jwt token for security reasons. So probably the second best alternative would be HttpOnly cookie for the jwt token and local storage for the refresh token. However I did read some articles where jwt token is stored in local storage while the refresh token is stored as HttpOnly cookie. Which approach is better, and the pros and cons of each. P.S I will be rotating the tokens, i.e a new access and refresh token will be generated once the old jwt token is refreshed. Or even store it in memory such as redux state

Question 2: When to refresh JWT Token?
Should the jwt token be refreshed just before it expires, such that the backend can verify the token, or is it fine to refresh the token after it expires (by bypassing the verificatoin when refreshing the token only i.e the refresh endpoint). Also should refreshing, be done by setting an timer/interval, or waiting for a request to fail?

Question 3: Accessing User Data and Expiry Date
I am storing some user data, such as username and password in the jwt token so I can acees them in the frontend. The problem is that when setting the jwt token as HttpOnly cookie, since Javascript can't access the token, I won't be able to access user data and the token's data(such as jti and expiry date). For the user data, I could do a seperate request to access user data such as username and email, but for the JWT token's expiry date, how could I obtain it?

I would appreciate answers to these questions or any feedback if someone faced similar issues and how you resolved them

Upvotes: 0

Views: 2942

Answers (2)

user8674632
user8674632

Reputation:

Question 1: Storing what where?

First, it is never recommended to use refresh tokens if you are not able to store them securely. Consider building a traditional web app instead.

Second, session storage is always recommended over local storage for these types of tokens.

However, I understand the problem and there are ways to get around this with “Secure SameSite Cookies” if both your apps use the same domain name. OWASP has recommendations, have a look at “token side jacking”: https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html

A simplified version below (please read OWASP recommendation and make the necessary adjustments):

During the authentication face (Web API):

  1. create a “user context”, a random string
  2. set access token with “user context”
  3. set refresh token with “user context”
  4. set http response header with a hardened cookie (flags: HttpOnly + Secure + SameSite + cookie prefixes). Value: “user context”

You need to implement validation of “user context” for API requests and for the refresh token flow; if “cookie user context” does not match “token user context”, then respond with proper http error code.

This makes it possible to:

  • store access token in session storage
  • store refresh token in local storage

Question 2: When to refresh JWT Token?

Should the jwt token be refreshed just before it expires, such that the backend can verify the token, or is it fine to refresh the token after it expires (by bypassing the verificatoin when refreshing the token only i.e the refresh endpoint).

If access token has expired then try refreshing tokens using your refresh token. If refresh token has expired, then a new authentication is needed. The definition of an expired token is that it is no longer valid and cannot be used.

Also should refreshing, be done by setting an timer/interval, or waiting for a request to fail?

Wait for the request to fail. If both access token and refresh token has expired, then a new authentication is needed.

Question 3: Accessing User Data and Expiry Date

It is not recommended to store sensitive information in access token. The access token should be opaque to the client application. Set access token with some identifier and create a /userinfo endpoint that returns information about the user. Eg, Create an authController with two actions:

/token (used for authentication)

/userinfo (used for retrieving information about the user)

Upvotes: 1

Azzy
Azzy

Reputation: 1731

Consider these as discussion rather then guideleines

Question 1: Storing what where?

  • Storing access tokens in memory is a good choice
  • But if you have a refresh token, and you need to do a silent login, local storage is the only choice
  • but you can always encrypt the token before storing

Question 2: When to refresh JWT Token?

  • if you wait for token to expire and then refresh with refresh token then existing request which failed with expired token need to be queued again.
  • if you refresh token on regular intervals, if existing token is invalidated with refreshing, then again the same issue failing requests needing to be queued again. if you are using axios, you can use libraries like axios-auth-refresh, which will queue the failed requests and try then again with a new token. you can check their source code or may be create your own version if handling failed calls is important.

Question 3: Accessing User Data and Expiry Date

  • Access token and cookies should not contain sensitive information its better to make another call to the api to get users info

Upvotes: 0

Related Questions