JWT authentication

Json Web Token

The essence of JWT is a string. It saves user information into a Json string, and then encodes it to get a JWT token. The JWT token has signature information. After receiving, it can verify whether it has been tampered with. Therefore, it can be used to safely transmit information as a Json object between all parties

At present, JWT token is more recommended for user authentication in both single and distributed applications

Process of user authentication using token

1. The client requests login with user name and password
2. The server receives the request and verifies the user name and password
3. After successful verification, the server will issue a token and return the token to the client
4. After receiving the token, the client can store it, for example, in a cookie
5. Each time the client requests resources from the server, it needs to carry the token issued by the server, which can be carried in the cookie or header
6. The server receives the request, and then verifies the token carried in the client request. If the verification is successful, it returns the request data to the client

JWT certification process

1. The front end sends its user name and password to the back-end interface through a Web form. This process is generally a POST request. The recommended method is SSL encrypted transmission (HTTPS), so as to avoid sensitive information being sniffed
2. After checking the user name and password successfully, the back-end takes the data containing user information as the Payload of JWT, performs Base64 coding and splicing with JWT Header respectively, and then signs to form a JWT Token. The formed JWT Token is a string like lll.zzz.xxx
3. The back end returns the JWT Token string to the front end as the result of successful login. The front end can save the returned results in the browser and delete the saved JWT Token when logging out
4. The front end puts the JWT Token into the Authorization attribute in the HTTP request header every time the request is made (solve the XSS and XSRF problems)
5. The back end checks the JWT Token passed from the front end to verify its validity, such as checking whether the signature is correct, whether it has expired, whether the receiver of the token is itself, etc
6. After the verification is passed, the back end parses the user information contained in the JWT Token, performs other logical operations (generally obtains permissions according to the user information), and returns the results

Advantages of JWT certification

Compared with the traditional session authentication method, the advantages of JWT are:

Concise: JWT Token has small amount of data and fast transmission speed
Because JWT tokens are stored on the client in JSON encrypted form, JWT is cross language and is supported in any web form in principle
There is no need to save session information on the server, that is, it does not depend on cookie s and sessions, so it has no disadvantages of traditional session authentication, and is especially suitable for distributed microservices
Single sign on friendly: if you use Session for identity authentication, it is difficult to achieve single sign on because cookies cannot cross domains. However, if the token is used for authentication, the token can be saved in the memory of any location of the client, not necessarily a cookie, so it does not rely on cookies, so there will be no such problems
Suitable for mobile applications: if you use Session for identity authentication, you need to save a piece of information on the server, and this method will depend on cookies (you need to save SessionId with cookies), so it is not suitable for mobile applications

At present, JWT token is more recommended for user authentication in both single and distributed applications

JWT structure

Header, payload, and signature

During transmission, the three parts of JWT will be Base64 encoded and connected with. To form the final transmitted string

1.Header

The JWT header is a JSON object that describes JWT metadata. The alg attribute indicates the algorithm used for signature. The default is HMAC SHA256; The typ attribute indicates the type of token. JWT tokens are uniformly written as JWT.

2.Payload

The payload part is the main content part of JWT. It is also a JSON object that contains the data to be passed. JWT specifies seven default fields to choose from

iss: publisher
exp: Expiration time
sub: theme
aud: user
nbf: Not available before
iat: Release time
jti: JWT ID Used to identify the JWT

In addition to the above default fields, we can also customize private fields. Generally, we will put the data containing user information into the payload

By default, JWT is unencrypted, because only base64 algorithm is adopted. After getting the JWT string, it can be converted back to the original JSON data, and anyone can interpret its content. Therefore, do not build a private information field. For example, the user's password must not be saved in JWT to prevent information disclosure. JWT is only suitable for transmitting some non sensitive information in the network

3.Signature

The signature hash part is to sign the above two parts of data. The header and payload data encoded by base64 need to be used to generate hash through the specified algorithm to ensure that the data will not be tampered with. First, you need to specify a secret. The password is only stored in the server and cannot be disclosed to the user. Then, use the signature algorithm specified in the header (HMAC SHA256 by default)

Role of each part of JWT

After the server receives the JWT token sent by the client:

The header and payload can directly decode the original text using base64, obtain the hash signature algorithm from the header, and obtain valid data from the payload

signature cannot decode the original text because it uses an irreversible encryption algorithm. Its function is to verify whether the token has been tampered with. After obtaining the encryption algorithm in the header, the server encrypts the header and payload with the algorithm and the secretKey, and compares whether the encrypted data is consistent with the data sent by the client. Note that the secretKey can only be saved on the server and has different meanings for different encryption algorithms. Generally, for MD5 digest encryption algorithms, the secretKey actually represents the salt value

JWT dependency

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.10.3</version>
</dependency>

JWT tool class

package com.example.demo.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @date 2019/4/25 11:46
 * @atuther wangbo
 */
public class JwtUtil {

    //Key (for signature)
    public static final String SECRET = "sdjhakdhajdklsl;o653632";
    //Expiration time: seconds
    public static final int EXPIRE = 5;

    /**
     * Generate Token
     * @param userId
     * @param userName
     * @return
     * @throws Exception
     */
    public static String createToken(String userId, String userName) throws Exception {
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.SECOND, EXPIRE);
        Date expireDate = nowTime.getTime();

        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        String token = JWT.create()
                .withHeader(map)//head
                .withClaim("userId", userId)
                .withClaim("userName", userName)
                .withSubject("test")//
                .withIssuedAt(new Date())//Signature time
                .withExpiresAt(expireDate)//Expiration time
                .sign(Algorithm.HMAC256(SECRET));//autograph
        return token;
    }

    /**
     * Verify Token
     * @param token
     * @return
     * @throws Exception
     */
    public static Map<String, Claim> verifyToken(String token)throws Exception{
        // When creating a parsing object, the algorithm and secret used should be consistent with that when creating a token
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        DecodedJWT jwt = null;
        try {
        	//If an exception occurs when parsing a token, it indicates that the previous and subsequent tokens are inconsistent, the verification fails, or the token expires
            jwt = verifier.verify(token);
        }catch (Exception e){
            throw new RuntimeException("The certificate has expired. Please log in again");
        }
        return jwt.getClaims();
    }

    /**
     * Parse Token
     * @param token
     * @return
     */
    public static Map<String, Claim> parseToken(String token){
        DecodedJWT decodedJWT = JWT.decode(token);
        return decodedJWT.getClaims();
    }

}

Tags: Front-end JSON http

Posted on Sun, 31 Oct 2021 20:30:53 -0400 by tomm098