CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-jsonwebtoken--jjwt-impl

JJWT Implementation module providing concrete implementations of JSON Web Token (JWT) creation, parsing, verification, and cryptographic operations for Java and Android applications.

Pending
Overview
Eval results
Files

jwt-parsing.mddocs/

JWT Parsing

The JWT Parsing functionality in JJWT Implementation centers around the DefaultJwtParser and DefaultJwtParserBuilder classes, providing comprehensive parsing, validation, and verification capabilities for JWT, JWS, and JWE tokens. The parser supports flexible configuration for security policies, key resolution, and validation rules.

Core Parser Classes

DefaultJwtParserBuilder

The configurable factory for creating JWT parsers with specific validation and security requirements.

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.JwtParserBuilder;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwe;
import io.jsonwebtoken.Locator;
import io.jsonwebtoken.Clock;
import javax.crypto.SecretKey;
import java.security.PublicKey;
import java.security.PrivateKey;
import java.security.Provider;
import java.util.Date;

// Basic parser creation
JwtParserBuilder parserBuilder = Jwts.parser();

// Parser with verification key
JwtParser parser = Jwts.parser()
    .verifyWith(secretKey)
    .build();

// Parser with decryption key
JwtParser decryptParser = Jwts.parser()
    .decryptWith(privateKey)
    .build();

DefaultJwtParser

The main parsing engine that handles JWT, JWS, and JWE token processing.

import io.jsonwebtoken.impl.DefaultJwtParser;

// Create parser instance
JwtParser parser = Jwts.parser()
    .verifyWith(verificationKey)
    .build();

// Token type detection
String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...";
boolean isSigned = parser.isSigned(token);

// Generic parsing (returns appropriate type based on token)
Object result = parser.parse(token);

Basic Parsing Operations

Unsecured JWT Parsing

// Parse unsecured JWT with claims
JwtParser unsecuredParser = Jwts.parser()
    .unsecured() // Allow unsecured JWTs
    .build();

String unsecuredToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0...";

Jwt<Claims> jwt = unsecuredParser.parseClaimsJwt(unsecuredToken);
Claims claims = jwt.getPayload();

String subject = claims.getSubject();
String issuer = claims.getIssuer();
Date expiration = claims.getExpiration();

// Parse unsecured JWT with content payload
Jwt<String> contentJwt = unsecuredParser.parseContentJwt(contentToken);
String content = contentJwt.getPayload();

JWS Parsing (Signed JWT)

// HMAC signature verification
SecretKey hmacKey = getHmacKey();
JwtParser hmacParser = Jwts.parser()
    .verifyWith(hmacKey)
    .build();

String signedToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...";

Jws<Claims> jws = hmacParser.parseSignedClaims(signedToken);
Claims verifiedClaims = jws.getPayload();

// Access signature information
String algorithm = jws.getHeader().getAlgorithm();
String keyId = jws.getHeader().getKeyId();

// RSA signature verification
PublicKey rsaPublicKey = getRsaPublicKey();
JwtParser rsaParser = Jwts.parser()
    .verifyWith(rsaPublicKey)
    .build();

Jws<Claims> rsaJws = rsaParser.parseSignedClaims(rsaSignedToken);

// EC signature verification
PublicKey ecPublicKey = getEcPublicKey();
JwtParser ecParser = Jwts.parser()
    .verifyWith(ecPublicKey)
    .build();

Jws<Claims> ecJws = ecParser.parseSignedClaims(ecSignedToken);

JWE Parsing (Encrypted JWT)

// Direct decryption
SecretKey contentKey = getContentEncryptionKey();
JwtParser directParser = Jwts.parser()
    .decryptWith(contentKey)
    .build();

String encryptedToken = "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0...";

Jwe<Claims> jwe = directParser.parseEncryptedClaims(encryptedToken);
Claims decryptedClaims = jwe.getPayload();

// Key wrapping decryption
SecretKey keyEncryptionKey = getKeyEncryptionKey();
JwtParser kwParser = Jwts.parser()
    .decryptWith(keyEncryptionKey)
    .build();

Jwe<Claims> kwJwe = kwParser.parseEncryptedClaims(keyWrappedToken);

// RSA decryption
PrivateKey rsaPrivateKey = getRsaPrivateKey();
JwtParser rsaDecryptParser = Jwts.parser()
    .decryptWith(rsaPrivateKey)
    .build();

