or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

compression.mdindex.mdjwk-support.mdjwt-building.mdjwt-parsing.mdsecurity-algorithms.mdutilities.md

jwt-parsing.mddocs/

0

# JWT Parsing

1

2

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.

3

4

## Core Parser Classes

5

6

### DefaultJwtParserBuilder

7

8

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

9

10

```java { .api }

11

import io.jsonwebtoken.Jwts;

12

import io.jsonwebtoken.JwtParser;

13

import io.jsonwebtoken.JwtParserBuilder;

14

import io.jsonwebtoken.Claims;

15

import io.jsonwebtoken.Jws;

16

import io.jsonwebtoken.Jwe;

17

import io.jsonwebtoken.Locator;

18

import io.jsonwebtoken.Clock;

19

import javax.crypto.SecretKey;

20

import java.security.PublicKey;

21

import java.security.PrivateKey;

22

import java.security.Provider;

23

import java.util.Date;

24

25

// Basic parser creation

26

JwtParserBuilder parserBuilder = Jwts.parser();

27

28

// Parser with verification key

29

JwtParser parser = Jwts.parser()

30

.verifyWith(secretKey)

31

.build();

32

33

// Parser with decryption key

34

JwtParser decryptParser = Jwts.parser()

35

.decryptWith(privateKey)

36

.build();

37

```

38

39

### DefaultJwtParser

40

41

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

42

43

```java { .api }

44

import io.jsonwebtoken.impl.DefaultJwtParser;

45

46

// Create parser instance

47

JwtParser parser = Jwts.parser()

48

.verifyWith(verificationKey)

49

.build();

50

51

// Token type detection

52

String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...";

53

boolean isSigned = parser.isSigned(token);

54

55

// Generic parsing (returns appropriate type based on token)

56

Object result = parser.parse(token);

57

```

58

59

## Basic Parsing Operations

60

61

### Unsecured JWT Parsing

62

63

```java { .api }

64

// Parse unsecured JWT with claims

65

JwtParser unsecuredParser = Jwts.parser()

66

.unsecured() // Allow unsecured JWTs

67

.build();

68

69

String unsecuredToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0...";

70

71

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

72

Claims claims = jwt.getPayload();

73

74

String subject = claims.getSubject();

75

String issuer = claims.getIssuer();

76

Date expiration = claims.getExpiration();

77

78

// Parse unsecured JWT with content payload

79

Jwt<String> contentJwt = unsecuredParser.parseContentJwt(contentToken);

80

String content = contentJwt.getPayload();

81

```

82

83

### JWS Parsing (Signed JWT)

84

85

```java { .api }

86

// HMAC signature verification

87

SecretKey hmacKey = getHmacKey();

88

JwtParser hmacParser = Jwts.parser()

89

.verifyWith(hmacKey)

90

.build();

91

92

String signedToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...";

93

94

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

95

Claims verifiedClaims = jws.getPayload();

96

97

// Access signature information

98

String algorithm = jws.getHeader().getAlgorithm();

99

String keyId = jws.getHeader().getKeyId();

100

101

// RSA signature verification

102

PublicKey rsaPublicKey = getRsaPublicKey();

103

JwtParser rsaParser = Jwts.parser()

104

.verifyWith(rsaPublicKey)

105

.build();

106

107

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

108

109

// EC signature verification

110

PublicKey ecPublicKey = getEcPublicKey();

111

JwtParser ecParser = Jwts.parser()

112

.verifyWith(ecPublicKey)

113

.build();

114

115

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

116

```

117

118

### JWE Parsing (Encrypted JWT)

119

120

```java { .api }

121

// Direct decryption

122

SecretKey contentKey = getContentEncryptionKey();

123

JwtParser directParser = Jwts.parser()

124

.decryptWith(contentKey)

125

.build();

126

127

String encryptedToken = "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0...";

128

129

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

130

Claims decryptedClaims = jwe.getPayload();

131

132

// Key wrapping decryption

133

SecretKey keyEncryptionKey = getKeyEncryptionKey();

134

JwtParser kwParser = Jwts.parser()

135

.decryptWith(keyEncryptionKey)

136

.build();

137

138

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

139

140

// RSA decryption

141

PrivateKey rsaPrivateKey = getRsaPrivateKey();

142

JwtParser rsaDecryptParser = Jwts.parser()

143

.decryptWith(rsaPrivateKey)

144

.build();

145

146

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

147

```

