JWT Essentials
A JSON Web Token (JWT) is a compact, URL-safe string that carries digitally-signed claims. Because the signature guarantees integrity, any party in possession of the token can trust its contents without contacting the issuer. Typical use cases include single-sign-on flows, micro-service authentication, and stateless session management.
Stateless Authentication Flow
- Client submits credentials (e.g., username/password or API key).
- Server validates credentials and issues a signed JWT.
- Client stores the token (cookie, local storage, mobile secure storage).
- Every subsequent request includes the token—usually in the
Authorization: Bearer <token>header. - Server verifies the signature and expiration, then grants or denies access.
No server-side session storage is required; all necessary data lives inside the token.
Maven Dependency
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.3</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.3</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.3</version>
<scope>runtime</scope>
</dependency>
Token Issuer
package security;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
public final class JwtIssuer {
private static final String ISSUER = "demo-service";
private static final Duration TTL = Duration.ofDays(3);
private static final SecretKey KEY = Keys.hmacShaKeyFor(
"my-256-bit-secret-key-must-be-32-chars-long!".getBytes()
);
public static String issue(Map<String, Object> claims) {
Instant now = Instant.now();
return Jwts.builder()
.header()
.add("typ", "JWT")
.add("alg", "HS256")
.and()
.issuer(ISSUER)
.issuedAt(Date.from(now))
.expiration(Date.from(now.plus(TTL)))
.id(UUID.randomUUID().toString())
.claims(claims)
.signWith(KEY, Jwts.SIG.HS256)
.compact();
}
}
Token Validator
package security;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.SecurityException;
import java.util.Map;
public final class JwtValidator {
private static final SecretKey KEY = JwtIssuer.KEY;
public static Map<String, Object> validate(String compact) throws JwtException {
return Jwts.parser()
.verifyWith(KEY)
.requireIssuer("demo-service")
.build()
.parseSignedClaims(compact)
.getPayload();
}
}
Quick Demo
public static void main(String[] args) {
Map<String, Object> payload = Map.of("userId", 123456, "role", "ADMIN");
String token = JwtIssuer.issue(payload);
System.out.println("Token: " + token);
Map<String, Object> verified = JwtValidator.validate(token);
System.out.println("User ID: " + verified.get("userId"));
System.out.println("Role: " + verified.get("role"));
}
Running the program prints a signed JWT followed by the extracted claims:
Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkZW1vLXNlcnZpY2UiLCJpYXQiOjE3MDg5NzQwMDAsImV4cCI6MTcwOTIzMzIwMCwianRpIjoiMGE5N2Y1YzQtZTU0Yi00MGEwLWIyMjQtZTI3YjY0MGE4MzI5IiwidXNlcklkIjoxMjM0NTYsInJvbGUiOiJBRE1JTiJ9.3bV9YqV7Kx8qG4X2yZ1A9mN6cF3tR5sU7vW0eH8jI4k
User ID: 123456
Role: ADMIN