Jwe<Claims> rsaJwe = rsaDecryptParser.parseEncryptedClaims(rsaEncryptedToken);

Advanced Parser Configuration

Key Locators

import io.jsonwebtoken.Locator;
import io.jsonwebtoken.ProtectedHeader;

// Dynamic key resolution based on header information
Locator<Key> keyLocator = new Locator<Key>() {
    @Override
    public Key locate(ProtectedHeader header) {
        String keyId = header.getKeyId();
        String algorithm = header.getAlgorithm();
        
        if ("HS256".equals(algorithm)) {
            return getHmacKeyById(keyId);
        } else if ("RS256".equals(algorithm)) {
            return getRsaPublicKeyById(keyId);
        } else if ("ES256".equals(algorithm)) {
            return getEcPublicKeyById(keyId);
        }
        
        throw new SecurityException("Unsupported algorithm: " + algorithm);
    }
};

JwtParser dynamicParser = Jwts.parser()
    .keyLocator(keyLocator)
    .build();

// Parse with dynamic key resolution
Jws<Claims> dynamicJws = dynamicParser.parseSignedClaims(tokenWithKeyId);

Clock Configuration

import io.jsonwebtoken.Clock;
import java.time.Instant;

// Custom clock for testing or specific time zones
Clock customClock = () -> Date.from(Instant.parse("2024-01-01T12:00:00Z"));

JwtParser clockParser = Jwts.parser()
    .verifyWith(secretKey)
    .clock(customClock)
    .build();

// Clock skew tolerance
JwtParser tolerantParser = Jwts.parser()
    .verifyWith(secretKey)
    .clockSkewSeconds(300) // Allow 5 minutes clock skew
    .build();

Jws<Claims> tolerantJws = tolerantParser.parseSignedClaims(tokenWithTimeSkew);

Algorithm Registry Configuration

// Configure supported signature algorithms
JwtParser sigParser = Jwts.parser()
    .verifyWith(secretKey)
    .sig() // Access signature algorithm registry
        .add(customSignatureAlgorithm)
        .and()
    .build();

// Configure supported encryption algorithms
JwtParser encParser = Jwts.parser()
    .decryptWith(decryptionKey)
    .enc() // Access encryption algorithm registry
        .add(customEncryptionAlgorithm)
        .and()
    .key() // Access key algorithm registry
        .add(customKeyAlgorithm)
        .and()
    .build();

// Configure compression algorithms
JwtParser zipParser = Jwts.parser()
    .verifyWith(secretKey)
    .zip() // Access compression algorithm registry
        .add(customCompressionAlgorithm)
        .and()
    .build();

Claims Requirements and Validation

The JwtParserBuilder provides comprehensive methods for requiring specific claim values during parsing.

// Require specific standard claims
JwtParser requiredClaimsParser = Jwts.parser()
    .verifyWith(secretKey)
    .requireId("unique-token-id")                    // Require specific 'jti' claim
    .requireSubject("john.doe")                      // Require specific 'sub' claim  
    .requireIssuer("https://auth.example.com")       // Require specific 'iss' claim
    .requireAudience("api.example.com")              // Require specific 'aud' claim
    .requireIssuedAt(specificIssuedAtDate)           // Require specific 'iat' claim
    .requireExpiration(specificExpirationDate)       // Require specific 'exp' claim
    .requireNotBefore(specificNotBeforeDate)         // Require specific 'nbf' claim
    .build();

// Require custom claims
JwtParser customClaimsParser = Jwts.parser()
    .verifyWith(secretKey)
    .require("role", "admin")                        // Require custom claim value
    .require("tenant_id", "acme-corp")               // Require tenant identification
    .require("scope", "read:users")                  // Require specific scope
    .require("version", 2)                           // Require numeric claim value
    .build();

// Mixed requirements
JwtParser mixedParser = Jwts.parser()
    .verifyWith(secretKey)
    .requireIssuer("trusted-issuer")
    .requireSubject("service-account")
    .require("service_type", "background")
    .require("priority", "high")
    .clockSkewSeconds(60)                            // Also configure clock skew
    .build();

// Parse with automatic validation
try {
    Jws<Claims> validatedJws = requiredClaimsParser.parseSignedClaims(token);
    // Token automatically validated against all requirements
    Claims validatedClaims = validatedJws.getPayload();
    processValidatedToken(validatedClaims);
    
} catch (MissingClaimException e) {
    // Required claim is missing
    handleMissingClaim(e.getClaimName());
} catch (IncorrectClaimException e) {
    // Claim has incorrect value
    handleIncorrectClaim(e.getClaimName(), e.getExpectedValue(), e.getActualValue());
}