148

149

## Advanced Parser Configuration

150

151

### Key Locators

152

153

```java { .api }

154

import io.jsonwebtoken.Locator;

155

import io.jsonwebtoken.ProtectedHeader;

156

157

// Dynamic key resolution based on header information

158

Locator<Key> keyLocator = new Locator<Key>() {

159

@Override

160

public Key locate(ProtectedHeader header) {

161

String keyId = header.getKeyId();

162

String algorithm = header.getAlgorithm();

163

164

if ("HS256".equals(algorithm)) {

165

return getHmacKeyById(keyId);

166

} else if ("RS256".equals(algorithm)) {

167

return getRsaPublicKeyById(keyId);

168

} else if ("ES256".equals(algorithm)) {

169

return getEcPublicKeyById(keyId);

170

}

171

172

throw new SecurityException("Unsupported algorithm: " + algorithm);

173

}

174

};

175

176

JwtParser dynamicParser = Jwts.parser()

177

.keyLocator(keyLocator)

178

.build();

179

180

// Parse with dynamic key resolution

181

Jws<Claims> dynamicJws = dynamicParser.parseSignedClaims(tokenWithKeyId);

182

```

183

184

### Clock Configuration

185

186

```java { .api }

187

import io.jsonwebtoken.Clock;

188

import java.time.Instant;

189

190

// Custom clock for testing or specific time zones

191

Clock customClock = () -> Date.from(Instant.parse("2024-01-01T12:00:00Z"));

192

193

JwtParser clockParser = Jwts.parser()

194

.verifyWith(secretKey)

195

.clock(customClock)

196

.build();

197

198

// Clock skew tolerance

199

JwtParser tolerantParser = Jwts.parser()

200

.verifyWith(secretKey)

201

.clockSkewSeconds(300) // Allow 5 minutes clock skew

202

.build();

203

204

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

205

```

206

207

### Algorithm Registry Configuration

208

209

```java { .api }

210

// Configure supported signature algorithms

211

JwtParser sigParser = Jwts.parser()

212

.verifyWith(secretKey)

213

.sig() // Access signature algorithm registry

214

.add(customSignatureAlgorithm)

215

.and()

216

.build();

217

218

// Configure supported encryption algorithms

219

JwtParser encParser = Jwts.parser()

220

.decryptWith(decryptionKey)

221

.enc() // Access encryption algorithm registry

222

.add(customEncryptionAlgorithm)

223

.and()

224

.key() // Access key algorithm registry

225

.add(customKeyAlgorithm)

226

.and()

227

.build();

228

229

// Configure compression algorithms

230

JwtParser zipParser = Jwts.parser()

231

.verifyWith(secretKey)

232

.zip() // Access compression algorithm registry

233

.add(customCompressionAlgorithm)

234

.and()

235

.build();

236

```

237

238

### Claims Requirements and Validation

239

240

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

241

242

```java { .api }

243

// Require specific standard claims

244

JwtParser requiredClaimsParser = Jwts.parser()

245

.verifyWith(secretKey)

246

.requireId("unique-token-id") // Require specific 'jti' claim

247

.requireSubject("john.doe") // Require specific 'sub' claim

248

.requireIssuer("https://auth.example.com") // Require specific 'iss' claim

249

.requireAudience("api.example.com") // Require specific 'aud' claim

250

.requireIssuedAt(specificIssuedAtDate) // Require specific 'iat' claim

251

.requireExpiration(specificExpirationDate) // Require specific 'exp' claim

252

.requireNotBefore(specificNotBeforeDate) // Require specific 'nbf' claim

253

.build();

254

255

// Require custom claims

256

JwtParser customClaimsParser = Jwts.parser()

257

.verifyWith(secretKey)

258

.require("role", "admin") // Require custom claim value

259

.require("tenant_id", "acme-corp") // Require tenant identification

260

.require("scope", "read:users") // Require specific scope

261

.require("version", 2) // Require numeric claim value

262

.build();

263

264

// Mixed requirements

265

JwtParser mixedParser = Jwts.parser()

266

.verifyWith(secretKey)

267

.requireIssuer("trusted-issuer")

268

.requireSubject("service-account")

269

.require("service_type", "background")

270

.require("priority", "high")

271

.clockSkewSeconds(60) // Also configure clock skew

272

.build();

273

274

// Parse with automatic validation

275

try {

276

Jws<Claims> validatedJws = requiredClaimsParser.parseSignedClaims(token);

277

// Token automatically validated against all requirements

278

Claims validatedClaims = validatedJws.getPayload();

279

processValidatedToken(validatedClaims);

280

281

} catch (MissingClaimException e) {

282

// Required claim is missing

283

handleMissingClaim(e.getClaimName());

284

} catch (IncorrectClaimException e) {

285

// Claim has incorrect value

286

handleIncorrectClaim(e.getClaimName(), e.getExpectedValue(), e.getActualValue());

287

}

288

```

