JWT is short for JSON Web token. This paper introduces its principle. Finally, how to generate token and verify token for the client using NodeJS

1. Why is session management needed

When we use NodeJS to provide resful interface for the front end or other services, HTTP protocol is a stateless protocol. Sometimes we need to obtain specific user permissions according to the request, and operate according to the context of the user. So the cookies session and the JWT are complementary to THE HTTP protocol. So that we can use HTTP protocol + state management to build a user-oriented WEB application.

2. The session and cookies

Session and cookies are related. Session is the session_ID under the cookies of the client, and the server saves all the status information of the current user corresponding to session_ID. Each time the client requests the server to bring the session_ID in the cookies, the server determines whether there is a specific user information, if not to adjust the login.

  • Cookies are insecure. Attackers can obtain local cookies for spoofing or use cookies for CSRF attacks.
  • Cookies in multiple domain names may cause cross-domain problems
  • Session information is stored on the server. When node.js deplores multiple machines in STKE, we need to solve the shared session, which leads to the problem of session persistence. Therefore, session does not support distributed architecture and horizontal expansion. Session data can only be stored in the database for sharing. An authentication failure occurs if the persistence layer fails.

3. The definition of JWT

JWT is the full name of JSON Web token, which solves the above problems of session. The advantage is that the server does not store any session data, that is, the server becomes stateless, which makes it easier to expand. When is it appropriate to use JWT? The backend is stateless, so it is widely used.

4. The principle of JWT

The JWT principle is that after the server authenticates, it generates a JSON object and sends it back to the user, as shown below.

{
  "Name": "Zhang"."Role": "Administrator"."Due Time": "0:0 on July 1, 2018."
}
Copy the code

In the future, the user will send back this JSON object when communicating with the server. The server identifies the user solely on this object. To prevent users from tampering with the data, the server generates this object with a signature.

5. JWT certification process

Process description:

  1. The browser initiates a login request with the user name and password;
  2. The server authenticates the identity to the database according to the user name and explicit code. According to the algorithm, the user identifier is packaged to generate token.
  3. The server returns the JWT information to the browser, and it is important that the JWT should not contain sensitive information
  4. The browser sends a request to obtain user information and sends the token to the server. The token is usually stored in the header and the field is authorization
  5. The server discovers the token in the data, decode the token information, and sign the token again to verify the identity.
  6. The server returns the user information for the user.
  7. The server can set the expiration time on the payload. If it expires, the server can ask the client to initiate authentication again.

6. Data structure of JWT

JWT includes use. Three parts of style

The Header in the head

{ "alg": "HS256"."typ": "JWT"}   
// algorithm => HMAC SHA256
// type => JWT
Copy the code

This is the fixed notation, alG surface to use HS256 algorithm

Payload The JWT defines seven official fields

Iss (Issuer) : exp (expiration time) : expiration time sub (subject) : aud (audience) : NBF (Not Before) : iAT (Issued At) : Issue time JTI (JWT ID) : numberCopy the code

In addition to these seven, you can customize, such as expiration time

Signature Signature

The header and payload are signed to prevent data tampering

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)
Copy the code

Secret is a string stored in the back end. Note that JWT acts as a token and may be placed in a URL (such as api.example.com/?token=xxx). Base64 has three characters +, /, and =, which have special meanings in URLS and are therefore replaced: = is omitted, + is replaced with -, and/is replaced with _. This is the Base64URL algorithm.

7. Usage of JWT

In the Authorization field of HTTP request header information, Bearer is also specified

Authorization: Bearer <token>
Copy the code

Transfer via URL (not recommended)

http://www.xxx.com/pwa?token=xxxxx
Copy the code

A POST request can also be placed in the request body

8. Use in THE KOA program

You can use off-the-shelf libraries, jwT-Simple or JsonWebToken

