Skip to content

Commit d8064d2

Browse files
authored
Merge pull request auth0#100 from auth0/custom-header-claims
Support for custom Header claims
2 parents e5e7c75 + 6ea25dc commit d8064d2

File tree

11 files changed

+171
-20
lines changed

11 files changed

+171
-20
lines changed

README.md

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,6 @@ try {
9393
.withIssuer("auth0")
9494
.build(); //Reusable verifier instance
9595
JWT jwt = verifier.verify(token);
96-
} catch (JWTDecodeException exception){
97-
//Invalid token
9896
} catch (JWTVerificationException exception){
9997
//Invalid signature/claims
10098
}
@@ -110,14 +108,11 @@ try {
110108
.withIssuer("auth0")
111109
.build(); //Reusable verifier instance
112110
JWT jwt = verifier.verify(token);
113-
} catch (JWTDecodeException exception){
114-
//Invalid token
115111
} catch (JWTVerificationException exception){
116112
//Invalid signature/claims
117113
}
118114
```
119115

120-
If the token has an invalid syntax or the header or payload are not JSONs, a `JWTDecodeException` will raise.
121116
If the token has an invalid signature or the Claim requirement is not met, a `JWTVerificationException` will raise.
122117

123118

@@ -148,67 +143,110 @@ JWTVerifier verifier = JWT.require(Algorithm.RSA256(key))
148143
```
149144

150145

151-
### Registered Claims
146+
### Header Claims
147+
148+
#### Algorithm ("alg")
149+
150+
Returns the Algorithm value or null if it's not defined in the Header.
151+
152+
```java
153+
String algorithm = jwt.getAlgorithm();
154+
```
155+
156+
#### Type ("typ")
157+
158+
Returns the Type value or null if it's not defined in the Header.
159+
160+
```java
161+
String type = jwt.getType();
162+
```
163+
164+
#### Content Type ("cty")
165+
166+
Returns the Content Type value or null if it's not defined in the Header.
167+
168+
```java
169+
String contentType = jwt.getContentType();
170+
```
171+
172+
#### Key Id ("kid")
173+
174+
Returns the Key Id value or null if it's not defined in the Header.
175+
176+
```java
177+
String keyId = jwt.getKeyId();
178+
```
179+
180+
#### Private Claims
181+
182+
Additional Claims defined in the token's Header can be obtained by calling `getHeaderClaim()` and passing the Claim name. A Claim will always be returned, even if it can't be found. You should always check for null values.
183+
184+
```java
185+
Claim claim = jwt.getHeaderClaim("owner");
186+
```
187+
188+
189+
### Payload Claims
152190

153191
#### Issuer ("iss")
154192

155-
Returns the Issuer value or null if it's not defined.
193+
Returns the Issuer value or null if it's not defined in the Payload.
156194

157195
```java
158196
String issuer = jwt.getIssuer();
159197
```
160198

161199
#### Subject ("sub")
162200

163-
Returns the Subject value or null if it's not defined.
201+
Returns the Subject value or null if it's not defined in the Payload.
164202

165203
```java
166204
String subject = jwt.getSubject();
167205
```
168206

169207
#### Audience ("aud")
170208

171-
Returns the Audience value in or null if it's not defined.
209+
Returns the Audience value in or null if it's not defined in the Payload.
172210

173211
```java
174212
String[] audience = jwt.getAudience();
175213
```
176214

177215
#### Expiration Time ("exp")
178216

179-
Returns the Expiration Time value or null if it's not defined.
217+
Returns the Expiration Time value or null if it's not defined in the Payload.
180218

181219
```java
182220
Date expiresAt = jwt.getExpiresAt();
183221
```
184222

185223
#### Not Before ("nbf")
186224

187-
Returns the Not Before value or null if it's not defined.
225+
Returns the Not Before value or null if it's not defined in the Payload.
188226

189227
```java
190228
Date notBefore = jwt.getNotBefore();
191229
```
192230

193231
#### Issued At ("iat")
194232

195-
Returns the Issued At value or null if it's not defined.
233+
Returns the Issued At value or null if it's not defined in the Payload.
196234

197235
```java
198236
Date issuedAt = jwt.getIssuedAt();
199237
```
200238

201239
#### JWT ID ("jti")
202240

203-
Returns the JWT ID value or null if it's not defined.
241+
Returns the JWT ID value or null if it's not defined in the Payload.
204242

205243
```java
206244
String id = jwt.getId();
207245
```
208246

209-
### Private Claims
247+
#### Private Claims
210248

211-
Additional Claims defined in the token can be obtained by calling `getClaim()` and passing the Claim name. A Claim will always be returned, even if it can't be found. You should always check for null values.
249+
Additional Claims defined in the token's Payload can be obtained by calling `getClaim()` and passing the Claim name. A Claim will always be returned, even if it can't be found. You should always check for null values.
212250

