I recently learned about token-based authentication, and share it with everyone. Token is also used by many large sites, such as Facebook, Twitter, Google+, Github, etc. Token is more scalable and secure than traditional authentication methods, and is ideal for Web or mobile applications. Some people translate the Chinese Token as “Token”, I think it is quite good, meaning that you can pass some levels with this Token.

This article first introduces traditional authentication and JWT-BASED authentication methods, then understands the components of JWT tokens (headers, data, signatures), and finally implements JWT signing and authentication on a Node.js project. A video version of the exercise can be found in the free JWT: JSON Web Token course, and the project code is available on Github.

We have a series of token-based authentication courses, such as the implementation of this authentication method in Node.js project, or WordPress site, we also introduced the use of Token based authentication in applets to verify the identity of applets users.

After subscribing to Ninghao, you can learn all these token-based authentication courses online.

Traditional authentication methods

HTTP is a stateless protocol, meaning it does not know who is accessing the application. Here we think of the user as a client. The client is authenticated with a username and password, but the next time the client sends a request, it has to be authenticated again.

The solution is that when the user requests login, if there is no problem, we will generate a record on the server, which can explain who the user is, and then send the ID number of this record to the client, and the client will store the ID number in the Cookie after receiving it. The next time the user sends a request to the server, it can take the Cookie with it, so that the server will verify the information in the Cookie and see if it can find the corresponding record in the server. If so, it indicates that the user has passed the authentication, and the data requested by the user will be returned to the client.

We need to store sessions generated for logged-in users on the server. These sessions may be stored in memory, disk, or database. We may need to periodically clean up expired sessions on the server.

Token-based authentication methods

With token-based authentication, there is no need to store a user’s login record on the server. The general process is like this:

  1. The client requests login using the username and password
  2. The server receives a request to verify the user name and password
  3. After the authentication succeeds, the server issues a Token and sends the Token to the client
  4. After receiving the Token, the client can store it, for example, in a Cookie or Local Storage
  5. Each time a client requests resources from the server, it must carry a Token signed by the server
  6. The server receives the request and verifies the Token in the request. If the verification succeeds, it returns the requested data to the client

JWT

There are many ways to implement Token verification. There are also some standard methods, such as JWT. The JWT standard Token has three parts:

  • Header
  • Payload
  • Signature (= signature)

The dots are separated and both are Base64 encoded, so the real Token looks something like this:

eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyH TEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJcCopy the code

Header

Each JWT token has a header, which is the header data. It contains the algorithm used and whether the JWT is signed or encrypted. The main point is to explain how to handle the JWT token.

The contents of the header may vary depending on the type of JWT, such as an encrypted JWT containing the encryption algorithm used. The only thing to include in the header is

alg

This property, if it is an encrypted JWT, the value of this property is the signature used or the algorithm used for decryption. If it is an unencrypted JWT, the value of this property is set to

none

.

Example:

{
  "alg": "HS256"
}
Copy the code

This JWT uses HS256. The content above has to be base64URL encoded, so it looks like this:

eyJhbGciOiJIUzI1NiJ9
Copy the code

Payload

Payload is the specific content of the Token. Some of these things are standard fields, and you can add other things as you want. Here are the standard fields:

  • Iss: Issuer
  • Sub: Subject
  • Aud: Audience
  • Exp: Expiration time
  • Diagindex.nbf: Not before
  • Iat: Issued at
  • Jit: JWT ID

So here’s the Payload

iss

Publisher, and

exp

Expiration time are the two standard fields. There are also two custom fields, one is

name

And there’s another one

admin

.

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

Using base64URL encoding, it looks like this:

eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ
Copy the code

Signature

The last part of the JWT is the Signature, which consists of three parts. The first part is the Base64 encoded header.payload, and the second part is the encryption algorithm. This password is secretly stored on the server.

  • header

  • payload

  • secret

    const encodedString = base64UrlEncode(header) + “.” + base64UrlEncode(payload); HMACSHA256(encodedString, ‘secret’);

The process will look something like this:

SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
Copy the code

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

eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyH TEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJcCopy the code

The client receives the Token and stores it for the next time it sends a request back to the server. The server receives the Token, verifies it, and returns the desired resource to the client.

Issue and validate JWT

To implement jWT-BASED authentication in your application, you can first find a feature pack that issues and authenticates JWTS. No matter what language, system, or framework your back-end application uses, you should be able to find packages that provide similar functionality.

Here we demonstrate the simplest way to issue and validate JWT in a Node.js project. There is a video version of this exercise, and you can check out JWT: JSON Web Token, a free video course.

