0
# Types and Interfaces
1
2
This document covers the core JWT types including Claims, Headers, and token interfaces that represent parsed JWT content in JJWT API.
3
4
## JWT Token Types
5
6
### Base JWT Interface
7
8
```java { .api }
9
public interface Jwt<H, P> {
10
// Core Methods
11
H getHeader();
12
P getPayload();
13
<T> T accept(JwtVisitor<T> visitor);
14
15
// Static Visitor Constants for Unsecured JWTs
16
JwtVisitor<Jwt<Header, byte[]>> UNSECURED_CONTENT = /* visitor implementation */;
17
JwtVisitor<Jwt<Header, Claims>> UNSECURED_CLAIMS = /* visitor implementation */;
18
}
19
```
20
21
### Protected JWT Interface
22
23
```java { .api }
24
public interface ProtectedJwt<H extends ProtectedHeader, P> extends Jwt<H, P> {
25
// Base interface for cryptographically-protected JWTs (JWS and JWE)
26
}
27
```
28
29
### JSON Web Signature (JWS) Interface
30
31
```java { .api }
32
public interface Jws<P> extends ProtectedJwt<JwsHeader, P> {
33
// JWS-specific method
34
String getDigest();
35
36
// Static Visitor Constants for JWS
37
JwtVisitor<Jws<byte[]>> CONTENT = /* visitor implementation */;
38
JwtVisitor<Jws<Claims>> CLAIMS = /* visitor implementation */;
39
}
40
```
41
42
### JSON Web Encryption (JWE) Interface
43
44
```java { .api }
45
public interface Jwe<P> extends ProtectedJwt<JweHeader, P> {
46
// JWE extends ProtectedJwt but doesn't add specific methods
47
// All functionality inherited from base interfaces
48
}
49
```
50
51
### JWT Token Usage Examples
52
53
```java
54
import io.jsonwebtoken.*;
55
56
// Parse different JWT types and access content
57
JwtParser parser = Jwts.parser().verifyWith(key).build();
58
59
// Parse generic JWT (auto-detects type)
60
Jwt<?, ?> jwt = parser.parse(jwtString);
61
System.out.println("JWT type: " + jwt.getClass().getSimpleName());
62
63
// Parse specific JWS with Claims
64
Jws<Claims> jws = parser.parseSignedClaims(jwtString);
65
JwsHeader header = jws.getHeader();
66
Claims claims = jws.getPayload();
67
String signature = jws.getDigest();
68
69
System.out.println("Algorithm: " + header.getAlgorithm());
70
System.out.println("Subject: " + claims.getSubject());
71
System.out.println("Signature: " + signature);
72
73
// Use visitor pattern for type-safe processing
74
String result = jwt.accept(new JwtVisitor<String>() {
75
@Override
76
public String visit(Jwt<Header, byte[]> jwt) {
77
return "Unsecured JWT with " + jwt.getPayload().length + " bytes";
78
}
79
80
@Override
81
public String visit(Jwt<Header, Claims> jwt) {
82
return "Unsecured JWT with subject: " + jwt.getPayload().getSubject();
83
}
84
85
@Override
86
public String visit(Jws<byte[]> jws) {
87
return "Signed JWT with " + jws.getPayload().length + " bytes";
88
}
89
90
@Override
91
public String visit(Jws<Claims> jws) {
92
return "Signed JWT with subject: " + jws.getPayload().getSubject();
93
}
94
95
@Override
96
public String visit(Jwe<byte[]> jwe) {
97
return "Encrypted JWT with " + jwe.getPayload().length + " bytes";
98
}
99
100
@Override
101
public String visit(Jwe<Claims> jwe) {
102
return "Encrypted JWT with subject: " + jwe.getPayload().getSubject();
103
}
104
});
105
```
106
107
## Header Types
108
109
### Base Header Interface
110
111
```java { .api }
112
public interface Header extends Map<String, Object> {
113
// Standard Header Parameters
114
String getType();
115
String getContentType();
116
String getAlgorithm();
117
String getCompressionAlgorithm();
118
119
// Standard Header Parameter Names
120
String TYPE = "typ";
121
String CONTENT_TYPE = "cty";
122
String ALGORITHM = "alg";
123
String COMPRESSION_ALGORITHM = "zip";
124
}
125
```
126
127
### Protected Header Interface
128
129
```java { .api }
130
public interface ProtectedHeader extends Header, X509Accessor {
131
// Additional Protected Header Parameters
132
String getKeyId();
133
Set<String> getCritical();
134
135
// Additional Parameter Names
136
String KEY_ID = "kid";
137
String CRITICAL = "crit";
138
}
139
```
140
141
### JWS Header Interface
142
143
```java { .api }
144
public interface JwsHeader extends ProtectedHeader {
145
// RFC 7797 Unencoded Payload Support
146
boolean isPayloadEncoded();
147
148
// Parameter Name
149
String PAYLOAD_ENCODED = "b64";
150
}
151
```
152
153
### JWE Header Interface
154
155
```java { .api }
156
public interface JweHeader extends ProtectedHeader {
157
// JWE-specific Header Parameters
158
String getEncryptionAlgorithm();
159
String getInitializationVector();
160
String getAuthenticationTag();
161
String getEphemeralPublicKey();
162
String getAgreementPartyUInfo();
163
String getAgreementPartyVInfo();
164
Integer getPbes2Count();
165
String getPbes2Salt();
166
167
// JWE Parameter Names
168
String ENCRYPTION_ALGORITHM = "enc";
169
String INITIALIZATION_VECTOR = "iv";
170
String AUTHENTICATION_TAG = "tag";
171
String EPHEMERAL_PUBLIC_KEY = "epk";
172
String AGREEMENT_PARTY_U_INFO = "apu";
173
String AGREEMENT_PARTY_V_INFO = "apv";
174
String PBES2_COUNT = "p2c";
175
String PBES2_SALT = "p2s";
176
}
177
```
178
179
### Header Usage Examples
180
181
```java
182
import io.jsonwebtoken.*;
183
184
// Access header information from parsed JWT
185
Jws<Claims> jws = parser.parseSignedClaims(jwtString);
186
JwsHeader header = jws.getHeader();
187
188
// Standard header parameters
189
String algorithm = header.getAlgorithm(); // "RS256"
190
String type = header.getType(); // "JWT"
191
String keyId = header.getKeyId(); // "key-1"
192
String contentType = header.getContentType(); // null (typically)
193
194
// Check for RFC 7797 unencoded payload
195
boolean isPayloadEncoded = header.isPayloadEncoded(); // true (default)
196
197
// Access custom header parameters
198
Object customParam = header.get("custom");
199
200
// JWE header example
201
Jwe<Claims> jwe = parser.parseEncryptedClaims(jweString);
202
JweHeader jweHeader = jwe.getHeader();
203
204
String encAlgorithm = jweHeader.getEncryptionAlgorithm(); // "A256GCM"
205
String keyAlgorithm = jweHeader.getAlgorithm(); // "RSA-OAEP"
206
```
207
208
## Claims Interface
209
210
### Core Claims Interface
211
212
```java { .api }
213
public interface Claims extends Map<String, Object> {
214
// Standard Claims Accessors
215
String getIssuer();
216
String getSubject();
217
Set<String> getAudience();
218
Date getExpiration();
219
Date getNotBefore();
220
Date getIssuedAt();
221
String getId();
222
223
// Type-safe Claim Access
224
<T> T get(String claimName, Class<T> requiredType);
225
226
// Standard Claim Names
227
String ISSUER = "iss";
228
String SUBJECT = "sub";
229
String AUDIENCE = "aud";
230
String EXPIRATION = "exp";
231
String NOT_BEFORE = "nbf";
232
String ISSUED_AT = "iat";
233
String ID = "jti";
234
}
235
```
236
237
### Claims Builder Interface
238
239
```java { .api }
240
public interface ClaimsBuilder extends MapMutator<String, Object, ClaimsBuilder>, ClaimsMutator<ClaimsBuilder> {
241
// Inherits methods from MapMutator and ClaimsMutator
242
Claims build();
243
}
244
```
245
246
### Claims Mutator Interface
247
248
```java { .api }
249
public interface ClaimsMutator<T> {
250
// Standard Claims Mutators
251
T issuer(String iss);
252
T subject(String sub);
253
T audience(String aud);
254
T audiences(String... audiences);
255
T expiration(Date exp);
256
T notBefore(Date nbf);
257
T issuedAt(Date iat);
258
T id(String jti);
259
}
260
```
261
262
### Claims Usage Examples
263
264
```java
265
import io.jsonwebtoken.*;
266
import java.util.Date;
267
import java.util.Set;
268
269
// Parse JWT and access claims
270
Jws<Claims> jws = parser.parseSignedClaims(jwtString);
271
Claims claims = jws.getPayload();
272
273
// Standard claims
274
String issuer = claims.getIssuer(); // "https://auth.example.com"
275
String subject = claims.getSubject(); // "user123"
276
Set<String> audience = claims.getAudience(); // ["web-app", "mobile-app"]
277
Date expiration = claims.getExpiration(); // expiration timestamp
278
Date notBefore = claims.getNotBefore(); // not-before timestamp
279
Date issuedAt = claims.getIssuedAt(); // issued-at timestamp
280
String jti = claims.getId(); // "unique-token-id"
281
282
// Type-safe custom claim access
283
String role = claims.get("role", String.class);
284
Integer userId = claims.get("user_id", Integer.class);
285
List<String> permissions = claims.get("permissions", List.class);
286
287
// Check for claim existence
288
if (claims.containsKey("department")) {
289
String department = claims.get("department", String.class);
290
}
291
292
// Iterate over all claims
293
for (Map.Entry<String, Object> entry : claims.entrySet()) {
294
System.out.println(entry.getKey() + ": " + entry.getValue());
295
}
296
297
// Create claims using builder
298
Claims customClaims = Jwts.claims()
299
.issuer("myapp")
300
.subject("user456")
301
.audience("api")
302
.expiration(new Date(System.currentTimeMillis() + 3600000))
303
.add("role", "admin")
304
.add("permissions", Arrays.asList("read", "write", "delete"))
305
.build();
306
```
307
308
## Visitor Pattern Support
309
310
### JWT Visitor Interface
311
312
```java { .api }
313
public interface JwtVisitor<T> {
314
T visit(Jwt<Header, byte[]> jwt);
315
T visit(Jwt<Header, Claims> jwt);
316
T visit(Jws<byte[]> jws);
317
T visit(Jws<Claims> jws);
318
T visit(Jwe<byte[]> jwe);
319
T visit(Jwe<Claims> jwe);
320
}
321
```
322
323
### Supported JWT Visitor
324
325
```java { .api }
326
public class SupportedJwtVisitor<T> implements JwtVisitor<T> {
327
// Base implementation that throws UnsupportedJwtException for unsupported types
328
// Subclasses override only methods for supported JWT types
329
}
330
```
331
332
### JWT Handler Interface (Alternative Pattern)
333
334
```java { .api }
335
public interface JwtHandler<T> {
336
T onUnsecuredContent(Jwt<Header, byte[]> jwt);
337
T onUnsecuredClaims(Jwt<Header, Claims> jwt);
338
T onSignedContent(Jws<byte[]> jws);
339
T onSignedClaims(Jws<Claims> jws);
340
T onEncryptedContent(Jwe<byte[]> jwe);
341
T onEncryptedClaims(Jwe<Claims> jwe);
342
}
343
```
344
345
### JWT Handler Adapter
346
347
```java { .api }
348
public class JwtHandlerAdapter<T> implements JwtHandler<T> {
349
// Default implementation that throws UnsupportedJwtException
350
// Subclasses override only methods for supported JWT types
351
}
352
```
353
354
### Visitor Pattern Examples
355
356
```java
357
import io.jsonwebtoken.*;
358
359
// Custom visitor to extract information
360
public class JwtInfoVisitor implements JwtVisitor<String> {
361
@Override
362
public String visit(Jwt<Header, byte[]> jwt) {
363
return "Unsecured JWT with byte payload, size: " + jwt.getPayload().length;
364
}
365
366
@Override
367
public String visit(Jwt<Header, Claims> jwt) {
368
Claims claims = jwt.getPayload();
369
return "Unsecured JWT, subject: " + claims.getSubject();
370
}
371
372
@Override
373
public String visit(Jws<byte[]> jws) {
374
return "Signed JWT (" + jws.getHeader().getAlgorithm() + ") with byte payload";
375
}
376
377
@Override
378
public String visit(Jws<Claims> jws) {
379
Claims claims = jws.getPayload();
380
return "Signed JWT, subject: " + claims.getSubject() +
381
", algorithm: " + jws.getHeader().getAlgorithm();
382
}
383
384
@Override
385
public String visit(Jwe<byte[]> jwe) {
386
return "Encrypted JWT with byte payload";
387
}
388
389
@Override
390
public String visit(Jwe<Claims> jwe) {
391
Claims claims = jwe.getPayload();
392
return "Encrypted JWT, subject: " + claims.getSubject();
393
}
394
}
395
396
// Use the visitor
397
Jwt<?, ?> jwt = parser.parse(jwtString);
398
String info = jwt.accept(new JwtInfoVisitor());
399
System.out.println(info);
400
401
// Using SupportedJwtVisitor for specific JWT types only
402
public class ClaimsExtractor extends SupportedJwtVisitor<Claims> {
403
@Override
404
public Claims visit(Jwt<Header, Claims> jwt) {
405
return jwt.getPayload();
406
}
407
408
@Override
409
public Claims visit(Jws<Claims> jws) {
410
return jws.getPayload();
411
}
412
413
@Override
414
public Claims visit(Jwe<Claims> jwe) {
415
return jwe.getPayload();
416
}
417
418
// Byte payload visits will throw UnsupportedJwtException
419
}
420
421
// Extract claims regardless of JWT type
422
Claims claims = jwt.accept(new ClaimsExtractor());
423
```
424
425
## Utility Interfaces
426
427
### Locator Interface
428
429
```java { .api }
430
public interface Locator<T> {
431
T locate(Header header);
432
}
433
```
434
435
### Locator Adapter
436
437
```java { .api }
438
public abstract class LocatorAdapter<T> implements Locator<T> {
439
@Override
440
public T locate(Header header) {
441
return null; // Default implementation
442
}
443
}
444
```
445
446
### Key Resolution Examples
447
448
```java
449
import io.jsonwebtoken.security.SigningKeyResolver;
450
451
// Dynamic key resolution based on header information
452
public class CustomKeyLocator implements Locator<Key> {
453
private final KeyService keyService;
454
455
public CustomKeyLocator(KeyService keyService) {
456
this.keyService = keyService;
457
}
458
459
@Override
460
public Key locate(Header header) {
461
String keyId = header instanceof ProtectedHeader
462
? ((ProtectedHeader) header).getKeyId()
463
: null;
464
465
String algorithm = header.getAlgorithm();
466
467
if (keyId != null) {
468
return keyService.getKeyById(keyId);
469
} else if ("HS256".equals(algorithm)) {
470
return keyService.getDefaultHmacKey();
471
} else {
472
throw new IllegalArgumentException("Cannot locate key for algorithm: " + algorithm);
473
}
474
}
475
}
476
477
// Use with parser
478
JwtParser parser = Jwts.parser()
479
.keyLocator(new CustomKeyLocator(keyService))
480
.build();
481
```
482
483
## Exception Types
484
485
### Claim-Related Exceptions
486
487
```java { .api }
488
public class ClaimJwtException extends JwtException {
489
// Base exception for claim validation failures
490
public ClaimJwtException(Header header, Claims claims, String message);
491
public ClaimJwtException(Header header, Claims claims, String message, Throwable cause);
492
493
public Header getHeader();
494
public Claims getClaims();
495
}
496
497
public class IncorrectClaimException extends ClaimJwtException {
498
// Claim has incorrect value
499
public IncorrectClaimException(Header header, Claims claims, String claimName, Object expectedValue, Object actualValue);
500
501
public String getClaimName();
502
public Object getExpectedValue();
503
public Object getActualValue();
504
}
505
506
public class MissingClaimException extends ClaimJwtException {
507
// Required claim is missing
508
public MissingClaimException(Header header, Claims claims, String claimName);
509
510
public String getClaimName();
511
}
512
513
public class InvalidClaimException extends ClaimJwtException {
514
// Claim value is invalid (e.g., malformed date)
515
public InvalidClaimException(Header header, Claims claims, String message);
516
}
517
```
518
519
### JWT Validation Exceptions
520
521
```java { .api }
522
public class ExpiredJwtException extends ClaimJwtException {
523
// JWT has expired
524
public ExpiredJwtException(Header header, Claims claims, String message);
525
}
526
527
public class PrematureJwtException extends ClaimJwtException {
528
// JWT is not yet valid (nbf claim)
529
public PrematureJwtException(Header header, Claims claims, String message);
530
}
531
532
public class RequiredTypeException extends JwtException {
533
// Type conversion failed
534
public RequiredTypeException(String message);
535
}
536
```
537
538
### Exception Handling Examples
539
540
```java
541
import io.jsonwebtoken.*;
542
543
try {
544
Jws<Claims> jws = parser.parseSignedClaims(jwtString);
545
Claims claims = jws.getPayload();
546
547
// JWT is valid, process claims
548
processValidJwt(claims);
549
550
} catch (ExpiredJwtException e) {
551
System.err.println("JWT expired at: " + e.getClaims().getExpiration());
552
// Handle expired token
553
554
} catch (PrematureJwtException e) {
555
System.err.println("JWT not valid until: " + e.getClaims().getNotBefore());
556
// Handle premature token
557
558
} catch (MissingClaimException e) {
559
System.err.println("Missing required claim: " + e.getClaimName());
560
// Handle missing claim
561
562
} catch (IncorrectClaimException e) {
563
System.err.println("Incorrect claim '" + e.getClaimName() +
564
"': expected '" + e.getExpectedValue() +
565
"', got '" + e.getActualValue() + "'");
566
// Handle incorrect claim
567
568
} catch (SignatureException e) {
569
System.err.println("JWT signature validation failed");
570
// Handle signature failure
571
572
} catch (MalformedJwtException e) {
573
System.err.println("JWT is malformed: " + e.getMessage());
574
// Handle malformed JWT
575
576
} catch (JwtException e) {
577
System.err.println("JWT processing failed: " + e.getMessage());
578
// Handle other JWT exceptions
579
}
580
```
581
582
## Type Conversion Utilities
583
584
### Safe Type Extraction
585
586
```java
587
import io.jsonwebtoken.Claims;
588
589
public class ClaimsUtils {
590
public static <T> T getClaimSafely(Claims claims, String claimName, Class<T> type, T defaultValue) {
591
try {
592
T value = claims.get(claimName, type);
593
return value != null ? value : defaultValue;
594
} catch (RequiredTypeException e) {
595
return defaultValue;
596
}
597
}
598
599
public static List<String> getStringList(Claims claims, String claimName) {
600
Object value = claims.get(claimName);
601
if (value instanceof List) {
602
List<?> list = (List<?>) value;
603
return list.stream()
604
.filter(String.class::isInstance)
605
.map(String.class::cast)
606
.collect(Collectors.toList());
607
}
608
return Collections.emptyList();
609
}
610
611
public static Date getDateClaim(Claims claims, String claimName) {
612
Object value = claims.get(claimName);
613
if (value instanceof Date) {
614
return (Date) value;
615
} else if (value instanceof Number) {
616
return new Date(((Number) value).longValue() * 1000);
617
}
618
return null;
619
}
620
}
621
622
// Usage
623
Claims claims = jws.getPayload();
624
String role = ClaimsUtils.getClaimSafely(claims, "role", String.class, "user");
625
List<String> permissions = ClaimsUtils.getStringList(claims, "permissions");
626
Date customDate = ClaimsUtils.getDateClaim(claims, "custom_date");
627
```