Algorithm Collection Configuration

Complete configuration of supported algorithms for parsing operations.

import io.jsonwebtoken.security.MacAlgorithm;
import io.jsonwebtoken.security.SignatureAlgorithm;
import io.jsonwebtoken.security.AeadAlgorithm;
import io.jsonwebtoken.security.KeyAlgorithm;
import io.jsonwebtoken.io.CompressionAlgorithm;

// Configure signature algorithms collection
JwtParser signatureParser = Jwts.parser()
    .verifyWith(secretKey)
    .sig()
        .add(Jwts.SIG.HS256)        // Add specific MAC algorithm
        .add(Jwts.SIG.HS384)        // Add another MAC algorithm
        .add(Jwts.SIG.RS256)        // Add RSA signature algorithm
        .remove(Jwts.SIG.NONE)      // Remove unsecured algorithm
        .and()
    .build();

// Configure encryption algorithms collection  
JwtParser encryptionParser = Jwts.parser()
    .decryptWith(decryptionKey)
    .enc()
        .add(Jwts.ENC.A256GCM)      // Add AEAD encryption algorithm
        .add(Jwts.ENC.A192GCM)      // Add another encryption algorithm
        .and()
    .key()
        .add(Jwts.KEY.A256KW)       // Add key wrapping algorithm
        .add(Jwts.KEY.DIRECT)       // Add direct key algorithm
        .and()
    .build();

// Configure compression algorithms collection
JwtParser compressionParser = Jwts.parser()
    .verifyWith(secretKey)
    .zip()
        .add(Jwts.ZIP.DEF)          // Add DEFLATE compression
        .add(Jwts.ZIP.GZIP)         // Add GZIP compression
        .and()
    .build();

// Comprehensive algorithm configuration
JwtParser comprehensiveParser = Jwts.parser()
    .verifyWith(verificationKey)
    .decryptWith(decryptionKey)
    .sig()
        .add(Jwts.SIG.HS512)        // Strong HMAC
        .add(Jwts.SIG.RS256)        // RSA signature
        .add(Jwts.SIG.ES256)        // Elliptic curve signature
        .and()
    .enc()
        .add(Jwts.ENC.A256GCM)      // Strong encryption
        .and()
    .key()
        .add(Jwts.KEY.A256KW)       // Key wrapping
        .add(Jwts.KEY.RSA_OAEP)     // RSA key encryption
        .and()
    .zip()
        .add(Jwts.ZIP.DEF)          // Compression support
        .and()
    .clockSkewSeconds(30)           // Time tolerance
    .build();

Unsecured JWT Handling

Configuration for handling unsecured JWTs in controlled scenarios.

// Allow parsing of unsecured JWTs (use with extreme caution)
JwtParser unsecuredParser = Jwts.parser()
    .unsecured()                    // Allow parsing without signature verification
    .build();

// Parse unsecured JWT
Jwt<Header, Claims> unsecuredJwt = unsecuredParser.parseUnsecuredClaims(unsecuredToken);
Claims unsecuredClaims = unsecuredJwt.getPayload();

// Allow decompression of unsecured content (additional risk)
JwtParser unsecuredDecompressionParser = Jwts.parser()
    .unsecured()
    .unsecuredDecompression()       // Allow decompression without verification
    .build();

// Production pattern: Conditional unsecured parsing
public JwtParser createParser(boolean allowUnsecured, SecretKey key) {
    JwtParserBuilder builder = Jwts.parser();
    
    if (allowUnsecured) {
        builder.unsecured();
        // Log security warning
        log.warn("SECURITY: Unsecured JWT parsing enabled");
    } else {
        builder.verifyWith(key);
    }
    
    return builder.build();
}

Critical Header Parameters

// Define critical header parameter handlers
JwtParser criticalParser = Jwts.parser()
    .verifyWith(secretKey)
    .critical() // Configure critical header handling
        .add("custom-critical-param")
        .add("security-level")
        .and()
    .build();

// Parser will validate that tokens include handlers for critical parameters
Jws<Claims> criticalJws = criticalParser.parseSignedClaims(tokenWithCriticalHeaders);

Validation and Error Handling

Time-based Validation

import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.PrematureJwtException;

