nodejs JWT with source code

Token-based authentication: JSON Web Token (attached: Node.js project)

Using the Token-based authentication method, there is no need to store user login records on the server side. The approximate process is this:

  1. The client uses the username and password to request login
  2. The server receives the request to verify the user name and password
  3. After the verification is successful, the server will issue a Token, and then send the Token to the client
  4. After receiving the Token, the client can store it, such as in Cookie or Local Storage
  5. The client needs to bring the Token issued by the server every time it requests resources from the server
  6. The server receives the request and then verifies the token contained in the client request. If the verification is successful, it returns the requested data to the client

There are many ways to implement Token verification, and there are some standard methods, such as JWT, pronounced as: jot  , which means: JSON Web Tokens. The JWT standard Token has three parts:

  • header
  • payload (data)
  • signature

The middle is separated by a dot, and Base64 encoding is used, so the real Token looks like this:

 

eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

Header

Each JWT token has a header, which is the header data. It contains the algorithm used, whether this JWT is signed or encrypted. The main thing is to explain how to deal with this JWT token.

The content contained in the header may vary according to the type of JWT. For example, an encrypted JWT must contain the encryption algorithm used. The only thing to include in the header is   the attribute alg . If it is an encrypted JWT, the value of this attribute is the algorithm used for signature or decryption. If it is an unencrypted JWT, the value of this attribute should be set to  none .

Example:

{
  "alg": "HS256"
}

This means that the algorithm used by this JWT is HS256. The above content  has  to be encoded in the form of base64url , so it becomes like this:

eyJhbGciOiJIUzI1NiJ9

Payload

Payload contains the specific content of Token. Some of these content are standard fields. You can also add other content as needed. The following are the standard fields:

  • iss: Issuer, issuer
  • sub: Subject, subject
  • aud: Audience, audience
  • exp: Expiration time, expiration time
  • nbf:Not before
  • iat: Issued at, issue time
  • jti : JWT ID

For example, the following Payload uses the  iss  issuer and   two standard fields of exp expiration time. There are also two custom fields, one is  name  and the other is  admin  .

{
 "iss": "ninghao.net",
 "exp": "1438955445",
 "name": "wanghao",
 "admin": true
}

After using base64url encoding, it becomes like this:

eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ

Signature

The last part of JWT is Signature. There are three parts in this part. First, use Base64-encoded header.payload, then encrypt it with an encryption algorithm. When encrypting, put in a Secret. This is equivalent to a password, which is stored secretly. On the server side.

  • header
  • payload
  • secret
const encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload); 
HMACSHA256(encodedString, 'secret');

After processing, it looks like this:

SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

The last token generated on the server and sent to the client looks like this:

eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

After the client receives this Token, it will be stored, and it will be taken with it when it sends a request to the server next time. The server receives this Token, then verifies it, and after passing it, it returns the resource that the client wants.

JWT issuance and verification

To implement a Token-based authentication method based on JWT in your application, you can first find a feature package for issuing and verifying JWT. No matter what programming language, system, or framework your back-end application uses, you should be able to find packages that provide similar functionality.

Below we are in a Node.js project, in the simplest way to demonstrate the method of issuing and verifying JWT.

Project code : https://github.com/ninghao/jwt-demo

Prepare the project

Prepare a simple Node.js project:

cd ~/desktop
mkdir jwt-demo
cd jwt-demo
npm init -y

Install the function package for issuing and verifying JWT. I use  jsonwebtoken . Install this package in the project:

npm install jsonwebtoken --save

Issue JWT

Just add a .js file to the project, such as  index.js , and add the following code to the file:

const jwt = require('jsonwebtoken')

// Token data
const payload = {
  name:'wanghao',
  admin: true
}

// key
const secret = 'ILOVENINGHAO'

// Issue Token
const token = jwt.sign(payload, secret, { expiresIn: '1day' })

// Output the issued Token
console.log(token)

Very simple, just use the jwt.sign function provided in the jsonwebtoken just installed for the project to issue a token. The sign method requires three parameters:

  1. Playload : some data to be included in the issued token.
  2. secret : The key used to sign the token. This key is also needed when verifying the token.
  3. options : some other options.

