CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-jsonwebtoken--jjwt-api

JJWT API - JSON Web Token library API for Java and Android

Pending
Overview
Eval results
Files

types.mddocs/

Types and Interfaces

This document covers the core JWT types including Claims, Headers, and token interfaces that represent parsed JWT content in JJWT API.

JWT Token Types

Base JWT Interface

public interface Jwt<H, P> {
    // Core Methods
    H getHeader();
    P getPayload();
    <T> T accept(JwtVisitor<T> visitor);
    
    // Static Visitor Constants for Unsecured JWTs
    JwtVisitor<Jwt<Header, byte[]>> UNSECURED_CONTENT = /* visitor implementation */;
    JwtVisitor<Jwt<Header, Claims>> UNSECURED_CLAIMS = /* visitor implementation */;
}

Protected JWT Interface

public interface ProtectedJwt<H extends ProtectedHeader, P> extends Jwt<H, P> {
    // Base interface for cryptographically-protected JWTs (JWS and JWE)
}

JSON Web Signature (JWS) Interface

public interface Jws<P> extends ProtectedJwt<JwsHeader, P> {
    // JWS-specific method
    String getDigest();
    
    // Static Visitor Constants for JWS
    JwtVisitor<Jws<byte[]>> CONTENT = /* visitor implementation */;
    JwtVisitor<Jws<Claims>> CLAIMS = /* visitor implementation */;
}

JSON Web Encryption (JWE) Interface

public interface Jwe<P> extends ProtectedJwt<JweHeader, P> {
    // JWE extends ProtectedJwt but doesn't add specific methods
    // All functionality inherited from base interfaces
}

JWT Token Usage Examples

import io.jsonwebtoken.*;

// Parse different JWT types and access content
JwtParser parser = Jwts.parser().verifyWith(key).build();

// Parse generic JWT (auto-detects type)
Jwt<?, ?> jwt = parser.parse(jwtString);
System.out.println("JWT type: " + jwt.getClass().getSimpleName());

// Parse specific JWS with Claims
Jws<Claims> jws = parser.parseSignedClaims(jwtString);
JwsHeader header = jws.getHeader();
Claims claims = jws.getPayload();
String signature = jws.getDigest();

System.out.println("Algorithm: " + header.getAlgorithm());
System.out.println("Subject: " + claims.getSubject());
System.out.println("Signature: " + signature);

// Use visitor pattern for type-safe processing
String result = jwt.accept(new JwtVisitor<String>() {
    @Override
    public String visit(Jwt<Header, byte[]> jwt) {
        return "Unsecured JWT with " + jwt.getPayload().length + " bytes";
    }
    
    @Override
    public String visit(Jwt<Header, Claims> jwt) {
        return "Unsecured JWT with subject: " + jwt.getPayload().getSubject();
    }
    
    @Override
    public String visit(Jws<byte[]> jws) {
        return "Signed JWT with " + jws.getPayload().length + " bytes";
    }
    
    @Override
    public String visit(Jws<Claims> jws) {
        return "Signed JWT with subject: " + jws.getPayload().getSubject();
    }
    
    @Override
    public String visit(Jwe<byte[]> jwe) {
        return "Encrypted JWT with " + jwe.getPayload().length + " bytes";
    }
    
    @Override
    public String visit(Jwe<Claims> jwe) {
        return "Encrypted JWT with subject: " + jwe.getPayload().getSubject();
    }
});

Header Types

Base Header Interface

public interface Header extends Map<String, Object> {
    // Standard Header Parameters
    String getType();
    String getContentType();
    String getAlgorithm();
    String getCompressionAlgorithm();
    
    // Standard Header Parameter Names
    String TYPE = "typ";
    String CONTENT_TYPE = "cty";
    String ALGORITHM = "alg";
    String COMPRESSION_ALGORITHM = "zip";
}

Protected Header Interface

public interface ProtectedHeader extends Header, X509Accessor {
    // Additional Protected Header Parameters
    String getKeyId();
    Set<String> getCritical();
    
    // Additional Parameter Names
    String KEY_ID = "kid";
    String CRITICAL = "crit";
}

JWS Header Interface

public interface JwsHeader extends ProtectedHeader {
    // RFC 7797 Unencoded Payload Support
    boolean isPayloadEncoded();
    
    // Parameter Name
    String PAYLOAD_ENCODED = "b64";
}

JWE Header Interface