JwtParser timeParser = Jwts.parser()
    .verifyWith(secretKey)
    .clockSkewSeconds(30) // 30 seconds tolerance
    .build();

try {
    Jws<Claims> validJws = timeParser.parseSignedClaims(token);
    Claims claims = validJws.getPayload();
    
    // Token is valid and within time bounds
    processValidToken(claims);
    
} catch (ExpiredJwtException e) {
    // Token has expired
    handleExpiredToken(e);
} catch (PrematureJwtException e) {
    // Token is not yet valid (nbf claim)
    handlePrematureToken(e);
}

Signature Validation

import io.jsonwebtoken.security.SignatureException;
import io.jsonwebtoken.MalformedJwtException;

try {
    Jws<Claims> validJws = parser.parseSignedClaims(suspiciousToken);
    
} catch (SignatureException e) {
    // Signature verification failed
    logSecurityIncident("Invalid signature", e);
    throw new SecurityException("Token signature invalid");
    
} catch (MalformedJwtException e) {
    // Token structure is malformed
    logSecurityIncident("Malformed token", e);
    throw new IllegalArgumentException("Invalid token format");
}

Encryption Validation

import io.jsonwebtoken.security.SecurityException;

try {
    Jwe<Claims> decryptedJwe = encryptParser.parseEncryptedClaims(encryptedToken);
    
} catch (SecurityException e) {
    // Decryption failed or key mismatch
    handleDecryptionFailure(e);
    
} catch (Exception e) {
    // Other encryption-related errors
    handleGeneralEncryptionError(e);
}

Content Type Handling

String Content

// Parse JWT with string content
JwtParser contentParser = Jwts.parser()
    .verifyWith(secretKey)
    .build();

Jws<String> contentJws = contentParser.parseSignedContent(signedContentToken);
String content = contentJws.getPayload();

// Handle different content types based on header
String contentType = contentJws.getHeader().getContentType();
if ("application/json".equals(contentType)) {
    JsonObject json = parseJson(content);
} else if ("text/plain".equals(contentType)) {
    String plainText = content;
}

Binary Content

// Parse JWT with binary content  
Jws<byte[]> binaryJws = contentParser.parseSignedContent(binaryContentToken);
byte[] binaryContent = binaryJws.getPayload();

// Process based on content type
String contentType = binaryJws.getHeader().getContentType();
if ("application/pdf".equals(contentType)) {
    processPdfContent(binaryContent);
} else if ("image/jpeg".equals(contentType)) {
    processImageContent(binaryContent);
}

Multi-Key Scenarios

Key Rotation Support

import java.util.List;

// Support multiple verification keys for key rotation
List<SecretKey> rotationKeys = Arrays.asList(currentKey, previousKey, oldKey);

Locator<Key> rotationLocator = header -> {
    String keyId = header.getKeyId();
    
    // Try keys in order of preference
    for (SecretKey key : rotationKeys) {
        if (keyMatches(key, keyId)) {
            return key;
        }
    }
    
    throw new SecurityException("No valid key found for keyId: " + keyId);
};

JwtParser rotationParser = Jwts.parser()
    .keyLocator(rotationLocator)
    .build();

Multi-Tenant Key Management

// Tenant-specific key resolution
Locator<Key> tenantKeyLocator = header -> {
    String keyId = header.getKeyId();
    String tenantId = extractTenantFromKeyId(keyId);
    
    return getTenantVerificationKey(tenantId, keyId);
};

JwtParser tenantParser = Jwts.parser()
    .keyLocator(tenantKeyLocator)
    .build();

// Parse tenant-specific tokens
Jws<Claims> tenantJws = tenantParser.parseSignedClaims(tenantToken);
String tenantId = tenantJws.getPayload().get("tenant_id", String.class);

Provider and Serialization Configuration

JCA Provider Configuration

import java.security.Provider;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

// Use specific JCA provider
Provider bcProvider = new BouncyCastleProvider();

JwtParser providerParser = Jwts.parser()
    .provider(bcProvider)
    .verifyWith(secretKey)
    .build();

Jws<Claims> bcJws = providerParser.parseSignedClaims(token);

JSON Deserialization

import io.jsonwebtoken.io.Deserializer;
import io.jsonwebtoken.jackson.io.JacksonDeserializer;

// Custom JSON deserializer
Deserializer<Map<String, ?>> deserializer = new JacksonDeserializer<>();

JwtParser jsonParser = Jwts.parser()
    .json(deserializer)
    .verifyWith(secretKey)
    .build();