289

290

### Algorithm Collection Configuration

291

292

Complete configuration of supported algorithms for parsing operations.

293

294

```java { .api }

295

import io.jsonwebtoken.security.MacAlgorithm;

296

import io.jsonwebtoken.security.SignatureAlgorithm;

297

import io.jsonwebtoken.security.AeadAlgorithm;

298

import io.jsonwebtoken.security.KeyAlgorithm;

299

import io.jsonwebtoken.io.CompressionAlgorithm;

300

301

// Configure signature algorithms collection

302

JwtParser signatureParser = Jwts.parser()

303

.verifyWith(secretKey)

304

.sig()

305

.add(Jwts.SIG.HS256) // Add specific MAC algorithm

306

.add(Jwts.SIG.HS384) // Add another MAC algorithm

307

.add(Jwts.SIG.RS256) // Add RSA signature algorithm

308

.remove(Jwts.SIG.NONE) // Remove unsecured algorithm

309

.and()

310

.build();

311

312

// Configure encryption algorithms collection

313

JwtParser encryptionParser = Jwts.parser()

314

.decryptWith(decryptionKey)

315

.enc()

316

.add(Jwts.ENC.A256GCM) // Add AEAD encryption algorithm

317

.add(Jwts.ENC.A192GCM) // Add another encryption algorithm

318

.and()

319

.key()

320

.add(Jwts.KEY.A256KW) // Add key wrapping algorithm

321

.add(Jwts.KEY.DIRECT) // Add direct key algorithm

322

.and()

323

.build();

324

325

// Configure compression algorithms collection

326

JwtParser compressionParser = Jwts.parser()

327

.verifyWith(secretKey)

328

.zip()

329

.add(Jwts.ZIP.DEF) // Add DEFLATE compression

330

.add(Jwts.ZIP.GZIP) // Add GZIP compression

331

.and()

332

.build();

333

334

// Comprehensive algorithm configuration

335

JwtParser comprehensiveParser = Jwts.parser()

336

.verifyWith(verificationKey)

337

.decryptWith(decryptionKey)

338

.sig()

339

.add(Jwts.SIG.HS512) // Strong HMAC

340

.add(Jwts.SIG.RS256) // RSA signature

341

.add(Jwts.SIG.ES256) // Elliptic curve signature

342

.and()

343

.enc()

344

.add(Jwts.ENC.A256GCM) // Strong encryption

345

.and()

346

.key()

347

.add(Jwts.KEY.A256KW) // Key wrapping

348

.add(Jwts.KEY.RSA_OAEP) // RSA key encryption

349

.and()

350

.zip()

351

.add(Jwts.ZIP.DEF) // Compression support

352

.and()

353

.clockSkewSeconds(30) // Time tolerance

354

.build();

355

```

356

357

### Unsecured JWT Handling

358

359

Configuration for handling unsecured JWTs in controlled scenarios.

360

361