213251
```java
214252
Claim claim = jwt.getClaim("isAdmin");

lib/src/main/java/com/auth0/jwt/JWT.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ public Claim getClaim(String name) {
9191
return jwt.getClaim(name);
9292
}
9393

94+
@Override
95+
public Claim getHeaderClaim(String name) {
96+
return jwt.getHeaderClaim(name);
97+
}
98+
9499
@Override
95100
public String getAlgorithm() {
96101
return jwt.getAlgorithm();
@@ -105,4 +110,9 @@ public String getType() {
105110
public String getContentType() {
106111
return jwt.getContentType();
107112
}
113+
114+
@Override
115+
public String getKeyId() {
116+
return jwt.getKeyId();
117+
}
108118
}

lib/src/main/java/com/auth0/jwt/JWTDecoder.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,16 @@ public String getContentType() {
6767
return header.getContentType();
6868
}
6969

70+
@Override
71+
public String getKeyId() {
72+
return header.getKeyId();
73+
}
74+
75+
@Override
76+
public Claim getHeaderClaim(String name) {
77+
return header.getHeaderClaim(name);
78+
}
79+
7080
@Override
7181
public String getIssuer() {
7282
return payload.getIssuer();

lib/src/main/java/com/auth0/jwt/JWTVerifier.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public Verification withJWTId(String jwtId) {
162162
/**
163163
* Require a specific Claim value.
164164
*
165-
* @param name the Claim's name
165+
* @param name the Claim's name
166166
* @param value the Claim's value. Must be an instance of Integer, Double, Boolean, Date or String class.
167167
* @return this same Verification instance.
168168
* @throws IllegalArgumentException if the name is null or the value class is not allowed.
@@ -229,10 +229,9 @@ private void requireClaim(String name, Object value) {
229229
*
230230
* @param token the String representation of the JWT.
231231
* @return a verified JWT.
232-
* @throws JWTDecodeException if any part of the Token contained an invalid JWT or JSON format.
233232
* @throws JWTVerificationException if any of the required contents inside the JWT is invalid.
234233
*/
235-
public JWT verify(String token) throws JWTDecodeException, JWTVerificationException {
234+
public JWT verify(String token) throws JWTVerificationException {
236235
JWT jwt = new JWT(JWTDecoder.decode(token));
237236
verifyAlgorithm(jwt, algorithm);
238237
verifySignature(TokenUtils.splitToken(token));

lib/src/main/java/com/auth0/jwt/exceptions/JWTDecodeException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.auth0.jwt.exceptions;
22

3-
public class JWTDecodeException extends RuntimeException {
3+
public class JWTDecodeException extends JWTVerificationException {
44
public JWTDecodeException(String message) {
55
this(message, null);
66
}

lib/src/main/java/com/auth0/jwt/impl/HeaderImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.auth0.jwt.impl;
22

3+
import com.auth0.jwt.interfaces.Claim;
34
import com.auth0.jwt.interfaces.Header;
45
import com.fasterxml.jackson.databind.JsonNode;
56

@@ -38,4 +39,14 @@ public String getType() {
3839
public String getContentType() {
3940
return extractClaim(CONTENT_TYPE, tree).asString();
4041
}
42+
43+
@Override
44+
public String getKeyId() {
45+
return extractClaim(KEY_ID, tree).asString();
46+
}
47+
48+
@Override
49+
public Claim getHeaderClaim(String name) {
50+
return extractClaim(name, tree);
51+
}
4152
}

lib/src/main/java/com/auth0/jwt/impl/PublicClaims.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public abstract class PublicClaims {
77
public static final String ALGORITHM = "alg";
88
static final String CONTENT_TYPE = "cty";
99
static final String TYPE = "typ";
10+
static final String KEY_ID = "kid";
1011

1112
//Payload
1213
public static final String ISSUER = "iss";

lib/src/main/java/com/auth0/jwt/interfaces/Header.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,19 @@ public interface Header {
2626
*/
2727
String getContentType();
2828

29+
30+
/**
31+
* Get the value of the "kid" claim, or null if it's not available.
32+
*
33+
* @return the Key ID value or null.
34+
*/
35+
String getKeyId();
36+
37+
/**
38+
* Get a Private Claim given it's name. If the Claim wasn't specified in the Header, a BaseClaim will be returned.
39+
*
40+
* @param name the name of the Claim to retrieve.
41+
* @return a non-null Claim.
42+
*/
43+
Claim getHeaderClaim(String name);
2944
}

lib/src/main/java/com/auth0/jwt/interfaces/Payload.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public interface Payload {
5252
/**
5353
* Get the value of the "jti" claim, or null if it's not available.
5454
*
55-
* @return the Payload ID value or null.
55+
* @return the JWT ID value or null.
5656
*/
5757
String getId();
5858

lib/src/test/java/com/auth0/jwt/JWTTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,30 @@ public void shouldGetType() throws Exception {
307307
assertThat(jwt.getType(), is("JWS"));
308308
}
309309

310+
@Test
311+
public void shouldGetKeyId() throws Exception {
312+
String token = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtleSJ9.e30.von1Vt9tq9cn5ZYdX1f4cf2EE7fUvb5BCBlKOTm9YWs";
313+
JWT jwt = JWT.require(Algorithm.HMAC256("secret"))
314+
.build()
315+
.verify(token);
316+
317+
assertThat(jwt, is(notNullValue()));
318+
assertThat(jwt.getKeyId(), is("key"));
319+
}
320+
321+
@Test
322+
public void shouldGetCustomClaims() throws Exception {
323+
String token = "eyJhbGciOiJIUzI1NiIsImlzQWRtaW4iOnRydWV9.eyJpc0FkbWluIjoibm9wZSJ9.YDKBAgUDbh0PkhioDcLNzdQ8c2Gdf_yS6zdEtJQS3F0";
324+
JWT jwt = JWT.require(Algorithm.HMAC256("secret"))
325+
.build()
326+
.verify(token);
327+
328+
assertThat(jwt, is(notNullValue()));
329+
assertThat(jwt.getHeaderClaim("isAdmin"), notNullValue());
330+
assertThat(jwt.getHeaderClaim("isAdmin").asBoolean(), is(true));
331+
assertThat(jwt.getClaim("isAdmin"), notNullValue());
332+
assertThat(jwt.getClaim("isAdmin").asString(), is("nope"));
333+
}
310334

311335
// Sign
312336

0 commit comments

Comments
 (0)