Jws<Claims> customJws = jsonParser.parseSignedClaims(tokenWithCustomJson);

Parsing Performance Optimization

Parser Reuse

// Create parser once and reuse (thread-safe)
JwtParser reusableParser = Jwts.parser()
    .verifyWith(secretKey)
    .clockSkewSeconds(30)
    .build();

// Reuse across multiple parsing operations
public Claims parseUserToken(String token) {
    return reusableParser.parseSignedClaims(token).getPayload();
}

public Claims parseServiceToken(String token) {
    return reusableParser.parseSignedClaims(token).getPayload();
}

Batch Processing

// Process multiple tokens efficiently
List<String> tokens = getTokenBatch();
JwtParser batchParser = Jwts.parser()
    .keyLocator(efficientKeyLocator)
    .build();

List<Claims> claimsList = tokens.stream()
    .map(token -> {
        try {
            return batchParser.parseSignedClaims(token).getPayload();
        } catch (Exception e) {
            logParsingError(token, e);
            return null;
        }
    })
    .filter(Objects::nonNull)
    .collect(Collectors.toList());

Unsecured JWT Handling

Allowing Unsecured JWTs

// Allow both secured and unsecured JWTs
JwtParser flexibleParser = Jwts.parser()
    .unsecured() // Allow unsecured JWTs
    .verifyWith(secretKey) // But verify if signature present
    .build();

// Parse any type of JWT
Object result = flexibleParser.parse(unknownToken);
if (result instanceof Jws) {
    Jws<Claims> jws = (Jws<Claims>) result;
    Claims verifiedClaims = jws.getPayload();
} else if (result instanceof Jwt) {
    Jwt<Claims> jwt = (Jwt<Claims>) result;
    Claims unverifiedClaims = jwt.getPayload();
}

Unsecured Decompression

// Allow decompression for unsecured JWTs (use with caution)
JwtParser decompressParser = Jwts.parser()
    .unsecured()
    .unsecuredDecompression() // Allow decompression of unsecured JWTs
    .build();

Jwt<Claims> decompressedJwt = decompressParser.parseClaimsJwt(compressedUnsecuredToken);

Exception Handling

JWT Exception Types

The JJWT library provides a comprehensive exception hierarchy for handling various JWT parsing and validation errors.

import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.PrematureJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.InvalidClaimException;
import io.jsonwebtoken.MissingClaimException;
import io.jsonwebtoken.IncorrectClaimException;
import io.jsonwebtoken.RequiredTypeException;
import io.jsonwebtoken.security.SecurityException;
import io.jsonwebtoken.security.SignatureException;

/**
 * Base class for JWT-related runtime exceptions.
 */
public class JwtException extends RuntimeException;

/**
 * Exception indicating that a JWT string is not in the proper three-part format.
 */
public class MalformedJwtException extends JwtException;

/**
 * Exception indicating that a JWT is expired and therefore not valid.
 */
public class ExpiredJwtException extends ClaimJwtException;

/**
 * Exception indicating that a JWT is not yet valid (nbf claim).
 */
public class PrematureJwtException extends ClaimJwtException;

/**
 * Exception indicating an unsupported JWT type or algorithm.
 */
public class UnsupportedJwtException extends JwtException;

/**
 * Exception indicating a claim validation failure.
 */
public class InvalidClaimException extends ClaimJwtException;

/**
 * Exception indicating a required claim is missing.
 */
public class MissingClaimException extends InvalidClaimException;

/**
 * Exception indicating a claim has an incorrect value.
 */
public class IncorrectClaimException extends InvalidClaimException;

/**
 * Exception indicating incorrect type conversion.
 */
public class RequiredTypeException extends JwtException;

/**
 * Base class for security-related exceptions.
 */
public class SecurityException extends JwtException;

/**
 * Exception indicating JWT signature verification failure.
 */
public class SignatureException extends SecurityException;

Exception Handling Patterns

