Passport is commonly used for Token authentication on Node.js. It can customize the verification policy, but if you are using the Express framework and are parsing simple requirements like JWT, express-JWT can be used instead.

About the JWT

JWT is a solution to replace the traditional session authentication. The idea is that the server generates a JSON object containing the user’s unique identity and issues it to the client. When a client requests an interface that requires permissions, it simply sends the JSON back to the server as it is, and the server can parse it to identify the user.

It usually looks like this:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJ SMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cCopy the code

The JSON object is divided into three segments via. And contains the request header (encryption algorithm), payload information (such as userId, expiration time), and the signature generated by the server key to ensure it is not tampered with.

This mechanism eliminates the need for servers to store tokens and is therefore a very lightweight user authentication scheme. In addition, JWT is currently the first choice for cross-domain authentication of micro-services, which requires Token sharing between different services.

About the express – JWT

Express-jwt is an open source library for Node.js, developed by ID authentication service provider Auth0. Express-jwt is a middleware specifically designed to parse JWT under the Express framework.

It is very simple to use, and automatically assigns the payload part of the JWT to req.user, so that the logical part can be called easily.

Begin to use

The installation

npm install express-jwt
Copy the code

Join middleware

const expressJwt = require('express-jwt')

app.use(expressJwt({
  secret: 'secret12345'  // Signature key or PublicKey
}).unless({
  path: ['/login'.'/signup']  // The specified path does not pass Token resolution
}))
Copy the code

To generate the Token

The Token generation method still uses jsonWebToken, such as adding the following code to the return part of the login interface:

const jwt = require('jsonwebtoken')

app.post('/login'.function (req, res) {
  // Note that the default Token must start with Bearer+ space
  const token = 'Bearer ' + jwt.sign(
    {
      _id: user._id,
      admin: user.role === 'admin'
    },
    'secret12345',
    {
      expiresIn: 3600 * 24 * 3
    }
  )
  res.json({
    status: 'ok'.data: { token: token }
  })
})
Copy the code

Get parsed content

When a Token request is received and resolved successfully, it can be accessed via req.user in the route callback:

app.get('/protected'.function (req, res) {
  if(! req.user.admin)return res.sendStatus(401)
  res.sendStatus(200)})Copy the code

Req. user is actually the payload portion of the JWT:

{
  _id: '5dbbc7daaf7dfe003680ba39'.admin: true.iat: 1572587484.exp: 1573192284
}
Copy the code

Parse failure

If parsing fails, an UnauthorizedError is raised, which can be captured by the backend middleware:

app.use(function (err, req, res, next) {
  if (err.name === 'UnauthorizedError') {   
    res.status(401).send('invalid token')}})Copy the code

Modify result field

The default parse result is assigned to req.user, which can also be changed by requestProperty:

app.use(expressJwt({
  secret: 'secret12345'.requestProperty: 'auth'
}))
Copy the code

Tokenless requests are allowed

When the interface allows access to both tokenless and tokenless states (such as post details login for a thumbs up), tokenless requests can be resolved and exceptions can be thrown by credentialsRequired: False.

app.use(expressJwt({
  secret: 'secret12345'.credentialsRequired: false
}))
Copy the code

Custom parsing

By default, Express-JWT retrieves the Token from the Authorization field of the Headers request and resolves it.

GetToken also allows you to customize some of the parsing logic, such as using other Header fields and custom exceptions:

app.use(expressJwt({
  secret: 'secret12345'.credentialsRequired: false.getToken: function fromHeaderOrQuerystring (req) {
    if (req.headers.authorization && req.headers.authorization.split(' ') [0= = ='Bearer') {
      return req.headers.authorization.split(' ') [1]}else if (req.query && req.query.token) {
      return req.query.token
    }
    return null}}))Copy the code

Revocation of Token

In JWT, since tokens are not usually stored, revoking a Token is usually done in a passive manner.

A common way to do this is to create a blacklist of fields (such as TokenId) and filter all tokens. Express-jwt specifically provides callbacks to handle this situation:

const expressJwt = require('express-jwt')
const blacklist = require('./blacklist')

let isRevokedCallback = function(req, payload, done){
  let issuer = payload.iss
  let tokenId = payload.jti

  blacklist.getRevokedToken(issuer, tokenId, function(err, token){
    if (err) { return done(err) }
    return done(null,!!!!! token)// If the second argument is true, it will not pass
  })
}

app.use(expressJwt({
  secret: 'secret12345'.isRevoked: isRevokedCallback
}))
Copy the code

See the official documentation for more usage


This article belongs to the original content, first published in the wechat public account “life oriented programming”, if you need to reprint, please leave a message in the public account background.