egurb
egurb

Reputation: 1216

Implementation JWT based authentication without Oauth and custom token scheme

I am working on a Web API where I implemented JWT based authentication. I am not using neither PasswordJS middlware nor Oauth protocol. Its basically JWT npm which I use to sign and verify tokens.

The whole concept of token are pretty clear, but I very much confused with the term 'token scheme' and cannot understand what it is used for.

What I would like to understand is: do I need to use some sort or custom 'JWT' scheme and validate it when token is send back to server for further requests, or this concept is used only by Oauth, and what I need is only send the plain token?

var accessToken = jwt.sign({
    userID: user.id,
    isAdmin: user.isAdmin
}, config.userSecret, {
    expiresIn: 600 
});

res.json({
    success: true,
    user: {
        id: user._id,
        name: user.name,
        username: user.username,
        accessToken: 'JWT ' + accessToken, 
    }
});


jwt.verify(accessToken, secret, function(err, token){...}); //throws error when token is passed with the custom scheme

Upvotes: 0

Views: 864

Answers (1)

Mika Sundland
Mika Sundland

Reputation: 18939

Exactly what scheme you are using isn't that important in this case, because you are parsing the content of the Authorization header manually anyway.

Basically, the token is sent from the client to the server on an HTTP header called Authorization. In front of the token you put the name of the scheme. So the Authorization header might look something like this:

Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

(The list of allowed names is here. For JWT it's usually Bearer. You are technically not following the OAuth 2.0 bearer scheme according to RFC6749, but it's usually called Bearer anyway.)

You have to manually take the token (ey...) and verify it with jwt.verify() to get its payload.

const headerExists = req.headers.authorization

if (headerExists) {
  let token = req.headers.authorization.split(' ')[1];

  jwt.verify(token, auth.secretjwtkey, function (err, decoded) {
    if (err) {
      res.status(HttpStatus.UNAUTHORIZED).json('Unauthorized');
    } else if (decoded.role === 'admin') {
      next();
    } else {
      res.status(HttpStatus.UNAUTHORIZED).json('Unauthorized');
    }
  })
} else {
  res.status(HttpStatus.FORBIDDEN).json('No token');
}

You can see from the example middleware above that I don't care about the Bearer string on the Authorization header, only the token itself. You could, of course, check that it actually was Bearer and not something else though.

So the moral of the story is that:

  • You send the token from client to the server on the Authorization header. You have to set up the front-end so that happens.
  • You prepend Bearer in front of the token (or one of the other in the allowed list, but bearer is recommended).
  • You decode the token by reading the second part of the string that is on the Authorization header and then feed it to jwt.verify().

See here for more details.

Upvotes: 2

Related Questions