// Comprehensive error handling
public Claims parseAndValidateToken(String token, SecretKey key) {
    JwtParser parser = Jwts.parser()
        .verifyWith(key)
        .build();
    
    try {
        Jws<Claims> jws = parser.parseSignedClaims(token);
        return jws.getPayload();
        
    } catch (ExpiredJwtException e) {
        // Token has expired
        Date expiration = e.getClaims().getExpiration();
        throw new TokenExpiredException("Token expired at: " + expiration);
        
    } catch (PrematureJwtException e) {
        // Token not yet valid
        Date notBefore = e.getClaims().getNotBefore();
        throw new TokenNotYetValidException("Token not valid until: " + notBefore);
        
    } catch (MalformedJwtException e) {
        // Token format is invalid
        throw new InvalidTokenFormatException("Invalid JWT format: " + e.getMessage());
        
    } catch (SignatureException e) {
        // Signature verification failed
        throw new InvalidSignatureException("JWT signature verification failed");
        
    } catch (MissingClaimException e) {
        // Required claim is missing
        String claimName = e.getClaimName();
        throw new MissingRequiredClaimException("Missing required claim: " + claimName);
        
    } catch (IncorrectClaimException e) {
        // Claim has wrong value  
        String claimName = e.getClaimName();
        Object expectedValue = e.getExpectedValue();
        Object actualValue = e.getActualValue();
        throw new InvalidClaimValueException(
            "Claim '" + claimName + "' expected '" + expectedValue + 
            "' but was '" + actualValue + "'");
            
    } catch (UnsupportedJwtException e) {
        // Unsupported JWT type
        throw new UnsupportedTokenException("Unsupported JWT: " + e.getMessage());
        
    } catch (RequiredTypeException e) {
        // Type conversion failed
        throw new TypeConversionException("Failed to convert claim type: " + e.getMessage());
        
    } catch (JwtException e) {
        // General JWT error
        throw new TokenProcessingException("JWT processing error: " + e.getMessage());
    }
}

Specific Exception Handling

// Handle specific validation scenarios
public void handleExpirationWithGracePeriod(String token, SecretKey key) {
    try {
        JwtParser parser = Jwts.parser()
            .verifyWith(key)
            .clockSkewSeconds(30) // 30 second grace period
            .build();
            
        Jws<Claims> jws = parser.parseSignedClaims(token);
        processValidToken(jws.getPayload());
        
    } catch (ExpiredJwtException e) {
        Claims expiredClaims = e.getClaims();
        Date expiration = expiredClaims.getExpiration();
        long gracePeriodMs = 60 * 1000; // 1 minute additional grace
        
        if (System.currentTimeMillis() - expiration.getTime() < gracePeriodMs) {
            // Within extended grace period
            processValidToken(expiredClaims);
        } else {
            throw new TokenDefinitelyExpiredException("Token expired beyond grace period");
        }
    }
}

// Extract claims from expired tokens for logging
public void logTokenDetails(String token) {
    try {
        // This will throw ExpiredJwtException but still provide claims
        Jwts.parser().verifyWith(key).build().parseSignedClaims(token);
        
    } catch (ExpiredJwtException e) {
        // Can still access claims from expired token
        Claims claims = e.getClaims();
        String subject = claims.getSubject();
        Date expiration = claims.getExpiration();
        
        log.info("Expired token - Subject: {}, Expired: {}", subject, expiration);
        
    } catch (JwtException e) {
        log.error("Token parsing failed: {}", e.getMessage());
    }
}

Custom Exception Handling

// Custom exception handler for multi-tenant scenarios
public class TenantAwareJwtHandler {
    
    public Claims parseToken(String token, String tenantId) {
        try {
            SecretKey tenantKey = getTenantKey(tenantId);
            
            JwtParser parser = Jwts.parser()
                .verifyWith(tenantKey)
                .require("tenant_id", tenantId) // Require specific tenant
                .build();
                
            return parser.parseSignedClaims(token).getPayload();
            
        } catch (IncorrectClaimException e) {
            if ("tenant_id".equals(e.getClaimName())) {
                throw new InvalidTenantException(
                    "Token belongs to different tenant: " + e.getActualValue());
            }
            throw e;
            
        } catch (MissingClaimException e) {
            if ("tenant_id".equals(e.getClaimName())) {
                throw new InvalidTenantException("Token missing tenant claim");
            }
            throw e;
        }
    }
    
    private SecretKey getTenantKey(String tenantId) {
        // Retrieve tenant-specific key
        return tenantKeyRepository.getKey(tenantId);
    }
}

The JWT Parsing functionality provides comprehensive, secure, and flexible parsing capabilities with extensive validation options, error handling, and performance optimizations for production use cases.

Install with Tessl CLI

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

docs

compression.md

index.md

jwk-support.md

jwt-building.md

jwt-parsing.md

security-algorithms.md

utilities.md

tile.json