Java JWT

Java JWT

Posted by Leonard Meng on January 29, 2022

Understanding Java JWT: A Deep Dive

JWT, or JSON Web Token, is a compact, URL-safe means of representing claims to be transferred between two parties. In the context of Java, this standard is commonly used to create access tokens for secure application services. Let’s take a deep dive into Java JWT, its structure, its usage, and its benefits.

Structure of JWT

A JWT typically consists of three parts: the header, the payload, and the signature.

  1. Header: This section primarily declares the type of the token and the signing algorithm being used. It’s base64Url encoded.
1
2
3
4
{
  "alg": "HS256",
  "typ": "JWT"
}
  1. Payload: Also known as the JWT Claims, this is where the actual data (like user information) is stored. It is also base64Url encoded.
1
2
3
4
5
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
  1. Signature: The signature is used to verify the message wasn’t changed along the way. It’s created by encoding the header and payload, then concatenating them with a period, and finally applying the specified algorithm.
1
2
3
//$secret is a string that contains the secret key
String signature = HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload), secret)

When combined, these sections form a complete JWT, which looks like: header.payload.signature

An example of JWT

This is a JWT string:

1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

dive-into-java-jwt1

JWT workflow

dive-into-java-jwt2

Usage in Java

Java has a variety of libraries available to handle JWT creation and validation. For this example, we’ll use the popular library JJWT.

  1. Import dependency in pom.xml:
1
2
3
4
5
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>
  1. Create JWTUtils Class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package org.mengsoft.adminbackend.common;

import io.jsonwebtoken.*;
import org.bouncycastle.util.encoders.Base64;
import org.mengsoft.adminbackend.constant.JwtConstant;
import org.mengsoft.adminbackend.entity.CheckResult;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;

public class JwtUtils {

    public static String createJWT(String id, String subject, long ttlMillis) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey secretKey = generalKey();
        JwtBuilder builder = Jwts.builder()
                .setId(id)
                .setSubject(subject)   // Subject
                .setIssuer("Java1234")     // Issuer
                .setIssuedAt(now)      // Issued time
                .signWith(signatureAlgorithm, secretKey); // Signature Algorithm and Secret Key
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date expDate = new Date(expMillis);
            builder.setExpiration(expDate); // Expiration time
        }
        return builder.compact();
    }

    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.decode(JwtConstant.JWT_SECERT);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

    /**
     * Check JWT
     * @param jwtStr
     * @return
     */
    public static CheckResult validateJWT(String jwtStr) {
        CheckResult checkResult = new CheckResult();
        Claims claims = null;
        try {
            claims = parseJWT(jwtStr);
            checkResult.setSuccess(true);
            checkResult.setClaims(claims);
        } catch (ExpiredJwtException e) {
            checkResult.setErrCode(JwtConstant.JWT_ERRCODE_EXPIRE);
            checkResult.setSuccess(false);
        } catch (SignatureException e) {
            checkResult.setErrCode(JwtConstant.JWT_ERRCODE_FAIL);
            checkResult.setSuccess(false);
        } catch (Exception e) {
            checkResult.setErrCode(JwtConstant.JWT_ERRCODE_FAIL);
            checkResult.setSuccess(false);
        }
        return checkResult;
    }


    /**
     * Parse JWT
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) {
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }
}

In these examples, "secret" is the secret key used to sign the JWT. For production use, remember to store this key securely and not hardcode it into your application.

Benefits of JWT

JWTs offer a number of benefits that make them ideal for usage in secure applications:

  1. Self-contained: A JWT is a self-contained token that has all the information needed within itself. This makes it extremely easy to transmit data between parties.

  2. Compact: Since JWTs are compact and URL safe, they can be sent through an URL, POST parameter, or inside an HTTP header.

  3. Versatile: JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.

  4. Secure: JWT ensures information integrity, meaning that the data contained in it cannot be easily tampered with.

Summary

Java JWT is a powerful standard that brings security and convenience to Java applications. Its compact and self-contained nature make it a go-to choice for secure data transfer in today’s digital world. While there are some considerations to keep in mind, such as securely storing the secret key and ensuring secure transmission of the tokens, the benefits it brings are well worth it.

As always, it’s crucial to understand the needs of your specific application before implementing any new technology or standard. If JWT seems like a fit for your needs, the next step is to dive in and start experimenting with creating and validating

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Welcome to reprint, and please indicate the source: Lingjun Meng's Blog Keep the content of the article complete and the above statement information!