Project Code:

Github.com/ninghao/jwt…

Prepare project

Prepare a simple Node.js project:

cd ~/desktop
mkdir jwt-demo
cd jwt-demo
npm init -y
Copy the code

Install the JWT feature pack, which I use called

jsonwebtoken

Install this package in your project:

npm install jsonwebtoken --save
Copy the code

Issued by JWT

Add a.js file to your project, for example

index.js

Add the following code to the file:

Const JWT = require('jsonwebtoken') // Token data Const Token = jwt.sign(payload, secret, {expiresIn: '1day'}) // Output issued Token console.log(Token)Copy the code

It is very simple to issue a token using the jwt.sign functionality provided in the JsonWebToken just installed for the project. The sign method takes three arguments:

  1. playload

    : Indicates the data to be included in the issued token.

  2. secret

    : Indicates the key used to issue the token. This key is also required when authenticating the token.

  3. options

    : Some other options.

Under the command line, use

node

Command. Execute the program

index.js

This file (

node index.js

), will output the application issued

token

:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlLCJpYXQiOjE1MjkwMzM5MDYsImV4cCI6MTUyOTEyMDM wNn0.DctA2QlUCrM6wLWkIO78wBVN0NLpjoIq4T5B_2WJ-PUCopy the code

The Token content above is not encrypted, so if you use some JWT decoding, you can see what the Token contains. 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
Copy the code

Assuming the user has passed some kind of authentication, you can issue a Token to the user using the Token issuing function above. It is usually stored in a Cookie or LocalStorage on the client side.

The next time a user requests a protected resource from our application, he can take the Token we issued to him in the request. The back-end application receives the request, checks the signature, and if the verification proves that the Token is issued by ourselves, he can respond to the resource he needs for the user.

Verify the JWT

Verify the validity of JWT and make sure that the user’s JWT is issued by us. First, we need to get the user’s JWT Token and then use it

jwt.verify

So let’s verify this method. This method is provided in the Node.js jsonWebToken package, and in other application frameworks or systems, you may find similar methods to validate JWT.

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

Jwt. verify(Token, 'bad secret', (error, decoded) => { if (error) { console.log(error.message) return } console.log(decoded) })Copy the code

Tell the Token data to be verified and the key used to issue the Token

verify

This method, which takes two arguments in a callback,

error

Represents an error,

decoded

Is decoded Token data.

Perform:

node ~/desktop/jwt-demo/index.js
Copy the code

Output:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlLCJpYXQiOjE1MjkwMzQ3MzMsImV4cCI6MTUyOTEyMTE zM30.swXojmu7VimFu3BoIgAxxpmm2J05dvD0HT3yu10vuqU invalid signatureCopy the code

Note: invalid signature is output, indicating that the signature in the Token is not correct, this is because of our team leader

verify

Method provides a key other than the one used to issue the Token. Modify it like this:

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

Run it again and output similar data:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlLCJpYXQiOjE1MjkwMzUzODYsImV4cCI6MTUyOTEyMTc 4Nn0.mkNrt4TfcfmP22xd3C_GQn8qnUmlB39dKT9SpIBTBGI { name: 'wanghao', admin: true, iat: 1529035386, exp: 1529121786 }Copy the code

RS256 algorithm

The HS256 algorithm is used to issue and validate tokens by default, which requires a key (password). We can also sign and validate JWT using the RS256 algorithm. This approach allows us to separate issuance from authentication, where a key is used for issuance and a public key is used for authentication, where a public key is used for authentication but not JWT.

Create a new directory under the project where you can store the key and public key files that will be generated.

cd ~/desktop/jwt-demo
mkdir config
cd config
Copy the code

The key

Mister into a key file:

ssh-keygen -t rsa -b 2048 -f private.key
Copy the code

The public key

Create a corresponding public key based on the generated key:

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

Issue JWT (RS256 algorithm)

To issue a JWT using RS256, you need to read the contents of the created key file from the file system.

Const fs = require('fs') // Obtain JWT key const privateKey = fs.readfilesync ('./config/private.key')Copy the code

Sign still uses the jwt.sign method, but in the option parameter it is specified that RS256 is used:

// Sign Token const tokenRS256 = jwt.sign(payload, privateKey, {algorithm: 'RS256'}) // Output signed Token console.log('RS256 algorithm: ', tokenRS256)Copy the code

Verify JWT (RS256 algorithm)

Verifying JWT issued using RS256 requires reading the contents of the public key file on the file system. And then use

jwt

the

verify

Method to do the verification.

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) })Copy the code

The original link