let Koa = require('koa');
let Router = require('koa-router');
let bodyparser = require('koa-bodyparser');
let jwt = require('jwt-simple');
let router = new Router()
let app = new Koa();
app.use(bodyparser());
// Can be customized
let secret = 'zhenglei';
// Verify login
router.post('/login'.async(ctx)=>{ 
    let {username,password} = ctx.request.body;
    if(username === 'admin' && password === 'admin') {// Check the database
       let token =  jwt.encode(username, secret);
       ctx.body = {
            code:200,
            username,
            token,
       }
    }
});
// Verify that you have permissions
router.get('/validate'.async(ctx)=>{ 
    let Authorization = ctx.get('authorization')
    let [,token] = Authorization.split(' ');
    if(token){
        try{
            let r = jwt.decode(token,secret);
            ctx.body = {
                code:200.username:r,
                token
            }
        }catch(e){
            ctx.body = {
                code:401.data:'Not logged in'}}}else{
        ctx.body = {
            code:401.data:'Not logged in'}}}); app.use(router.routes()); app.listen(4000);
Copy the code
  1. Implement two interfaces one is/loginVerify login. One is yesvalidateTo verify that you have permission
  2. When requesting the login interface, the client carries username and password, and the back-end checks the database to verify whether the current user exists. If the current user exists, the username is signed. Do not add sensitive information such as password to the signature
  3. The client receives the token from the back end and requests another interface, such as the one in this example/validateCan be specified in the header when ajax requests are madeauthorizationField. The backend retrieves the token for decode, and then signs the header and payload. If the signatures are the same, the permission verification succeeds. Because it is a synchronous process, you can use a try catch to catch errors

9. Implementation of principles

  1. Sha256 hash algorithm, can use NodeJS built-in encryption module crypto, generate base64 string, it should be noted that the generation of base64 needs to be replaced by + – =, = is omitted, + replaced by -, / replaced by _. This is the Base64URL algorithm.

  2. The token consists of header, payload, and SIGin. To form a

  3. The decoding of base64 URlunescape is fixed, and the contents of base64 are decode out

let myJwt = {
    sign(content,secret){
        let r = crypto.createHmac('sha256',secret).update(content).digest('base64');
        return this.base64urlEscape(r)
    },
    base64urlEscape(str){
        return str.replace(/\+/g.The '-').replace(/\//g.'_').replace(/=/g.' ');
    },
    toBase64(content){
        return this.base64urlEscape(Buffer.from(JSON.stringify(content)).toString('base64'))},encode(username,secret){
        let header = this.toBase64({ typ: 'JWT'.alg: 'HS256' });
        let content = this.toBase64(username);
        let sign = this.sign([header,content].join('. '),secret);
        return  [header,content,sign].join('. ')},base64urlUnescape(str) {
        str += new Array(5 - str.length % 4).join('=');
        return str.replace(/\-/g.'+').replace(/_/g.'/');
    },
    decode(token,secret){
        let [header,content,sign] = token.split('. ');
        let newSign = this.sign([header,content].join('. '),secret);
        if(sign === newSign){
            return Buffer.from(this.base64urlUnescape(content),'base64').toString();
        }else{
            throw new Error('tampered with')}}}Copy the code

10. Advantages and disadvantages of JWT

  1. JWT is not encrypted by default, but it can be. Once the original token is generated, it can be encrypted again using the modified token.
  2. When JWT is not encrypted, some private data cannot be transmitted through JWT.
  3. JWT can be used not only for authentication, but also for information exchange. Making good use of JWT helps reduce the number of server requests to the database.
  4. The biggest disadvantage of JWT is that the server does not store session state, so it is not possible to cancel tokens or change their permissions during use. That is, once issued by JWT, it will remain valid for the duration of its validity.
  5. The JWT itself contains authentication information, so anyone can gain full access to the token if the information is compromised. To reduce theft, the JWT validity period should not be set too long. For some important operations, users should authenticate each time they use it.
  6. To reduce theft and theft, JWT does not recommend using THE HTTP protocol to transfer code, but the encrypted HTTPS protocol.