Implementation of Token authentication mechanism based on jsonwebtoken in egg

Json web token (JWT) is a JSON based development standard (RFC 7519) which is implemented for the purpose of passing statements between network application environments. The token is designed to be compact and secure, especially suitable for SSO scenarios of distributed sites. JWT declaration is generally used to transfer the authenticated user identity information between identity provider and service provider, so as to obtain resources from resource server. It can also add some additional declaration information necessary for other business logic. The token can also be directly used for authentication or encryption.

Relevant technical points

eggmiddleware
jwt official website
node-jsonwebtoken

install

npm install jsonwebtoken

Middleware programming

Create a new jwt.js file under the middleware file

'use strict'
const fs = require('fs')
const path = require('path')
const jwt = require('jsonwebtoken') //Introducing jsonwebtoken

module.exports = (options, app) => {
  return async function userInterceptor(ctx, next) {
    let authToken = ctx.header.authorization // Get authorization in header
    if (authToken) {
      authToken = authToken.substring(7)
      const res = verifyToken(authToken) // Decrypt acquired Token
      if (res.corpid && res.userid) {
        // If it is necessary to restrict the authorization of a token during single sign on or use, or change the permission of the token. That is, once the JWT is issued, it will remain in effect until it expires
        // Use redis to save here
        const redis_token = await app.redis.get('loginToken').get(res.corpid + res.userid) // Get the saved token
        if (authToken === redis_token) {
          ctx.locals.corpid = res.corpid
          ctx.locals.userid = res.userid
          await next()
        } else {
          ctx.body = { code: 50012, msg: 'Your account has been signed in elsewhere' }
        }
      } else {
        ctx.body = { code: 50012, msg: 'Login status expired' }
      }
    } else {
      ctx.body = { code: 50008, msg: 'Please log in before operation' }
    }
  }
}

// Decryption, verification
function verifyToken(token) {
  const cert = fs.readFileSync(path.join(__dirname, '../public/rsa_public_key.pem')) // Public key, see later generation method
  let res = ''
  try {
    const result = jwt.verify(token, cert, { algorithms: [ 'RS256' ] }) || {}
    const { exp } = result,
      current = Math.floor(Date.now() / 1000)
    if (current <= exp) res = result.data || {}
  } catch (e) {
    console.log(e)
  }
  return res
}

Using middleware

Add the following configuration in < label style = "color: Red" > config. Default. JS < / label > to complete the opening and configuration of middleware

// Method 1: use middleware in application
config.middleware = [ 'jwt' ]

config.jwt = {
    enable: true,
    ignore: [ '/api/v1/test/', '/public/' ], // Which requests do not require authentication
}

// Method 2: Using Middleware in router
module.exports = app => {
  const jwt = app.middleware.jwt();
  app.router.get('/api/v1/test/', jwt, app.controller.test.test);
};

token generation

It is recommended to write it in < label style = "color: Red" > helper < / label > for easy calling

loginToken(data, expires = 7200) {
  const exp = Math.floor(Date.now() / 1000) + expires
  const cert = fs.readFileSync(path.join(__dirname, '../public/rsa_private_key.pem')) // Private key, see the generation method later
  const token = jwt.sign({ data, exp }, cert, { algorithm: 'RS256' })
  return token
}

Call token generation method

const token = ctx.helper.loginToken({ corpid: usersData.corpid, userid: usersData.userid }, 7200) // token generation
await app.redis.get('loginToken').set(usersData.corpid + usersData.userid, token, 'ex', 7200) // Save to redis
ctx.body = { data: { token, expires: this.config.login_token_time }, code: 1, msg: 'Login successfully' } // Return front end

Front end use

Set authorization of headers = 'bearer' + token
< label style = "color: Red" > space after bearer < / label >

Example: axios in
// request interceptor
service.interceptors.request.use(config => {
  if (store.getters.token) {
    config.headers['Authorization'] = `Bearer ${getToken()}`
  }
  return config
}, error => {
  console.log(error)
  Promise.reject(error)
})

Using Openssl to generate private key and public key

Here's how to install git under Windows
Setting environment variables
My computer > right click > Properties > Advanced System Settings > environment variables > Path > Edit > New git path \ bin and git path \ usr\bin
For example: C:\Program Files\Git\bin and C:\Program Files\Git\usr\bin
Generate public key: openssl genrsa -out rsa_private_key.pem 1024
Generate private key: OpenSSL RSA - in RSA \ private \ key.pem - pubout - out RSA \ public \ key.pem

END

Keywords: node.js git Redis OpenSSL JSON

Added by smalband on Tue, 03 Dec 2019 21:29:16 +0200