```java { .api }

362

// Allow parsing of unsecured JWTs (use with extreme caution)

363

JwtParser unsecuredParser = Jwts.parser()

364

.unsecured() // Allow parsing without signature verification

365

.build();

366

367

// Parse unsecured JWT

368

Jwt<Header, Claims> unsecuredJwt = unsecuredParser.parseUnsecuredClaims(unsecuredToken);

369

Claims unsecuredClaims = unsecuredJwt.getPayload();

370

371

// Allow decompression of unsecured content (additional risk)

372

JwtParser unsecuredDecompressionParser = Jwts.parser()

373

.unsecured()

374

.unsecuredDecompression() // Allow decompression without verification

375

.build();

376

377

// Production pattern: Conditional unsecured parsing

378

public JwtParser createParser(boolean allowUnsecured, SecretKey key) {

379

JwtParserBuilder builder = Jwts.parser();

380

381

if (allowUnsecured) {

382

builder.unsecured();

383

// Log security warning

384

log.warn("SECURITY: Unsecured JWT parsing enabled");

385

} else {

386

builder.verifyWith(key);

387

}

388

389

return builder.build();

390

}

391

```

392

393

### Critical Header Parameters

394

395

```java { .api }

396

// Define critical header parameter handlers

397

JwtParser criticalParser = Jwts.parser()

398

.verifyWith(secretKey)

399

.critical() // Configure critical header handling

400

.add("custom-critical-param")

401

.add("security-level")

402

.and()

403

.build();

404

405

// Parser will validate that tokens include handlers for critical parameters

406

Jws<Claims> criticalJws = criticalParser.parseSignedClaims(tokenWithCriticalHeaders);

407

```

408

409

## Validation and Error Handling

410

411

### Time-based Validation

412

413

```java { .api }

414

import io.jsonwebtoken.ExpiredJwtException;

415

import io.jsonwebtoken.PrematureJwtException;

416

417

JwtParser timeParser = Jwts.parser()

418

.verifyWith(secretKey)

419

.clockSkewSeconds(30) // 30 seconds tolerance

420

.build();

421

422

try {

423

Jws<Claims> validJws = timeParser.parseSignedClaims(token);

424

Claims claims = validJws.getPayload();

425

426

// Token is valid and within time bounds

427

processValidToken(claims);

428

429

} catch (ExpiredJwtException e) {

430

// Token has expired

431

handleExpiredToken(e);

432

} catch (PrematureJwtException e) {

433

// Token is not yet valid (nbf claim)

434

handlePrematureToken(e);

435

}

436

```

437

438

### Signature Validation

439

440

```java { .api }

441

import io.jsonwebtoken.security.SignatureException;

442

import io.jsonwebtoken.MalformedJwtException;

443

444

try {

445

Jws<Claims> validJws = parser.parseSignedClaims(suspiciousToken);

446

447

} catch (SignatureException e) {

448

// Signature verification failed

449

logSecurityIncident("Invalid signature", e);

450

throw new SecurityException("Token signature invalid");

451

452

} catch (MalformedJwtException e) {

453

// Token structure is malformed

454

logSecurityIncident("Malformed token", e);

455

throw new IllegalArgumentException("Invalid token format");

456

}

457

```

458

459

### Encryption Validation

460

461

```java { .api }

462

import io.jsonwebtoken.security.SecurityException;

463

464

try {

465

Jwe<Claims> decryptedJwe = encryptParser.parseEncryptedClaims(encryptedToken);

466

467

} catch (SecurityException e) {

468

// Decryption failed or key mismatch

469

handleDecryptionFailure(e);

470

471

} catch (Exception e) {

472

// Other encryption-related errors

473

handleGeneralEncryptionError(e);

474

}

475

```

476

477

## Content Type Handling

478

479

### String Content

480

481

```java { .api }

482

// Parse JWT with string content

483

JwtParser contentParser = Jwts.parser()

484

.verifyWith(secretKey)

485

.build();

486

487

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

488

String content = contentJws.getPayload();

489

490

// Handle different content types based on header

491

String contentType = contentJws.getHeader().getContentType();

492

if ("application/json".equals(contentType)) {

493

JsonObject json = parseJson(content);

494

} else if ("text/plain".equals(contentType)) {

495

String plainText = content;

496

}

497

```

498

499

### Binary Content

500

501

