Skip to content

Commit 6ea25dc

Browse files
committed
add header keyId and custom claims support
1 parent ae65a6d commit 6ea25dc

9 files changed

Lines changed: 168 additions & 11 deletions

File tree

README.md

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -143,67 +143,110 @@ JWTVerifier verifier = JWT.require(Algorithm.RSA256(key))
143143
```
144144

145145

146-
### 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
147190

148191
#### Issuer ("iss")
149192

150-
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.
151194

152195
```java
153196
String issuer = jwt.getIssuer();
154197
```
155198

156199
#### Subject ("sub")
157200

158-
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.
159202

160203
```java
161204
String subject = jwt.getSubject();
162205
```
163206

164207
#### Audience ("aud")
165208

166-
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.
167210

168211
```java
169212
String[] audience = jwt.getAudience();
170213
```
171214

172215
#### Expiration Time ("exp")
173216

174-
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.
175218

176219
```java
177220
Date expiresAt = jwt.getExpiresAt();
178221
```
179222

180223
#### Not Before ("nbf")
181224

182-
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.
183226

184227
```java
185228
Date notBefore = jwt.getNotBefore();
186229
```
187230

188231
#### Issued At ("iat")
189232

190-
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.
191234

192235
```java
193236
Date issuedAt = jwt.getIssuedAt();
194237
```
195238

196239
#### JWT ID ("jti")
197240

198-
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.
199242

200243
```java
201244
String id = jwt.getId();
202245
```
203246

204-
### Private Claims
247+
#### Private Claims
205248

206-
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.
207250

208251
```java
209252
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/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

lib/src/test/java/com/auth0/jwt/impl/HeaderImplTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.junit.rules.ExpectedException;
1010

1111
import java.util.HashMap;
12+
import java.util.Map;
1213

1314
import static org.hamcrest.MatcherAssert.assertThat;
1415
import static org.hamcrest.Matchers.*;
@@ -178,4 +179,46 @@ public void shouldGetNullContentTypeIfMissing() throws Exception {
178179
assertThat(header, is(notNullValue()));
179180
assertThat(header.getContentType(), is(nullValue()));
180181
}
182+
183+
@Test
184+
public void shouldGetKeyId() throws Exception {
185+
JsonNode kidNode = new TextNode("key");
186+
HashMap<String, JsonNode> tree = new HashMap<>();
187+
tree.put("kid", kidNode);
188+
HeaderImpl header = new HeaderImpl(tree);
189+
190+
assertThat(header, is(notNullValue()));
191+
assertThat(header.getKeyId(), is(notNullValue()));
192+
assertThat(header.getKeyId(), is("key"));
193+
}
194+
195+
@Test
196+
public void shouldGetNullKeyIdIfMissing() throws Exception {
197+
HashMap<String, JsonNode> tree = new HashMap<>();
198+
HeaderImpl header = new HeaderImpl(tree);
199+
200+
assertThat(header, is(notNullValue()));
201+
assertThat(header.getKeyId(), is(nullValue()));
202+
}
203+
204+
@Test
205+
public void shouldGetExtraClaim() throws Exception {
206+
Map<String, JsonNode> tree = new HashMap<>();
207+
tree.put("extraClaim", new TextNode("extraValue"));
208+
HeaderImpl header = new HeaderImpl(tree);
209+
210+
assertThat(header, is(notNullValue()));
211+
assertThat(header.getHeaderClaim("extraClaim"), is(instanceOf(ClaimImpl.class)));
212+
assertThat(header.getHeaderClaim("extraClaim").asString(), is("extraValue"));
213+
}
214+
215+
@Test
216+
public void shouldGetNotNullExtraClaimIfMissing() throws Exception {
217+
Map<String, JsonNode> tree = new HashMap<>();
218+
HeaderImpl header = new HeaderImpl(tree);
219+
220+
assertThat(header, is(notNullValue()));
221+
assertThat(header.getHeaderClaim("missing"), is(notNullValue()));
222+
assertThat(header.getHeaderClaim("missing"), is(instanceOf(BaseClaim.class)));
223+
}
181224
}

0 commit comments

Comments
 (0)