public interface JweHeader extends ProtectedHeader {
    // JWE-specific Header Parameters
    String getEncryptionAlgorithm();
    String getInitializationVector();
    String getAuthenticationTag();
    String getEphemeralPublicKey();
    String getAgreementPartyUInfo();
    String getAgreementPartyVInfo();
    Integer getPbes2Count();
    String getPbes2Salt();
    
    // JWE Parameter Names
    String ENCRYPTION_ALGORITHM = "enc";
    String INITIALIZATION_VECTOR = "iv";
    String AUTHENTICATION_TAG = "tag";
    String EPHEMERAL_PUBLIC_KEY = "epk";
    String AGREEMENT_PARTY_U_INFO = "apu";
    String AGREEMENT_PARTY_V_INFO = "apv";
    String PBES2_COUNT = "p2c";
    String PBES2_SALT = "p2s";
}

Header Usage Examples

import io.jsonwebtoken.*;

// Access header information from parsed JWT
Jws<Claims> jws = parser.parseSignedClaims(jwtString);
JwsHeader header = jws.getHeader();

// Standard header parameters
String algorithm = header.getAlgorithm();      // "RS256"
String type = header.getType();                // "JWT"
String keyId = header.getKeyId();              // "key-1"
String contentType = header.getContentType();  // null (typically)

// Check for RFC 7797 unencoded payload
boolean isPayloadEncoded = header.isPayloadEncoded(); // true (default)

// Access custom header parameters
Object customParam = header.get("custom");

// JWE header example
Jwe<Claims> jwe = parser.parseEncryptedClaims(jweString);
JweHeader jweHeader = jwe.getHeader();

String encAlgorithm = jweHeader.getEncryptionAlgorithm(); // "A256GCM"
String keyAlgorithm = jweHeader.getAlgorithm();           // "RSA-OAEP"

Claims Interface

Core Claims Interface

public interface Claims extends Map<String, Object> {
    // Standard Claims Accessors
    String getIssuer();
    String getSubject();
    Set<String> getAudience();
    Date getExpiration();
    Date getNotBefore();
    Date getIssuedAt();
    String getId();
    
    // Type-safe Claim Access
    <T> T get(String claimName, Class<T> requiredType);
    
    // Standard Claim Names
    String ISSUER = "iss";
    String SUBJECT = "sub";
    String AUDIENCE = "aud";
    String EXPIRATION = "exp";
    String NOT_BEFORE = "nbf";
    String ISSUED_AT = "iat";
    String ID = "jti";
}

Claims Builder Interface

public interface ClaimsBuilder extends MapMutator<String, Object, ClaimsBuilder>, ClaimsMutator<ClaimsBuilder> {
    // Inherits methods from MapMutator and ClaimsMutator
    Claims build();
}

Claims Mutator Interface

public interface ClaimsMutator<T> {
    // Standard Claims Mutators
    T issuer(String iss);
    T subject(String sub);
    T audience(String aud);
    T audiences(String... audiences);
    T expiration(Date exp);
    T notBefore(Date nbf);
    T issuedAt(Date iat);
    T id(String jti);
}

Claims Usage Examples

import io.jsonwebtoken.*;
import java.util.Date;
import java.util.Set;

// Parse JWT and access claims
Jws<Claims> jws = parser.parseSignedClaims(jwtString);
Claims claims = jws.getPayload();

// Standard claims
String issuer = claims.getIssuer();        // "https://auth.example.com"
String subject = claims.getSubject();      // "user123"
Set<String> audience = claims.getAudience(); // ["web-app", "mobile-app"]
Date expiration = claims.getExpiration();  // expiration timestamp
Date notBefore = claims.getNotBefore();    // not-before timestamp
Date issuedAt = claims.getIssuedAt();      // issued-at timestamp
String jti = claims.getId();               // "unique-token-id"

// Type-safe custom claim access
String role = claims.get("role", String.class);
Integer userId = claims.get("user_id", Integer.class);
List<String> permissions = claims.get("permissions", List.class);

// Check for claim existence
if (claims.containsKey("department")) {
    String department = claims.get("department", String.class);
}

