Implementing refresh token with JWT in Node.js

In this blog we will implement solution to handle refresh token with JSON web token in Node.js

What is refresh token?
Refresh tokens are the credentials that can be used to acquire new access tokens.When current access tokens expire or become invalid, the authorization server provides refresh tokens to the client to obtain new access token.

How token based authentication works?
First user logins to the system and after successful authentication, one token is assigned to the user which is unique and bounded by some time limit. Then on each API call, the user provides the access token in order to consume the system resources. But when token time expires, the user has to login again. This is little bit frustrating, we can not ask user to login every time when token expires.

To avoid this we can do two things, first is we can increase expiration token time
second is we can use JWT refresh token to generate new token. We will see second one.

Create refresh token

  • It is the same as how we create access token by using payload (user's data), secret key and token expiry. Here only difference is there will be no expiry for refresh token as we are going use that to generate new token. In order to do this we will store refresh token with user data in database.
  • Whenever user authenticate with login credentials we will check if user has refresh token or not. If there is a refresh token for that user authorization server will send refresh token with access token or if there is no refresh token for user we will generate new one by using user data and secret key with JWT and then after we will send along with access token. Here we have used feathersjs authentication.
var jwt = require('jsonwebtoken');

const setRefreshToken = async (context) => {
  const { params, app } = context;
  const { user } = params;
  const secret = app.get('authentication').secret;
  if (user.refresh_token) {
    context.result.refresh_token = user.refresh_token;
  } else {
    let refresh_token = jwt.sign({ userId: user.id }, secret);
    user.refresh_token = refresh_token;
    await user.save();
    context.result.refresh_token = refresh_token;
  }
  return Promise.resolve(context);
};

module.exports = setRefreshToken;

app.service('authentication').hooks({
    before: {
      create: [
        authentication.hooks.authenticate(['local', 'jwt', 'custom']),
        context => {
          context.params.payload = context.params.payload || {};
          Object.assign(context.params.payload, { userId: context.params.user.id });
        }
      ],
      remove: [
        authentication.hooks.authenticate('custom')
      ]
    },
    after: {
      create: [
        setRefreshToken
      ]
    }
  });
  • So next time when the access token expires the client will again make a request with a refresh token as authentication credentials. Authorization server will validate the refresh token and after validating if token is valid then it will respond with new access token.