Skip to content

Commit

Permalink
Supporte to add objects (primitive and collection) as claim in token …
Browse files Browse the repository at this point in the history
…payload
  • Loading branch information
veerasekharbab.golla committed Jan 12, 2019
1 parent 861a6d7 commit a530799
Show file tree
Hide file tree
Showing 3 changed files with 354 additions and 17 deletions.
73 changes: 69 additions & 4 deletions lib/src/main/java/com/auth0/jwt/JWTCreator.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.auth0.jwt;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.codec.binary.Base64;

Expand Down Expand Up @@ -60,6 +64,13 @@ public static class Builder {
private final Map<String, Object> payloadClaims;
private Map<String, Object> headerClaims;

private static final Set<Class<?>> SUPPORTED_TYPES = new HashSet<>();
private static final Set<Class<?>> SUPPORTED_ARRAY_TYPES = new HashSet<>();
static {
SUPPORTED_ARRAY_TYPES.addAll(Arrays.asList(Integer[].class, Long[].class, String[].class));
SUPPORTED_TYPES.addAll(Arrays.asList(String.class, Integer.class, Double.class, Long.class, Date.class, Boolean.class));
}

Builder() {
this.payloadClaims = new HashMap<>();
this.headerClaims = new HashMap<>();
Expand Down Expand Up @@ -166,20 +177,74 @@ public Builder withJWTId(String jwtId) {
}

/**
* Add a map of Claim values. Only primitives and collections are supported as values in the map.
* Warning: Custom classes are not guaranteed to be handled just fine.
*
* Add a Map of Claim values. Only primitives and collections are supported as values in the map.
* Warning: Custom classes are not allowed.
*
* @param name
* @param values
* @throws IllegalArgumentException
*/
public Builder withClaim(String name, Map<String, Object> values) throws IllegalArgumentException {
assertNonNull(name);
if(!validateClaim(values)) {
throw new IllegalArgumentException("Unsupported claim type found in passed collection. Refer supported types.");
}
addClaim(name, values);
return this;
}

/**
/**
* Add a Collection of Claim values. Only primitives and supported array types are supported as values in the Collection.
* Warning: Custom classes are not allowed.
*
* @param name
* @param values
* @throws IllegalArgumentException
*/
public Builder withClaim(String name, Collection<Object> values) throws IllegalArgumentException {
assertNonNull(name);
if(!validateClaim(values)) {
throw new IllegalArgumentException("Unsupported claim type found in passed collection. Refer supported types.");
}
addClaim(name, values);
return this;
}

private static boolean validateClaim(Map<String, Object> claim) {
if (claim == null || claim.isEmpty()) {
return false;
}
Collection<Object> values = claim.values();
return validateClaim(values);
}

private static boolean validateClaim(Collection<Object> values) {
if (values == null || values.isEmpty()) {
return false;
}
for (Object value : values) {
if (!isValidClaimValue(value)) {
return false;
}
}
return true;
}

/**
* We are allowing value can be null at this point which will be handled at {@link #addClaim(String, Object)}
*/
private static boolean isValidClaimValue(Object value) {
if (value == null) {
return true;
}
Class<?> clazz = value.getClass();
if (clazz.isArray() && SUPPORTED_ARRAY_TYPES.contains(clazz)) {
return true;
}
return SUPPORTED_TYPES.contains(clazz);
}

/**
* Add a custom Claim value.
*
* @param name the Claim's name.
Expand Down
191 changes: 180 additions & 11 deletions lib/src/test/java/com/auth0/jwt/JWTCreatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import java.nio.charset.StandardCharsets;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -20,7 +22,6 @@
import org.junit.rules.ExpectedException;

import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.interfaces.ECDSAKeyProvider;
import com.auth0.jwt.interfaces.RSAKeyProvider;

Expand Down Expand Up @@ -361,6 +362,167 @@ public void shouldAcceptCustomArrayClaimOfTypeLong() throws Exception {
assertThat(parts[1], is("eyJuYW1lIjpbMSwyLDNdfQ"));
}

@Test
public void shouldAcceptCustomCollectionClaimOfBooleanType() throws Exception {
Collection<Object> collection = new ArrayList<>();
collection.add(true);
collection.add(false);

String jwt = JWTCreator.init().withClaim("name", collection).sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbdHJ1ZSxmYWxzZV19"));
}

@Test
public void shouldAcceptCustomCollectionClaimOfIntegerType() throws Exception {
Collection<Object> collection = new ArrayList<>();
collection.add(1);
collection.add(2);

String jwt = JWTCreator.init().withClaim("name", collection).sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbMSwyXX0"));
}

@Test
public void shouldAcceptCustomCollectionClaimOfLongType() throws Exception {
Collection<Object> collection = new ArrayList<>();
collection.add(1L);
collection.add(2L);

String jwt = JWTCreator.init().withClaim("name", collection).sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbMSwyXX0"));
}

@Test
public void shouldAcceptCustomCollectionClaimOfStringType() throws Exception {
Collection<Object> collection = new ArrayList<>();
collection.add("1");
collection.add("2");

String jwt = JWTCreator.init().withClaim("name", collection).sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbIjEiLCIyIl19"));
}

@Test
public void shouldAcceptCustomCollectionClaimOfDoubleType() throws Exception {
Collection<Object> collection = new ArrayList<>();
collection.add(1.2);
collection.add(3.4);

String jwt = JWTCreator.init().withClaim("name", collection).sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbMS4yLDMuNF19"));
}

@Test
public void shouldAcceptCustomCollectionClaimOfDateType() throws Exception {
Collection<Object> collection = new ArrayList<>();
collection.add(new Date(123456));
collection.add(new Date(7890123));

String jwt = JWTCreator.init().withClaim("name", collection).sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbMTIzNDU2LDc4OTAxMjNdfQ"));
}


@Test
public void shouldAcceptCustomCollectionClaimOfIntegerArrayType() throws Exception {
Collection<Object> collection = new ArrayList<>();
collection.add(new Integer[] {1, 2});

String jwt = JWTCreator.init().withClaim("name", collection).sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbWzEsMl1dfQ"));
}

@Test
public void shouldAcceptCustomCollectionClaimOfLongArrayType() throws Exception {
Collection<Object> collection = new ArrayList<>();
collection.add(new Long[] {3L, 4L});

String jwt = JWTCreator.init().withClaim("name", collection).sign(Algorithm.HMAC256("secret"));
System.out.println(jwt);
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbWzMsNF1dfQ"));
}

@Test
public void shouldAcceptCustomCollectionClaimOfStringArrayType() throws Exception {
Collection<Object> collection = new ArrayList<>();
collection.add(new String[] {"5", "6"});

String jwt = JWTCreator.init().withClaim("name", collection).sign(Algorithm.HMAC256("secret"));
System.out.println(jwt);
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbWyI1IiwiNiJdXX0"));
}

@Test(expected = IllegalArgumentException.class)
public void shouldNotAcceptCustomCollectionClaimOfUnSupportedType() throws Exception {
Collection<Object> collection = new ArrayList<>();
collection.add(new JWTTest());

JWTCreator.init().withClaim("name", collection);
}

@Test
public void shouldAcceptCustomCollectionClaimOfArrayType() throws Exception {
Collection<Object> collection = new ArrayList<>();
collection.add(new Integer[] {1,2,3});
collection.add(new Long[] {1L, 2L, 3L});
collection.add(new String[] {"1", "2", "3"});

String jwt = JWTCreator.init().withClaim("name", collection).sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbWzEsMiwzXSxbMSwyLDNdLFsiMSIsIjIiLCIzIl1dfQ"));
}

@Test(expected = IllegalArgumentException.class)
public void shouldNotAcceptCustomCollectionClaimOfUnSupportedArrayType() throws Exception {
Collection<Object> collection = new ArrayList<>();
collection.add(new Boolean[] {true});

JWTCreator.init().withClaim("name", collection);
}

@Test(expected = IllegalArgumentException.class)
public void shouldNotAcceptNullCustomCollectionClaim() throws Exception {
Collection<Object> collection = null;
JWTCreator.init().withClaim("name", collection);
}

@Test(expected = IllegalArgumentException.class)
public void shouldAcceptEmptyCustomCollectionClaim() throws Exception {
Collection<Object> collection = new ArrayList<>();
JWTCreator.init().withClaim("name", collection);
}

@Test(expected = IllegalArgumentException.class)
public void shouldNotAcceptNullCustomMapClaim() throws Exception {
Map<String, Object> map = null;
JWTCreator.init().withClaim("name", map);
}

@Test(expected = IllegalArgumentException.class)
public void shouldAcceptEmptyCustomMapClaim() throws Exception {
Map<String, Object> map = new HashMap<>();
JWTCreator.init().withClaim("name", map);
}

@Test
public void shouldAcceptCustomMapClaimOfTypeLong() throws Exception {
Map<String, Object> map = new HashMap<>();
Expand Down Expand Up @@ -440,25 +602,32 @@ public void shouldAcceptCustomMapClaimOfTypeBoolean() throws Exception {
}

@Test
public void shouldAcceptCustomMapClaimOfTypeCollection() throws Exception {
public void shouldAcceptCustomMapClaimOfArrayType() throws Exception {
Map<String, Object> map = new HashMap<>();
map.put("first", Arrays.asList(new Integer[] { 1, 2, 3 }));
map.put("two", new Integer[] { 2, 3, 4 });
map.put("first", new Integer[] {1, 2, 3});
map.put("two", new Long[] {4L, 5L, 6L});
map.put("three", new String[] {"1", "2", "3"});

String jwt = JWTCreator.init().withClaim("name", map).sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjp7InR3byI6WzIsMyw0XSwiZmlyc3QiOlsxLDIsM119fQ"));
assertThat(parts[1], is("eyJuYW1lIjp7InR3byI6WzQsNSw2XSwidGhyZWUiOlsiMSIsIjIiLCIzIl0sImZpcnN0IjpbMSwyLDNdfX0"));
}

@Test(expected = IllegalArgumentException.class)
public void shouldNotAcceptCustomMapClaimOfTypeCollection() throws Exception {
Map<String, Object> map = new HashMap<>();
map.put("first", Arrays.asList(new Integer[] { 1, 2, 3 }));
map.put("two", new Integer[] { 2, 3, 4 });

JWTCreator.init().withClaim("name", map);
}

@Test(expected = JWTCreationException.class)
public void shouldThrowJWTCreationExceptionWhenNonSerializedCustomClassIsUsed() throws Exception {
@Test(expected = IllegalArgumentException.class)
public void shouldNotAcceptWhenNonSerializedCustomClassIsUsed() throws Exception {
Map<String, Object> map = new HashMap<>();
map.put("first", new JWTCreatorTest());

String jwt = JWTCreator.init().withClaim("name", map).sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjp7InR3byI6WzIsMyw0XSwiZmlyc3QiOlsxLDIsM119fQ"));
JWTCreator.init().withClaim("name", map);
}
}
Loading

0 comments on commit a530799

Please sign in to comment.