JJWT API - JSON Web Token library API for Java and Android
—
This document covers the core JWT building, parsing, and validation functionality of JJWT API.
The Jwts class serves as the main entry point for JWT operations, providing factory methods and standard algorithm constants.
public final class Jwts {
// Factory Methods
public static JwtBuilder builder();
public static JwtParserBuilder parser();
public static ClaimsBuilder claims();
public static HeaderBuilder header();
// Standard Algorithm Constants
public static final class SIG {
public static final MacAlgorithm HS256;
public static final MacAlgorithm HS384;
public static final MacAlgorithm HS512;
public static final SignatureAlgorithm RS256;
public static final SignatureAlgorithm RS384;
public static final SignatureAlgorithm RS512;
public static final SignatureAlgorithm PS256;
public static final SignatureAlgorithm PS384;
public static final SignatureAlgorithm PS512;
public static final SignatureAlgorithm ES256;
public static final SignatureAlgorithm ES384;
public static final SignatureAlgorithm ES512;
public static final SignatureAlgorithm EdDSA;
}
public static final class ENC {
public static final AeadAlgorithm A128GCM;
public static final AeadAlgorithm A192GCM;
public static final AeadAlgorithm A256GCM;
public static final AeadAlgorithm A128CBC_HS256;
public static final AeadAlgorithm A192CBC_HS384;
public static final AeadAlgorithm A256CBC_HS512;
}
public static final class KEY {
public static final KeyAlgorithm<SecretKey, SecretKey> DIRECT;
public static final KeyAlgorithm<SecretKey, SecretKey> A128KW;
public static final KeyAlgorithm<SecretKey, SecretKey> A192KW;
public static final KeyAlgorithm<SecretKey, SecretKey> A256KW;
public static final KeyAlgorithm<PublicKey, PrivateKey> RSA1_5;
public static final KeyAlgorithm<PublicKey, PrivateKey> RSA_OAEP;
public static final KeyAlgorithm<PublicKey, PrivateKey> RSA_OAEP_256;
public static final KeyAlgorithm<PublicKey, PrivateKey> ECDH_ES;
public static final KeyAlgorithm<PublicKey, PrivateKey> ECDH_ES_A128KW;
public static final KeyAlgorithm<PublicKey, PrivateKey> ECDH_ES_A192KW;
public static final KeyAlgorithm<PublicKey, PrivateKey> ECDH_ES_A256KW;
public static final KeyAlgorithm<Password, Password> PBES2_HS256_A128KW;
public static final KeyAlgorithm<Password, Password> PBES2_HS384_A192KW;
public static final KeyAlgorithm<Password, Password> PBES2_HS512_A256KW;
}
public static final class ZIP {
public static final CompressionAlgorithm DEF;
public static final CompressionAlgorithm GZIP;
}
}The JwtBuilder interface provides a fluent API for constructing JWTs with various configurations.
public interface JwtBuilder {
// Configuration
JwtBuilder provider(Provider provider);
JwtBuilder random(SecureRandom secureRandom);
// Content
JwtBuilder content(String content);
JwtBuilder content(byte[] content);
JwtBuilder content(InputStream content);
// Standard Claims
JwtBuilder issuer(String iss);
JwtBuilder subject(String sub);
JwtBuilder audience(String aud);
JwtBuilder audiences(String... audiences);
JwtBuilder expiration(Date exp);
JwtBuilder notBefore(Date nbf);
JwtBuilder issuedAt(Date iat);
JwtBuilder id(String jti);
// Custom Claims
JwtBuilder claim(String name, Object value);
// Security
JwtBuilder signWith(Key key);
<K extends Key> JwtBuilder signWith(K key, SecureDigestAlgorithm<? super K, ?> alg);
JwtBuilder encryptWith(SecretKey key, AeadAlgorithm enc);
<K extends Key> JwtBuilder encryptWith(K key, KeyAlgorithm<? super K, ?> keyAlg, AeadAlgorithm enc);
// Compression
JwtBuilder compressWith(CompressionAlgorithm alg);
// Access Builders
BuilderHeader header();
BuilderClaims claims();
// Build
String compact();
}public interface BuilderClaims extends ClaimsBuilder<BuilderClaims> {
JwtBuilder and();
}
public interface BuilderHeader extends HeaderBuilder<BuilderHeader> {
JwtBuilder and();
}import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;
// Generate key
SecretKey key = Keys.secretKeyFor(Jwts.SIG.HS256);
// Build JWT with standard claims
String jwt = Jwts.builder()
.subject("user123")
.issuer("myapp")
.audience("web-app")
.expiration(new Date(System.currentTimeMillis() + 3600000)) // 1 hour
.issuedAt(new Date())
.id(UUID.randomUUID().toString())
.claim("role", "admin")
.claim("permissions", Arrays.asList("read", "write"))
.signWith(key)
.compact();import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
// Generate encryption key
SecretKey encKey = Keys.secretKeyFor(Jwts.ENC.A256GCM);
// Build encrypted JWT
String jwe = Jwts.builder()
.subject("sensitive-user")
.claim("ssn", "123-45-6789")
.claim("salary", 150000)
.encryptWith(encKey, Jwts.ENC.A256GCM)
.compact();String jwt = Jwts.builder()
.header()
.type("JWT")
.keyId("key-1")
.and()
.claims()
.subject("user123")
.issuer("myapp")
.add("custom", "value")
.and()
.signWith(key)
.compact();The JwtParserBuilder and JwtParser interfaces provide comprehensive JWT parsing and validation capabilities.
public interface JwtParserBuilder {
// Configuration
JwtParserBuilder unsecured();
JwtParserBuilder provider(Provider provider);
JwtParserBuilder clock(Clock clock);
JwtParserBuilder clockSkewSeconds(long seconds);
// Key Management
JwtParserBuilder verifyWith(SecretKey key);
JwtParserBuilder verifyWith(PublicKey key);
JwtParserBuilder decryptWith(SecretKey key);
JwtParserBuilder decryptWith(PrivateKey key);
JwtParserBuilder keyLocator(Locator<Key> keyLocator);
// Claim Validation
JwtParserBuilder requireId(String id);
JwtParserBuilder requireSubject(String subject);
JwtParserBuilder requireIssuer(String issuer);
JwtParserBuilder requireAudience(String audience);
JwtParserBuilder requireExpiration(Date expiration);
JwtParserBuilder requireNotBefore(Date notBefore);
JwtParserBuilder requireIssuedAt(Date issuedAt);
JwtParserBuilder require(String claimName, Object value);
// Algorithm Configuration
NestedCollection<AeadAlgorithm, JwtParserBuilder> enc();
NestedCollection<KeyAlgorithm<?, ?>, JwtParserBuilder> key();
NestedCollection<SecureDigestAlgorithm<?, ?>, JwtParserBuilder> sig();
NestedCollection<CompressionAlgorithm, JwtParserBuilder> zip();
// Build
JwtParser build();
}public interface JwtParser {
// Utility
boolean isSigned(CharSequence compact);
// Generic Parsing
Jwt<?, ?> parse(CharSequence jwt);
// Unsecured JWT Parsing
Jwt<Header, byte[]> parseUnsecuredContent(CharSequence jwt);
Jwt<Header, Claims> parseUnsecuredClaims(CharSequence jwt);
// Signed JWT (JWS) Parsing
Jws<byte[]> parseSignedContent(CharSequence jws);
Jws<Claims> parseSignedClaims(CharSequence jws);
// RFC 7797 Unencoded Payload Support
Jws<byte[]> parseSignedContent(CharSequence jws, byte[] unencodedPayload);
Jws<Claims> parseSignedClaims(CharSequence jws, byte[] unencodedPayload);
// Encrypted JWT (JWE) Parsing
Jwe<byte[]> parseEncryptedContent(CharSequence jwe);
Jwe<Claims> parseEncryptedClaims(CharSequence jwe);
}import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
// Create parser with key and validation rules
JwtParser parser = Jwts.parser()
.verifyWith(key)
.requireIssuer("myapp")
.requireAudience("web-app")
.clockSkewSeconds(30) // Allow 30 seconds clock skew
.build();
// Parse and validate
try {
Jws<Claims> jws = parser.parseSignedClaims(jwtString);
Claims claims = jws.getPayload();
String subject = claims.getSubject();
String role = claims.get("role", String.class);
System.out.println("Successfully parsed JWT for: " + subject);
System.out.println("Role: " + role);
} catch (JwtException e) {
System.err.println("JWT validation failed: " + e.getMessage());
}// Custom key locator for multi-tenant scenarios
Locator<Key> keyLocator = new Locator<Key>() {
@Override
public Key locate(Header header) {
String keyId = header.getKeyId();
String issuer = ((Claims) header).getIssuer(); // If available
// Look up key based on kid and/or issuer
return keyService.getKey(keyId, issuer);
}
};
JwtParser parser = Jwts.parser()
.keyLocator(keyLocator)
.build();// Restrict to specific algorithms for security
JwtParser parser = Jwts.parser()
.verifyWith(publicKey)
.sig().add(Jwts.SIG.RS256).add(Jwts.SIG.RS384).and() // Only allow RS256/RS384
.build();JwtParser parser = Jwts.parser()
.decryptWith(privateKey)
.build();
try {
Jwe<Claims> jwe = parser.parseEncryptedClaims(jweString);
Claims claims = jwe.getPayload();
// Access sensitive data
String ssn = claims.get("ssn", String.class);
Integer salary = claims.get("salary", Integer.class);
} catch (JwtException e) {
System.err.println("JWE decryption failed: " + e.getMessage());
}JJWT supports RFC 7797 for JWS with unencoded (detached) payloads:
// Create JWS with unencoded payload
byte[] payload = "sensitive payload data".getBytes(StandardCharsets.UTF_8);
String jws = Jwts.builder()
.content(payload)
.header()
.add("b64", false) // Indicate unencoded payload
.and()
.signWith(key)
.compact();
// Parse JWS with detached payload
Jws<byte[]> parsedJws = parser.parseSignedContent(jws, payload);JJWT supports payload compression to reduce JWT size:
String compressedJwt = Jwts.builder()
.claim("data", largeDataObject)
.compressWith(Jwts.ZIP.DEF) // or Jwts.ZIP.GZIP
.signWith(key)
.compact();
// Decompression is automatic during parsing
Jws<Claims> jws = parser.parseSignedClaims(compressedJwt);// Use custom clock for deterministic testing
Clock fixedClock = new Clock() {
@Override
public Date now() {
return new Date(1609459200000L); // Fixed timestamp
}
};
JwtParser parser = Jwts.parser()
.verifyWith(key)
.clock(fixedClock)
.build();Install with Tessl CLI
npx tessl i tessl/maven-io-jsonwebtoken--jjwt-api