```java { .api }

502

// Parse JWT with binary content

503

Jws<byte[]> binaryJws = contentParser.parseSignedContent(binaryContentToken);

504

byte[] binaryContent = binaryJws.getPayload();

505

506

// Process based on content type

507

String contentType = binaryJws.getHeader().getContentType();

508

if ("application/pdf".equals(contentType)) {

509

processPdfContent(binaryContent);

510

} else if ("image/jpeg".equals(contentType)) {

511

processImageContent(binaryContent);

512

}

513

```

514

515

## Multi-Key Scenarios

516

517

### Key Rotation Support

518

519

```java { .api }

520

import java.util.List;

521

522

// Support multiple verification keys for key rotation

523

List<SecretKey> rotationKeys = Arrays.asList(currentKey, previousKey, oldKey);

524

525

Locator<Key> rotationLocator = header -> {

526

String keyId = header.getKeyId();

527

528

// Try keys in order of preference

529

for (SecretKey key : rotationKeys) {

530

if (keyMatches(key, keyId)) {

531

return key;

532

}

533

}

534

535

throw new SecurityException("No valid key found for keyId: " + keyId);

536

};

537

538

JwtParser rotationParser = Jwts.parser()

539

.keyLocator(rotationLocator)

540

.build();

541

```

542

543

### Multi-Tenant Key Management

544

545

```java { .api }

546

// Tenant-specific key resolution

547

Locator<Key> tenantKeyLocator = header -> {

548

String keyId = header.getKeyId();

549

String tenantId = extractTenantFromKeyId(keyId);

550

551

return getTenantVerificationKey(tenantId, keyId);

552

};

553

554

JwtParser tenantParser = Jwts.parser()

555

.keyLocator(tenantKeyLocator)

556

.build();

557

558

// Parse tenant-specific tokens

559

Jws<Claims> tenantJws = tenantParser.parseSignedClaims(tenantToken);

560

String tenantId = tenantJws.getPayload().get("tenant_id", String.class);

561

```

562

563

## Provider and Serialization Configuration

564

565

### JCA Provider Configuration

566

567

```java { .api }

568

import java.security.Provider;

569

import org.bouncycastle.jce.provider.BouncyCastleProvider;

570

571

// Use specific JCA provider

572

Provider bcProvider = new BouncyCastleProvider();

573

574

JwtParser providerParser = Jwts.parser()

575

.provider(bcProvider)

576

.verifyWith(secretKey)

577

.build();

578

579

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

580

```

581

582

### JSON Deserialization

583

584

```java { .api }

585

import io.jsonwebtoken.io.Deserializer;

586

import io.jsonwebtoken.jackson.io.JacksonDeserializer;

587

588

// Custom JSON deserializer

589

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

590

591

JwtParser jsonParser = Jwts.parser()

592

.json(deserializer)

593

.verifyWith(secretKey)

594

.build();

595

596

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

597

```

598

599

## Parsing Performance Optimization

600

601

### Parser Reuse

602

603

```java { .api }

604

// Create parser once and reuse (thread-safe)

605

JwtParser reusableParser = Jwts.parser()

606

.verifyWith(secretKey)

607

.clockSkewSeconds(30)

608

.build();

609

610

// Reuse across multiple parsing operations

611

public Claims parseUserToken(String token) {

612

return reusableParser.parseSignedClaims(token).getPayload();

613

}

614

615

public Claims parseServiceToken(String token) {

616

return reusableParser.parseSignedClaims(token).getPayload();

617

}

618

```

619

620

### Batch Processing

621

622

```java { .api }

623

// Process multiple tokens efficiently

624

List<String> tokens = getTokenBatch();

625

JwtParser batchParser = Jwts.parser()

626

.keyLocator(efficientKeyLocator)

627

.build();

628

629

List<Claims> claimsList = tokens.stream()

630

.map(token -> {

631

try {

632

return batchParser.parseSignedClaims(token).getPayload();

633

} catch (Exception e) {

634

logParsingError(token, e);

635

return null;

636

}

637

})

638

.filter(Objects::nonNull)

639

.collect(Collectors.toList());

640

```

641

642

## Unsecured JWT Handling

643

644

### Allowing Unsecured JWTs

645

646