Under the command line, use the  node  command to execute the  index.js  file ( node index.js ) in the project, and the token issued by the application will be output  :

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlLCJpYXQiOjE1MjkwMzM5MDYsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlLCJpYXQiOjE1MjkwMzM5MDYsImV4cCI6MTUWyOTEy78PUCIMTUq2NQN0KIO

The Token content above is not encrypted, so if you use some JWT decoding functions, you can see the content contained in the Token. The content consists of three parts, like this:

// header
{
  "alg": "HS256", 
  "typ": "JWT"
}

// payload
{
  "admin": true, 
  "iat": 1529033906, 
  "name": "wanghao", 
  "exp": 1529120306
}

// signature
DctA2QlUCrM6wLWkIO78wBVN0NLpjoIq4T5B_2WJ-PU

Assuming that the user passes some kind of authentication, you can use the Token issuance function above to issue a Token for the user. Generally, the client will save it in Cookie or LocalStorage.

The next time the user requests a protected resource from our application, he can bring the Token we issued to it in the request. The back-end application receives the request and checks the signature. If the verification passes, it is confirmed that the Token is issued by us. Then the user can respond to the resources he needs.

Verify JWT

To verify the effectiveness of the JWT, make sure that the user's JWT is issued by us. First, we must obtain the user's JWT Token, and then use the  jwt.verify  method to verify. This method is provided in the jsonwebtoken package of Node.js. In other application frameworks or systems, you may find a similar method to verify JWT.

Open the index.js file of the project and add a few lines of code:

// Verify Token
jwt.verify(token, 'bad secret', (error, decoded) => {
  if (error) {
    console.log(error.message)
    return
  }
  console.log(decoded)
})

Tell the verify  method the Token data to be verified and the key used when issuing the Token  . There are two parameters in a callback. Error  represents an error, and decoded  is the decoded Token data.

carried out:

node ~/desktop/jwt-demo/index.js

Output:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid2FuZ2hhbyIsmFkbWluIjp0cnVlLCJpYXQiOjE1MjkwMzQ3MzMsImV4cCy6o

invalid signature

Note that an invalid signature is output, indicating that the signature in the Token is incorrect. This is because  the key provided by our team leader’s  verify method is not the one used when issuing the Token. Modify it like this:

jwt.verify(token, secret, (error, decoded) => { ...

Run again, it will output similar data:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlLCJpYXQiOjE1MjkwMzUzODYsImV4cCI6MTUyOTEyMTc4Nn0.mkNrt4TfcfmP22xd3C_GQn8qnUmlB39dKT9SpIBTBGI

{ name: 'wanghao', admin: true, iat: 1529035386, exp: 1529121786 }

RS256 algorithm

The HS256 algorithm is used by default when issuing and verifying the Token. This algorithm requires a key (password). We can also use the RS256 algorithm to issue and verify JWT. This method allows us to separate issuance and verification. A key is used for issuance and a public key is used for verification. That is, where there is a public key, only verification can be done, but JWT cannot be issued.

Create a new directory under the project, which can store the key and public key files to be generated.

cd ~/desktop/jwt-demo
mkdir config
cd config

Key

First generate a key file:

ssh-keygen -t rsa -b 2048 -f private.key

Public key

Based on the key generated above, create a corresponding public key:

openssl rsa -in private.key -pubout -outform PEM -out public.key

Issue JWT (RS256 algorithm)

When using the RS256 algorithm to issue JWT, you need to read the content of the created key file from the file system.

const fs = require('fs')

// Obtain the key needed to issue JWT
const privateKey = fs.readFileSync('./config/private.key')

Signing still uses the jwt.sign method, but the algorithm used is RS256 in the option parameters:

// Issue Token
const tokenRS256 = jwt.sign(payload, privateKey, { algorithm: 'RS256' })

// Output the issued Token
console.log('RS256 algorithm:', tokenRS256)

Verify JWT (RS256 algorithm)

To verify the JWT issued using the RS256 algorithm, you need to read the contents of the public key file on the file system. Then use  jwt  's  verify  method to verify.

// Obtain the public key needed to verify the JWT
const publicKey = fs.readFileSync('./config/public.key')

// Verify Token
jwt.verify(tokenRS256, publicKey, (error, decoded) => {
  if (error) {
    console.log(error.message)
    return
  }
  console.log(decoded)
})

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/huochuangchuang/article/details/110784132