node.jsexpressjwttoken

Node.js JWT refresh token in express middleware


I'm trying to configure a token refresh method in my express middleware in which the token is validate at every request to the API. I will check if the token expired and if so, I will sign a new token with new exp date. The problem is that I have to send the token again, but doing that I lose the original request to send the token with the response and the API will not continue to the destination endpoint.

How I can send back the new refreshed token and continue with the request?

My express middleware to check the token:

apiRouter.use(function(req, res, next) {
      var token = req.body.token || req.query.token || req.headers['x-access-token'];
      if (token) {
        jwt.verify(token, app.get('superSecret'), function(err, decoded) {
          if (err) {
            //Here I can check if the received token in the request expired
            if(err.name == "TokenExpiredError"){
                var refreshedToken = jwt.sign({
                    success: true,
                    }, app.get('superSecret'), {
                        expiresIn: '5m'
                    });
                //Here need to send the new token back to the client and continue with the request
                //but if I use return res.... the request don't continue to next()
                next();
              }else if (err) {
                return res.json({ success: false, message: 'Failed to authenticate token.' });
              }         
          } else {
            //If no error with the token, continue 
            next();
          };
        });
      } else {
        return res.status(403).send({
            success: false,
            message: 'No token provided.'
        });
      }
    });

I don't know if it's the best approach to this.

Thank you.


Solution

  • You can not send a response to the client two times for single request, so better way will be sent an access token with the actual API response.

    apiRouter.use(function(req, res, next) {
          var token = req.body.token || req.query.token || req.headers['x-access-token'];
          if (token) {
            jwt.verify(token, app.get('superSecret'), function(err, decoded) {
              if (err) {
                //Here I can check if the received token in the request expired
                if(err.name == "TokenExpiredError"){
                    var refreshedToken = jwt.sign({
                        success: true,
                        }, app.get('superSecret'), {
                            expiresIn: '5m'
                        });
                    request.apiToken = refreshedToken;
                    next();
                  }else if (err) {
                    return res.json({ success: false, message: 'Failed to authenticate token.' });
                  }         
              } else {
                //If no error with the token, continue 
                request.apiToken = token;
                next();
              };
            });
          } else {
            return res.status(403).send({
                success: false,
                message: 'No token provided.'
            });
          }
        });
    

    then when you send a response then send a response with the token, that you can get with request.apiToken.

    but a better strategy is to provide a client refresh token and let the client make a request to get refreshed token.

    You can read more about that here