```java { .api }

647

// Allow both secured and unsecured JWTs

648

JwtParser flexibleParser = Jwts.parser()

649

.unsecured() // Allow unsecured JWTs

650

.verifyWith(secretKey) // But verify if signature present

651

.build();

652

653

// Parse any type of JWT

654

Object result = flexibleParser.parse(unknownToken);

655

if (result instanceof Jws) {

656

Jws<Claims> jws = (Jws<Claims>) result;

657

Claims verifiedClaims = jws.getPayload();

658

} else if (result instanceof Jwt) {

659

Jwt<Claims> jwt = (Jwt<Claims>) result;

660

Claims unverifiedClaims = jwt.getPayload();

661

}

662

```

663

664

### Unsecured Decompression

665

666

```java { .api }

667

// Allow decompression for unsecured JWTs (use with caution)

668

JwtParser decompressParser = Jwts.parser()

669

.unsecured()

670

.unsecuredDecompression() // Allow decompression of unsecured JWTs

671

.build();

672

673

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

674

```

675

676

## Exception Handling

677

678

### JWT Exception Types

679

680

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

681

682

```java { .api }

683

import io.jsonwebtoken.JwtException;

684

import io.jsonwebtoken.MalformedJwtException;

685

import io.jsonwebtoken.ExpiredJwtException;

686

import io.jsonwebtoken.PrematureJwtException;

687

import io.jsonwebtoken.UnsupportedJwtException;

688

import io.jsonwebtoken.InvalidClaimException;

689

import io.jsonwebtoken.MissingClaimException;

690

import io.jsonwebtoken.IncorrectClaimException;

691

import io.jsonwebtoken.RequiredTypeException;

692

import io.jsonwebtoken.security.SecurityException;

693

import io.jsonwebtoken.security.SignatureException;

694

695

/**

696

* Base class for JWT-related runtime exceptions.

697

*/

698

public class JwtException extends RuntimeException;

699

700

/**

701

* Exception indicating that a JWT string is not in the proper three-part format.

702

*/

703

public class MalformedJwtException extends JwtException;

704

705

/**

706

* Exception indicating that a JWT is expired and therefore not valid.

707

*/

708

public class ExpiredJwtException extends ClaimJwtException;

709

710

/**

711

* Exception indicating that a JWT is not yet valid (nbf claim).

712

*/

713

public class PrematureJwtException extends ClaimJwtException;

714

715

/**

716

* Exception indicating an unsupported JWT type or algorithm.

717

*/

718

public class UnsupportedJwtException extends JwtException;

719

720

/**

721

* Exception indicating a claim validation failure.

722

*/

723

public class InvalidClaimException extends ClaimJwtException;

724

725

/**

726

* Exception indicating a required claim is missing.

727

*/

728

public class MissingClaimException extends InvalidClaimException;

729

730

/**

731

* Exception indicating a claim has an incorrect value.

732

*/

733

public class IncorrectClaimException extends InvalidClaimException;

734

735

/**

736

* Exception indicating incorrect type conversion.

737

*/

738

public class RequiredTypeException extends JwtException;

739

740

/**

741

* Base class for security-related exceptions.

742

*/

743

public class SecurityException extends JwtException;

744

745

/**

746

* Exception indicating JWT signature verification failure.

747

*/

748

public class SignatureException extends SecurityException;

749

```

750

751

### Exception Handling Patterns

752

753

