package com.auth0.jwt;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.ECDSAKeyProvider;
import com.auth0.jwt.interfaces.RSAKeyProvider;
import org.apache.commons.codec.binary.Base64;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.nio.charset.StandardCharsets;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.RSAPrivateKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class JWTCreatorTest {
private static final String PRIVATE_KEY_FILE_RSA = "src/test/resources/rsa-private.pem";
private static final String PRIVATE_KEY_FILE_EC_256 = "src/test/resources/ec256-key-private.pem";
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void shouldThrowWhenRequestingSignWithoutAlgorithm() throws Exception {
exception.expect(IllegalArgumentException.class);
exception.expectMessage("The Algorithm cannot be null");
JWTCreator.init()
.sign(null);
}
@SuppressWarnings("Convert2Diamond")
@Test
public void shouldAddHeaderClaim() throws Exception {
Map<String, Object> header = new HashMap<String, Object>();
header.put("asd", 123);
String signed = JWTCreator.init()
.withHeader(header)
.sign(Algorithm.HMAC256("secret"));
assertThat(signed, is(notNullValue()));
String[] parts = signed.split("\\.");
String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8);
assertThat(headerJson, JsonMatcher.hasEntry("asd", 123));
}
@Test
public void shouldAddKeyId() throws Exception {
String signed = JWTCreator.init()
.withKeyId("56a8bd44da435300010000015f5ed")
.sign(Algorithm.HMAC256("secret"));
assertThat(signed, is(notNullValue()));
String[] parts = signed.split("\\.");
String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8);
assertThat(headerJson, JsonMatcher.hasEntry("kid", "56a8bd44da435300010000015f5ed"));
}
@Test
public void shouldAddKeyIdIfAvailableFromRSAAlgorithms() throws Exception {
RSAPrivateKey privateKey = (RSAPrivateKey) PemUtils.readPrivateKeyFromFile(PRIVATE_KEY_FILE_RSA, "RSA");
RSAKeyProvider provider = mock(RSAKeyProvider.class);
when(provider.getPrivateKeyId()).thenReturn("my-key-id");
when(provider.getPrivateKey()).thenReturn(privateKey);
String signed = JWTCreator.init()
.sign(Algorithm.RSA256(provider));
assertThat(signed, is(notNullValue()));
String[] parts = signed.split("\\.");
String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8);
assertThat(headerJson, JsonMatcher.hasEntry("kid", "my-key-id"));
}
@Test
public void shouldNotOverwriteKeyIdIfAddedFromRSAAlgorithms() throws Exception {
RSAPrivateKey privateKey = (RSAPrivateKey) PemUtils.readPrivateKeyFromFile(PRIVATE_KEY_FILE_RSA, "RSA");
RSAKeyProvider provider = mock(RSAKeyProvider.class);
when(provider.getPrivateKeyId()).thenReturn("my-key-id");
when(provider.getPrivateKey()).thenReturn(privateKey);
String signed = JWTCreator.init()
.withKeyId("real-key-id")
.sign(Algorithm.RSA256(provider));
assertThat(signed, is(notNullValue()));
String[] parts = signed.split("\\.");
String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8);
assertThat(headerJson, JsonMatcher.hasEntry("kid", "my-key-id"));
}
@Test
public void shouldAddKeyIdIfAvailableFromECDSAAlgorithms() throws Exception {
ECPrivateKey privateKey = (ECPrivateKey) PemUtils.readPrivateKeyFromFile(PRIVATE_KEY_FILE_EC_256, "EC");
ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class);
when(provider.getPrivateKeyId()).thenReturn("my-key-id");
when(provider.getPrivateKey()).thenReturn(privateKey);
String signed = JWTCreator.init()
.sign(Algorithm.ECDSA256(provider));
assertThat(signed, is(notNullValue()));
String[] parts = signed.split("\\.");
String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8);
assertThat(headerJson, JsonMatcher.hasEntry("kid", "my-key-id"));
}
@Test
public void shouldNotOverwriteKeyIdIfAddedFromECDSAAlgorithms() throws Exception {
ECPrivateKey privateKey = (ECPrivateKey) PemUtils.readPrivateKeyFromFile(PRIVATE_KEY_FILE_EC_256, "EC");
ECDSAKeyProvider provider = mock(ECDSAKeyProvider.class);
when(provider.getPrivateKeyId()).thenReturn("my-key-id");
when(provider.getPrivateKey()).thenReturn(privateKey);
String signed = JWTCreator.init()
.withKeyId("real-key-id")
.sign(Algorithm.ECDSA256(provider));
assertThat(signed, is(notNullValue()));
String[] parts = signed.split("\\.");
String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8);
assertThat(headerJson, JsonMatcher.hasEntry("kid", "my-key-id"));
}
@Test
public void shouldAddIssuer() throws Exception {
String signed = JWTCreator.init()
.withIssuer("auth0")
.sign(Algorithm.HMAC256("secret"));
assertThat(signed, is(notNullValue()));
assertThat(TokenUtils.splitToken(signed)[1], is("eyJpc3MiOiJhdXRoMCJ9"));
}
@Test
public void shouldAddSubject() throws Exception {
String signed = JWTCreator.init()
.withSubject("1234567890")
.sign(Algorithm.HMAC256("secret"));
assertThat(signed, is(notNullValue()));
assertThat(TokenUtils.splitToken(signed)[1], is("eyJzdWIiOiIxMjM0NTY3ODkwIn0"));
}
@Test
public void shouldAddAudience() throws Exception {
String signed = JWTCreator.init()
.withAudience("Mark")
.sign(Algorithm.HMAC256("secret"));
assertThat(signed, is(notNullValue()));
assertThat(TokenUtils.splitToken(signed)[1], is("eyJhdWQiOiJNYXJrIn0"));
String signedArr = JWTCreator.init()
.withAudience("Mark", "David")
.sign(Algorithm.HMAC256("secret"));
assertThat(signedArr, is(notNullValue()));
assertThat(TokenUtils.splitToken(signedArr)[1], is("eyJhdWQiOlsiTWFyayIsIkRhdmlkIl19"));
}
@Test
public void shouldAddExpiresAt() throws Exception {
String signed = JWTCreator.init()
.withExpiresAt(new Date(1477592000))
.sign(Algorithm.HMAC256("secret"));
assertThat(signed, is(notNullValue()));
assertThat(TokenUtils.splitToken(signed)[1], is("eyJleHAiOjE0Nzc1OTJ9"));
}
@Test
public void shouldAddNotBefore() throws Exception {
String signed = JWTCreator.init()
.withNotBefore(new Date(1477592000))
.sign(Algorithm.HMAC256("secret"));
assertThat(signed, is(notNullValue()));
assertThat(TokenUtils.splitToken(signed)[1], is("eyJuYmYiOjE0Nzc1OTJ9"));
}
@Test
public void shouldAddIssuedAt() throws Exception {
String signed = JWTCreator.init()
.withIssuedAt(new Date(1477592000))
.sign(Algorithm.HMAC256("secret"));
assertThat(signed, is(notNullValue()));
assertThat(TokenUtils.splitToken(signed)[1], is("eyJpYXQiOjE0Nzc1OTJ9"));
}
@Test
public void shouldAddJWTId() throws Exception {
String signed = JWTCreator.init()
.withJWTId("jwt_id_123")
.sign(Algorithm.HMAC256("secret"));
assertThat(signed, is(notNullValue()));
assertThat(TokenUtils.splitToken(signed)[1], is("eyJqdGkiOiJqd3RfaWRfMTIzIn0"));
}
@Test
public void shouldRemoveClaimWhenPassingNull() throws Exception {
String signed = JWTCreator.init()
.withIssuer("iss")
.withIssuer(null)
.sign(Algorithm.HMAC256("secret"));
assertThat(signed, is(notNullValue()));
assertThat(TokenUtils.splitToken(signed)[1], is("e30"));
}
@Test
public void shouldSetCorrectAlgorithmInTheHeader() throws Exception {
String signed = JWTCreator.init()
.sign(Algorithm.HMAC256("secret"));
assertThat(signed, is(notNullValue()));
String[] parts = signed.split("\\.");
String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8);
assertThat(headerJson, JsonMatcher.hasEntry("alg", "HS256"));
}
@Test
public void shouldSetCorrectTypeInTheHeader() throws Exception {
String signed = JWTCreator.init()
.sign(Algorithm.HMAC256("secret"));
assertThat(signed, is(notNullValue()));
String[] parts = signed.split("\\.");
String headerJson = new String(Base64.decodeBase64(parts[0]), StandardCharsets.UTF_8);
assertThat(headerJson, JsonMatcher.hasEntry("typ", "JWT"));
}
@Test
public void shouldSetEmptySignatureIfAlgorithmIsNone() throws Exception {
String signed = JWTCreator.init()
.sign(Algorithm.none());
assertThat(signed, is(notNullValue()));
assertThat(TokenUtils.splitToken(signed)[2], is(""));
}
@Test
public void shouldThrowOnNullCustomClaimName() throws Exception {
exception.expect(IllegalArgumentException.class);
exception.expectMessage("The Custom Claim's name can't be null.");
JWTCreator.init()
.withClaim(null, "value");
}
@Test
public void shouldAcceptCustomClaimOfTypeString() throws Exception {
String jwt = JWTCreator.init()
.withClaim("name", "value")
.sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjoidmFsdWUifQ"));
}
@Test
public void shouldAcceptCustomClaimOfTypeInteger() throws Exception {
String jwt = JWTCreator.init()
.withClaim("name", 123)
.sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjoxMjN9"));
}
@Test
public void shouldAcceptCustomClaimOfTypeLong() throws Exception {
String jwt = JWTCreator.init()
.withClaim("name", Long.MAX_VALUE)
.sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjo5MjIzMzcyMDM2ODU0Nzc1ODA3fQ"));
}
@Test
public void shouldAcceptCustomClaimOfTypeDouble() throws Exception {
String jwt = JWTCreator.init()
.withClaim("name", 23.45)
.sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjoyMy40NX0"));
}
@Test
public void shouldAcceptCustomClaimOfTypeBoolean() throws Exception {
String jwt = JWTCreator.init()
.withClaim("name", true)
.sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjp0cnVlfQ"));
}
@Test
public void shouldAcceptCustomClaimOfTypeDate() throws Exception {
Date date = new Date(1478891521000L);
String jwt = JWTCreator.init()
.withClaim("name", date)
.sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjoxNDc4ODkxNTIxfQ"));
}
@Test
public void shouldAcceptCustomArrayClaimOfTypeString() throws Exception {
String jwt = JWTCreator.init()
.withArrayClaim("name", new String[]{"text", "123", "true"})
.sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbInRleHQiLCIxMjMiLCJ0cnVlIl19"));
}
@Test
public void shouldAcceptCustomArrayClaimOfTypeInteger() throws Exception {
String jwt = JWTCreator.init()
.withArrayClaim("name", new Integer[]{1, 2, 3})
.sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbMSwyLDNdfQ"));
}
@Test
public void shouldAcceptCustomArrayClaimOfTypeLong() throws Exception {
String jwt = JWTCreator.init()
.withArrayClaim("name", new Long[]{1L, 2L, 3L})
.sign(Algorithm.HMAC256("secret"));
assertThat(jwt, is(notNullValue()));
String[] parts = jwt.split("\\.");
assertThat(parts[1], is("eyJuYW1lIjpbMSwyLDNdfQ"));
}
}