// Iterate over all claims
for (Map.Entry<String, Object> entry : claims.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

// Create claims using builder
Claims customClaims = Jwts.claims()
    .issuer("myapp")
    .subject("user456")
    .audience("api")
    .expiration(new Date(System.currentTimeMillis() + 3600000))
    .add("role", "admin")
    .add("permissions", Arrays.asList("read", "write", "delete"))
    .build();

Visitor Pattern Support

JWT Visitor Interface

public interface JwtVisitor<T> {
    T visit(Jwt<Header, byte[]> jwt);
    T visit(Jwt<Header, Claims> jwt);
    T visit(Jws<byte[]> jws);
    T visit(Jws<Claims> jws);
    T visit(Jwe<byte[]> jwe);
    T visit(Jwe<Claims> jwe);
}

Supported JWT Visitor

public class SupportedJwtVisitor<T> implements JwtVisitor<T> {
    // Base implementation that throws UnsupportedJwtException for unsupported types
    // Subclasses override only methods for supported JWT types
}

JWT Handler Interface (Alternative Pattern)

public interface JwtHandler<T> {
    T onUnsecuredContent(Jwt<Header, byte[]> jwt);
    T onUnsecuredClaims(Jwt<Header, Claims> jwt);
    T onSignedContent(Jws<byte[]> jws);
    T onSignedClaims(Jws<Claims> jws);
    T onEncryptedContent(Jwe<byte[]> jwe);
    T onEncryptedClaims(Jwe<Claims> jwe);
}

JWT Handler Adapter

public class JwtHandlerAdapter<T> implements JwtHandler<T> {
    // Default implementation that throws UnsupportedJwtException
    // Subclasses override only methods for supported JWT types
}

Visitor Pattern Examples

import io.jsonwebtoken.*;

// Custom visitor to extract information
public class JwtInfoVisitor implements JwtVisitor<String> {
    @Override
    public String visit(Jwt<Header, byte[]> jwt) {
        return "Unsecured JWT with byte payload, size: " + jwt.getPayload().length;
    }
    
    @Override
    public String visit(Jwt<Header, Claims> jwt) {
        Claims claims = jwt.getPayload();
        return "Unsecured JWT, subject: " + claims.getSubject();
    }
    
    @Override
    public String visit(Jws<byte[]> jws) {
        return "Signed JWT (" + jws.getHeader().getAlgorithm() + ") with byte payload";
    }
    
    @Override
    public String visit(Jws<Claims> jws) {
        Claims claims = jws.getPayload();
        return "Signed JWT, subject: " + claims.getSubject() + 
               ", algorithm: " + jws.getHeader().getAlgorithm();
    }
    
    @Override
    public String visit(Jwe<byte[]> jwe) {
        return "Encrypted JWT with byte payload";
    }
    
    @Override
    public String visit(Jwe<Claims> jwe) {
        Claims claims = jwe.getPayload();
        return "Encrypted JWT, subject: " + claims.getSubject();
    }
}

// Use the visitor
Jwt<?, ?> jwt = parser.parse(jwtString);
String info = jwt.accept(new JwtInfoVisitor());
System.out.println(info);

// Using SupportedJwtVisitor for specific JWT types only
public class ClaimsExtractor extends SupportedJwtVisitor<Claims> {
    @Override
    public Claims visit(Jwt<Header, Claims> jwt) {
        return jwt.getPayload();
    }
    
    @Override
    public Claims visit(Jws<Claims> jws) {
        return jws.getPayload();
    }
    
    @Override
    public Claims visit(Jwe<Claims> jwe) {
        return jwe.getPayload();
    }
    
    // Byte payload visits will throw UnsupportedJwtException
}

// Extract claims regardless of JWT type
Claims claims = jwt.accept(new ClaimsExtractor());

Utility Interfaces

Locator Interface

public interface Locator<T> {
    T locate(Header header);
}

Locator Adapter

public abstract class LocatorAdapter<T> implements Locator<T> {
    @Override
    public T locate(Header header) {
        return null; // Default implementation
    }
}

Key Resolution Examples

import io.jsonwebtoken.security.SigningKeyResolver;

// Dynamic key resolution based on header information
public class CustomKeyLocator implements Locator<Key> {
    private final KeyService keyService;
    
    public CustomKeyLocator(KeyService keyService) {
        this.keyService = keyService;
    }
    
    @Override
    public Key locate(Header header) {
        String keyId = header instanceof ProtectedHeader 
            ? ((ProtectedHeader) header).getKeyId() 
            : null;
            
        String algorithm = header.getAlgorithm();
        
        if (keyId != null) {
            return keyService.getKeyById(keyId);
        } else if ("HS256".equals(algorithm)) {
            return keyService.getDefaultHmacKey();
        } else {
            throw new IllegalArgumentException("Cannot locate key for algorithm: " + algorithm);
        }
    }
}

// Use with parser
JwtParser parser = Jwts.parser()
    .keyLocator(new CustomKeyLocator(keyService))
    .build();

Exception Types

Claim-Related Exceptions

public class ClaimJwtException extends JwtException {
    // Base exception for claim validation failures
    public ClaimJwtException(Header header, Claims claims, String message);
    public ClaimJwtException(Header header, Claims claims, String message, Throwable cause);
    
    public Header getHeader();
    public Claims getClaims();
}

public class IncorrectClaimException extends ClaimJwtException {
    // Claim has incorrect value
    public IncorrectClaimException(Header header, Claims claims, String claimName, Object expectedValue, Object actualValue);
    
    public String getClaimName();
    public Object getExpectedValue();
    public Object getActualValue();
}

public class MissingClaimException extends ClaimJwtException {
    // Required claim is missing
    public MissingClaimException(Header header, Claims claims, String claimName);
    
    public String getClaimName();
}

public class InvalidClaimException extends ClaimJwtException {
    // Claim value is invalid (e.g., malformed date)
    public InvalidClaimException(Header header, Claims claims, String message);
}

JWT Validation Exceptions

public class ExpiredJwtException extends ClaimJwtException {
    // JWT has expired
    public ExpiredJwtException(Header header, Claims claims, String message);
}

public class PrematureJwtException extends ClaimJwtException {
    // JWT is not yet valid (nbf claim)
    public PrematureJwtException(Header header, Claims claims, String message);
}

public class RequiredTypeException extends JwtException {
    // Type conversion failed
    public RequiredTypeException(String message);
}

Exception Handling Examples

import io.jsonwebtoken.*;

try {
    Jws<Claims> jws = parser.parseSignedClaims(jwtString);
    Claims claims = jws.getPayload();
    
    // JWT is valid, process claims
    processValidJwt(claims);
    
} catch (ExpiredJwtException e) {
    System.err.println("JWT expired at: " + e.getClaims().getExpiration());
    // Handle expired token
    
} catch (PrematureJwtException e) {
    System.err.println("JWT not valid until: " + e.getClaims().getNotBefore());
    // Handle premature token
    
} catch (MissingClaimException e) {
    System.err.println("Missing required claim: " + e.getClaimName());
    // Handle missing claim
    
} catch (IncorrectClaimException e) {
    System.err.println("Incorrect claim '" + e.getClaimName() + 
                      "': expected '" + e.getExpectedValue() + 
                      "', got '" + e.getActualValue() + "'");
    // Handle incorrect claim
    
} catch (SignatureException e) {
    System.err.println("JWT signature validation failed");
    // Handle signature failure
    
} catch (MalformedJwtException e) {
    System.err.println("JWT is malformed: " + e.getMessage());
    // Handle malformed JWT
    
} catch (JwtException e) {
    System.err.println("JWT processing failed: " + e.getMessage());
    // Handle other JWT exceptions
}

Type Conversion Utilities

Safe Type Extraction

import io.jsonwebtoken.Claims;

public class ClaimsUtils {
    public static <T> T getClaimSafely(Claims claims, String claimName, Class<T> type, T defaultValue) {
        try {
            T value = claims.get(claimName, type);
            return value != null ? value : defaultValue;
        } catch (RequiredTypeException e) {
            return defaultValue;
        }
    }
    
    public static List<String> getStringList(Claims claims, String claimName) {
        Object value = claims.get(claimName);
        if (value instanceof List) {
            List<?> list = (List<?>) value;
            return list.stream()
                .filter(String.class::isInstance)
                .map(String.class::cast)
                .collect(Collectors.toList());
        }
        return Collections.emptyList();
    }
    
    public static Date getDateClaim(Claims claims, String claimName) {
        Object value = claims.get(claimName);
        if (value instanceof Date) {
            return (Date) value;
        } else if (value instanceof Number) {
            return new Date(((Number) value).longValue() * 1000);
        }
        return null;
    }
}

// Usage
Claims claims = jws.getPayload();
String role = ClaimsUtils.getClaimSafely(claims, "role", String.class, "user");
List<String> permissions = ClaimsUtils.getStringList(claims, "permissions");
Date customDate = ClaimsUtils.getDateClaim(claims, "custom_date");

Install with Tessl CLI

npx tessl i tessl/maven-io-jsonwebtoken--jjwt-api

docs

index.md

io-utilities.md

jwt-operations.md

security-jwk.md

types.md

tile.json