Skip to content

Commit d713cec

Browse files
authored
Merge branch 'master' into insertion-order
2 parents 2050c03 + a18955b commit d713cec

File tree

3 files changed

+124
-4
lines changed

3 files changed

+124
-4
lines changed

lib/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ javadoc {
7272
}
7373

7474
dependencies {
75-
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4.2'
75+
implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.0'
7676

7777
testImplementation 'org.bouncycastle:bcprov-jdk15on:1.70'
7878
testImplementation 'junit:junit:4.13.2'

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,27 @@ public Builder withHeader(Map<String, Object> headerClaims) {
9898
return this;
9999
}
100100

101+
/**
102+
* Add specific Claims to set as the Header.
103+
* If provided json is null then nothing is changed
104+
*
105+
* @param headerClaimsJson the values to use as Claims in the token's Header.
106+
* @return this same Builder instance.
107+
* @throws IllegalArgumentException if json value has invalid structure
108+
*/
109+
public Builder withHeader(String headerClaimsJson) throws IllegalArgumentException {
110+
if (headerClaimsJson == null) {
111+
return this;
112+
}
113+
114+
try {
115+
Map<String, Object> headerClaims = mapper.readValue(headerClaimsJson, HashMap.class);
116+
return withHeader(headerClaims);
117+
} catch (JsonProcessingException e) {
118+
throw new IllegalArgumentException("Invalid header JSON", e);
119+
}
120+
}
121+
101122
/**
102123
* Add a specific Key Id ("kid") claim to the Header.
103124
* If the {@link Algorithm} used to sign this token was instantiated with a KeyProvider,
@@ -467,6 +488,33 @@ public Builder withPayload(Map<String, ?> payloadClaims) throws IllegalArgumentE
467488
return this;
468489
}
469490

491+
/**
492+
* Add specific Claims to set as the Payload. If the provided json is null then
493+
* nothing is changed.
494+
*
495+
* <p>
496+
* If any of the claims are invalid, none will be added.
497+
* </p>
498+
*
499+
* @param payloadClaimsJson the values to use as Claims in the token's payload.
500+
* @return this same Builder instance.
501+
* @throws IllegalArgumentException if any of the claim keys or null,
502+
* or if the values are not of a supported type,
503+
* or if json value has invalid structure.
504+
*/
505+
public Builder withPayload(String payloadClaimsJson) throws IllegalArgumentException {
506+
if (payloadClaimsJson == null) {
507+
return this;
508+
}
509+
510+
try {
511+
Map<String, Object> payloadClaims = mapper.readValue(payloadClaimsJson, HashMap.class);
512+
return withPayload(payloadClaims);
513+
} catch (JsonProcessingException e) {
514+
throw new IllegalArgumentException("Invalid payload JSON", e);
515+
}
516+
}
517+
470518
private boolean validatePayload(Map<String, ?> payload) {
471519
for (Map.Entry<String, ?> entry : payload.entrySet()) {
472520
String key = entry.getKey();

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

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.auth0.jwt.algorithms.Algorithm;
44
import com.auth0.jwt.interfaces.ECDSAKeyProvider;
55
import com.auth0.jwt.interfaces.RSAKeyProvider;
6+
import com.fasterxml.jackson.core.JsonProcessingException;
67
import com.fasterxml.jackson.databind.ObjectMapper;
78
import com.fasterxml.jackson.databind.node.ObjectNode;
89
import org.junit.Rule;
@@ -83,13 +84,48 @@ public void shouldAddHeaderClaim() {
8384

8485
@Test
8586
public void shouldReturnBuilderIfNullMapIsProvided() {
87+
Map<String, Object> nullMap = null;
88+
String nullString = null;
8689
String signed = JWTCreator.init()
87-
.withHeader(null)
90+
.withHeader(nullMap)
91+
.withHeader(nullString)
8892
.sign(Algorithm.HMAC256("secret"));
8993

9094
assertThat(signed, is(notNullValue()));
9195
}
9296

97+
@Test
98+
public void shouldSupportJsonValueHeaderWithNestedDataStructure() {
99+
String stringClaim = "someClaim";
100+
Integer intClaim = 1;
101+
List<String> nestedListClaims = Arrays.asList("1", "2");
102+
String claimsJson = "{\"stringClaim\": \"someClaim\", \"intClaim\": 1, \"nestedClaim\": { \"listClaim\": [ \"1\", \"2\" ]}}";
103+
104+
String jwt = JWTCreator.init()
105+
.withHeader(claimsJson)
106+
.sign(Algorithm.HMAC256("secret"));
107+
108+
assertThat(jwt, is(notNullValue()));
109+
String[] parts = jwt.split("\\.");
110+
String headerJson = new String(Base64.getUrlDecoder().decode(parts[0]), StandardCharsets.UTF_8);
111+
112+
assertThat(headerJson, JsonMatcher.hasEntry("stringClaim", stringClaim));
113+
assertThat(headerJson, JsonMatcher.hasEntry("intClaim", intClaim));
114+
assertThat(headerJson, JsonMatcher.hasEntry("listClaim", nestedListClaims));
115+
}
116+
117+
@Test
118+
public void shouldFailWithIllegalArgumentExceptionForInvalidJsonForHeaderClaims() {
119+
String invalidJson = "{ invalidJson }";
120+
121+
exception.expect(IllegalArgumentException.class);
122+
exception.expectMessage("Invalid header JSON");
123+
124+
JWTCreator.init()
125+
.withHeader(invalidJson)
126+
.sign(Algorithm.HMAC256("secret"));
127+
}
128+
93129
@Test
94130
public void shouldOverwriteExistingHeaderIfHeaderMapContainsTheSameKey() {
95131
Map<String, Object> header = new HashMap<>();
@@ -106,6 +142,7 @@ public void shouldOverwriteExistingHeaderIfHeaderMapContainsTheSameKey() {
106142
assertThat(headerJson, JsonMatcher.hasEntry(HeaderParams.KEY_ID, "xyz"));
107143
}
108144

145+
109146
@Test
110147
public void shouldOverwriteExistingHeadersWhenSettingSameHeaderKey() {
111148
Map<String, Object> header = new HashMap<>();
@@ -716,8 +753,11 @@ public void withPayloadShouldAddBasicClaim() {
716753

717754
@Test
718755
public void withPayloadShouldCreateJwtWithEmptyBodyIfPayloadNull() {
756+
Map<String, Object> nullMap = null;
757+
String nullString = null;
719758
String jwt = JWTCreator.init()
720-
.withPayload(null)
759+
.withPayload(nullMap)
760+
.withPayload(nullString)
721761
.sign(Algorithm.HMAC256("secret"));
722762

723763
assertThat(jwt, is(notNullValue()));
@@ -922,10 +962,42 @@ public void withPayloadShouldSupportNullValuesEverywhere() {
922962
assertThat(headerJson, JsonMatcher.hasEntry("objClaim", objClaim));
923963
}
924964

965+
@Test
966+
public void withPayloadShouldSupportJsonValueWithNestedDataStructure() {
967+
String stringClaim = "someClaim";
968+
Integer intClaim = 1;
969+
List<String> nestedListClaims = Arrays.asList("1", "2");
970+
String claimsJson = "{\"stringClaim\": \"someClaim\", \"intClaim\": 1, \"nestedClaim\": { \"listClaim\": [ \"1\", \"2\" ]}}";
971+
972+
String jwt = JWTCreator.init()
973+
.withPayload(claimsJson)
974+
.sign(Algorithm.HMAC256("secret"));
975+
976+
assertThat(jwt, is(notNullValue()));
977+
String[] parts = jwt.split("\\.");
978+
String payloadJson = new String(Base64.getUrlDecoder().decode(parts[1]), StandardCharsets.UTF_8);
979+
980+
assertThat(payloadJson, JsonMatcher.hasEntry("stringClaim", stringClaim));
981+
assertThat(payloadJson, JsonMatcher.hasEntry("intClaim", intClaim));
982+
assertThat(payloadJson, JsonMatcher.hasEntry("listClaim", nestedListClaims));
983+
}
984+
985+
@Test
986+
public void shouldFailWithIllegalArgumentExceptionForInvalidJsonForPayloadClaims() {
987+
String invalidJson = "{ invalidJson }";
988+
989+
exception.expect(IllegalArgumentException.class);
990+
exception.expectMessage("Invalid payload JSON");
991+
992+
JWTCreator.init()
993+
.withPayload(invalidJson)
994+
.sign(Algorithm.HMAC256("secret"));
995+
}
996+
925997
@Test
926998
public void shouldCreatePayloadWithNullForMap() {
927999
String jwt = JWTCreator.init()
928-
.withClaim("name", (Map<String,?>) null)
1000+
.withClaim("name", (Map<String, ?>) null)
9291001
.sign(Algorithm.HMAC256("secret"));
9301002
assertThat(jwt, is(notNullValue()));
9311003
assertTrue(JWT.decode(jwt).getClaim("name").isNull());

0 commit comments

Comments
 (0)