```java { .api }

754

// Comprehensive error handling

755

public Claims parseAndValidateToken(String token, SecretKey key) {

756

JwtParser parser = Jwts.parser()

757

.verifyWith(key)

758

.build();

759

760

try {

761

Jws<Claims> jws = parser.parseSignedClaims(token);

762

return jws.getPayload();

763

764

} catch (ExpiredJwtException e) {

765

// Token has expired

766

Date expiration = e.getClaims().getExpiration();

767

throw new TokenExpiredException("Token expired at: " + expiration);

768

769

} catch (PrematureJwtException e) {

770

// Token not yet valid

771

Date notBefore = e.getClaims().getNotBefore();

772

throw new TokenNotYetValidException("Token not valid until: " + notBefore);

773

774

} catch (MalformedJwtException e) {

775

// Token format is invalid

776

throw new InvalidTokenFormatException("Invalid JWT format: " + e.getMessage());

777

778

} catch (SignatureException e) {

779

// Signature verification failed

780

throw new InvalidSignatureException("JWT signature verification failed");

781

782

} catch (MissingClaimException e) {

783

// Required claim is missing

784

String claimName = e.getClaimName();

785

throw new MissingRequiredClaimException("Missing required claim: " + claimName);

786

787

} catch (IncorrectClaimException e) {

788

// Claim has wrong value

789

String claimName = e.getClaimName();

790

Object expectedValue = e.getExpectedValue();

791

Object actualValue = e.getActualValue();

792

throw new InvalidClaimValueException(

793

"Claim '" + claimName + "' expected '" + expectedValue +

794

"' but was '" + actualValue + "'");

795

796

} catch (UnsupportedJwtException e) {

797

// Unsupported JWT type

798

throw new UnsupportedTokenException("Unsupported JWT: " + e.getMessage());

799

800

} catch (RequiredTypeException e) {

801

// Type conversion failed

802

throw new TypeConversionException("Failed to convert claim type: " + e.getMessage());

803

804

} catch (JwtException e) {

805

// General JWT error

806

throw new TokenProcessingException("JWT processing error: " + e.getMessage());

807

}

808

}

809

```

810

811

### Specific Exception Handling

812

813

```java { .api }

814

// Handle specific validation scenarios

815

public void handleExpirationWithGracePeriod(String token, SecretKey key) {

816

try {

817

JwtParser parser = Jwts.parser()

818

.verifyWith(key)

819

.clockSkewSeconds(30) // 30 second grace period

820

.build();

821

822

Jws<Claims> jws = parser.parseSignedClaims(token);

823

processValidToken(jws.getPayload());

824

825

} catch (ExpiredJwtException e) {

826

Claims expiredClaims = e.getClaims();

827

Date expiration = expiredClaims.getExpiration();

828

long gracePeriodMs = 60 * 1000; // 1 minute additional grace

829

830

if (System.currentTimeMillis() - expiration.getTime() < gracePeriodMs) {

831

// Within extended grace period

832

processValidToken(expiredClaims);

833

} else {

834

throw new TokenDefinitelyExpiredException("Token expired beyond grace period");

835

}

836

}

837

}

838

839

// Extract claims from expired tokens for logging

840

public void logTokenDetails(String token) {

841

try {

842

// This will throw ExpiredJwtException but still provide claims

843

Jwts.parser().verifyWith(key).build().parseSignedClaims(token);

844

845

} catch (ExpiredJwtException e) {

846

// Can still access claims from expired token

847

Claims claims = e.getClaims();

848

String subject = claims.getSubject();

849

Date expiration = claims.getExpiration();

850

851

log.info("Expired token - Subject: {}, Expired: {}", subject, expiration);

852

853

} catch (JwtException e) {

854

log.error("Token parsing failed: {}", e.getMessage());

855

}

856

}

857

```

858

859

### Custom Exception Handling

860

861

```java { .api }

862

// Custom exception handler for multi-tenant scenarios

863

public class TenantAwareJwtHandler {

864

865

public Claims parseToken(String token, String tenantId) {

866

try {

867

SecretKey tenantKey = getTenantKey(tenantId);

868

869

JwtParser parser = Jwts.parser()

870

.verifyWith(tenantKey)

871

.require("tenant_id", tenantId) // Require specific tenant

872

.build();

873

874

return parser.parseSignedClaims(token).getPayload();

875

876

} catch (IncorrectClaimException e) {

877

if ("tenant_id".equals(e.getClaimName())) {

878

throw new InvalidTenantException(

879

"Token belongs to different tenant: " + e.getActualValue());

880

}

881

throw e;

882

883

} catch (MissingClaimException e) {

884

if ("tenant_id".equals(e.getClaimName())) {

885

throw new InvalidTenantException("Token missing tenant claim");

886

}

887

throw e;

888

}

889

}

890

891

private SecretKey getTenantKey(String tenantId) {

892

// Retrieve tenant-specific key

893

return tenantKeyRepository.getKey(tenantId);

894

}

895

}

896

```

897

898

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