skip to Main Content

Q) When using JWT token authentication, is it correct to store the refresh token in the server’s storage (DB or Redis, etc.)?

Reason for question)

  1. I know that the advantage of JWT is that it can be used directly without having to store additional information on the server like sessions.

  2. I understand that refresh tokens are stored in more secure storage than access tokens on the client side as a precaution against access tokens being stolen, and unlike access tokens, which are often used for communication, refresh tokens are only used when the access token expires, thus minimizing the risk of being stolen.

  3. However, after searching for various documents online, I found that the refresh token is stored in the server’s storage and then retrieved and used during verification, but if this is the case, the advantages of JWT are lost, and the refresh token itself is already prepared for security, so why do I need to do it again?

I searched a lot of online documentation on Google.

2

Answers


  1. Yes, storing refresh tokens on the server-side in a secure storage solution like a database (e.g., MongoDB, PostgreSQL) or a distributed caching system (e.g., Redis) is a common and recommended practice when implementing JWT (JSON Web Token) authentication with token refresh mechanisms.

    app.post('/refresh-token', async (req, res) => {
      const refreshToken = req.body.refreshToken;
    
      // Check if the refresh token is valid and exists in the database
      const isValidRefreshToken = await RefreshToken.findOne({ token: refreshToken });
    
      if (!isValidRefreshToken) {
        return res.status(401).json({ error: 'Invalid refresh token' });
      }
    
      // Generate a new access token
      const newAccessToken = jwt.sign({ /* payload */ }, 'your-secret-key', { expiresIn: '15m' });
    
      // Respond with the new access token
      res.json({ accessToken: newAccessToken });
    });
    Login or Signup to reply.
  2. I prefer to always store the token in the client, and behavior varies depending upon the type of client.

    BROWSER BASED APP

    The refresh token is best stored in an encrypted cookie with secure properties: HttpOnly, Secure, SameSite=strict. When using JWTs the cookies can get a little large, and to counteract that it is preferred to issue refresh tokens in an opaque format, similar to a UUID.

    MOBILE APP

    This can store the refresh token in memory or in operating system secure storage private to the app, eg Android shared preferences or iOS keychain.

    DESKTOP APP

    This can store the refresh token in memory or in operating system secure storage private to the app and user, eg Windows Credential Manager, macOS keychain, Linux password and keys.

    BACKEND TOKEN STORES

    I have always avoided building my own token store in any type of app. Doing so adds complexity and can introduce new threats. A rogue employee might exploit such a store – especially for native apps, which are usually public clients and do not require a client credential when refreshing access tokens.

    AUTHORIZATION SERVERS

    These store a hash of the latest refresh token. During a refresh token grant request, the AS compares the incoming token’s hash to that value. Leaving token storage to an authorization server written by experts is a good policy I think.

    CONCURRENCY

    One of the reasons why I like to store refresh tokens in the client is reliability. Consider a React app, where 3 views call APIs concurrently. The current access token might expire and all 3 views attempt a token refresh at the same time:

    <>
      <View1 />
      <View2 />
      <View3 />
    /<>
    

    These days, refresh tokens are usually rotated on every refresh request. So for the above setup to be resilient and avoid application errors, the client must synchronize token refresh. This can be done client side but probably not server side, and I think this issue is not handled well in some website technology stacks. For further info, see this blog post of mine.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search