Skip to content

Commit ad06ef4

Browse files
committed
add several tests to increase coverage
1 parent 81328c1 commit ad06ef4

17 files changed

Lines changed: 790 additions & 43 deletions

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*/
1212
class JWTVerifier {
1313
private final Algorithm algorithm;
14-
private final Map<String, Object> claims;
14+
final Map<String, Object> claims;
1515

1616
private JWTVerifier(Algorithm algorithm, Map<String, Object> claims) {
1717
this.algorithm = algorithm;

lib/src/main/java/com/auth0/jwtdecodejava/SignUtils.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
import org.apache.commons.codec.binary.Base64;
55
import org.apache.commons.codec.binary.StringUtils;
66

7-
import java.security.*;
8-
9-
class SignUtils {
7+
abstract class SignUtils {
108

119
/**
1210
* Decodes a given String from it's Base64 string representation into a UTF-8 String.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.auth0.jwtdecodejava.algorithms;
2+
3+
import javax.crypto.Mac;
4+
import javax.crypto.spec.SecretKeySpec;
5+
import java.security.*;
6+
7+
class CryptoHelper {
8+
9+
boolean verifyMacFor(String algorithm, byte[] secretBytes, byte[] contentBytes, byte[] signatureBytes) throws NoSuchAlgorithmException, InvalidKeyException {
10+
final Mac mac = Mac.getInstance(algorithm);
11+
mac.init(new SecretKeySpec(secretBytes, algorithm));
12+
byte[] result = mac.doFinal(contentBytes);
13+
return MessageDigest.isEqual(result, signatureBytes);
14+
}
15+
16+
boolean verifySignatureFor(String algorithm, PublicKey publicKey, byte[] contentBytes, byte[] signatureBytes) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
17+
final Signature s = Signature.getInstance(algorithm);
18+
s.initVerify(publicKey);
19+
s.update(contentBytes);
20+
return s.verify(signatureBytes);
21+
}
22+
}

lib/src/main/java/com/auth0/jwtdecodejava/algorithms/ECDSAAlgorithm.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,29 @@
33
import com.auth0.jwtdecodejava.exceptions.SignatureVerificationException;
44
import org.apache.commons.codec.binary.Base64;
55

6-
import java.security.*;
6+
import java.security.InvalidKeyException;
7+
import java.security.NoSuchAlgorithmException;
8+
import java.security.PublicKey;
9+
import java.security.SignatureException;
710

811
class ECDSAAlgorithm extends Algorithm {
912

13+
private final CryptoHelper crypto;
1014
private final int ecNumberSize;
1115
private final PublicKey publicKey;
1216

13-
ECDSAAlgorithm(String id, String algorithm, int ecNumberSize, PublicKey publicKey) {
17+
ECDSAAlgorithm(CryptoHelper crypto, String id, String algorithm, int ecNumberSize, PublicKey publicKey) {
1418
super(id, algorithm);
1519
if (publicKey == null) {
1620
throw new IllegalArgumentException("The PublicKey cannot be null");
1721
}
1822
this.ecNumberSize = ecNumberSize;
1923
this.publicKey = publicKey;
24+
this.crypto = crypto;
25+
}
26+
27+
ECDSAAlgorithm(String id, String algorithm, int ecNumberSize, PublicKey publicKey) {
28+
this(new CryptoHelper(), id, algorithm, ecNumberSize, publicKey);
2029
}
2130

2231
PublicKey getPublicKey() {
@@ -27,14 +36,12 @@ PublicKey getPublicKey() {
2736
public void verify(String[] jwtParts) throws SignatureVerificationException {
2837
try {
2938
String content = String.format("%s.%s", jwtParts[0], jwtParts[1]);
30-
Signature s = Signature.getInstance(getDescription());
31-
s.initVerify(publicKey);
32-
s.update(content.getBytes());
3339
byte[] signature = Base64.decodeBase64(jwtParts[2]);
3440
if (!isDERSignature(signature)) {
3541
signature = JOSEToDER(signature);
3642
}
37-
boolean valid = s.verify(signature);
43+
boolean valid = crypto.verifySignatureFor(getDescription(), publicKey, content.getBytes(), signature);
44+
3845
if (!valid) {
3946
throw new SignatureVerificationException(this);
4047
}
@@ -61,7 +68,7 @@ private byte[] JOSEToDER(byte[] joseSignature) throws SignatureException {
6168
int sLength = ecNumberSize - sPadding;
6269

6370
int length = 2 + rLength + 2 + sLength;
64-
if (length > 0xFF) {
71+
if (length > 255) {
6572
throw new SignatureException("Invalid ECDSA signature format");
6673
}
6774

lib/src/main/java/com/auth0/jwtdecodejava/algorithms/HMACAlgorithm.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,25 @@
33
import com.auth0.jwtdecodejava.exceptions.SignatureVerificationException;
44
import org.apache.commons.codec.binary.Base64;
55

6-
import javax.crypto.Mac;
7-
import javax.crypto.spec.SecretKeySpec;
86
import java.security.InvalidKeyException;
9-
import java.security.MessageDigest;
107
import java.security.NoSuchAlgorithmException;
118

129
class HMACAlgorithm extends Algorithm {
1310

11+
private final CryptoHelper crypto;
1412
private final String secret;
1513

16-
HMACAlgorithm(String id, String algorithm, String secret) {
14+
HMACAlgorithm(CryptoHelper crypto, String id, String algorithm, String secret) {
1715
super(id, algorithm);
1816
if (secret == null) {
1917
throw new IllegalArgumentException("The Secret cannot be null");
2018
}
2119
this.secret = secret;
20+
this.crypto = crypto;
21+
}
22+
23+
HMACAlgorithm(String id, String algorithm, String secret) {
24+
this(new CryptoHelper(), id, algorithm, secret);
2225
}
2326

2427
String getSecret() {
@@ -28,16 +31,16 @@ String getSecret() {
2831
@Override
2932
public void verify(String[] jwtParts) throws SignatureVerificationException {
3033
try {
31-
Mac mac = Mac.getInstance(getDescription());
32-
mac.init(new SecretKeySpec(secret.getBytes(), getDescription()));
3334
String message = String.format("%s.%s", jwtParts[0], jwtParts[1]);
34-
byte[] result = mac.doFinal(message.getBytes());
35-
boolean valid = MessageDigest.isEqual(result, Base64.decodeBase64(jwtParts[2]));
35+
byte[] signature = Base64.decodeBase64(jwtParts[2]);
36+
boolean valid = crypto.verifyMacFor(getDescription(), secret.getBytes(), message.getBytes(), signature);
37+
3638
if (!valid) {
3739
throw new SignatureVerificationException(this);
3840
}
39-
} catch (InvalidKeyException | NoSuchAlgorithmException e) {
41+
} catch (IllegalStateException | InvalidKeyException | NoSuchAlgorithmException e) {
4042
throw new SignatureVerificationException(this, e);
4143
}
4244
}
45+
4346
}

lib/src/main/java/com/auth0/jwtdecodejava/algorithms/RSAAlgorithm.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,27 @@
33
import com.auth0.jwtdecodejava.exceptions.SignatureVerificationException;
44
import org.apache.commons.codec.binary.Base64;
55

6-
import java.security.*;
6+
import java.security.InvalidKeyException;
7+
import java.security.NoSuchAlgorithmException;
8+
import java.security.PublicKey;
9+
import java.security.SignatureException;
710

811
class RSAAlgorithm extends Algorithm {
912

1013
private final PublicKey publicKey;
14+
private CryptoHelper crypto;
1115

12-
RSAAlgorithm(String id, String algorithm, PublicKey publicKey) {
16+
RSAAlgorithm(CryptoHelper crypto, String id, String algorithm, PublicKey publicKey) {
1317
super(id, algorithm);
1418
if (publicKey == null) {
1519
throw new IllegalArgumentException("The PublicKey cannot be null");
1620
}
1721
this.publicKey = publicKey;
22+
this.crypto = crypto;
23+
}
24+
25+
RSAAlgorithm(String id, String algorithm, PublicKey publicKey) {
26+
this(new CryptoHelper(), id, algorithm, publicKey);
1827
}
1928

2029
PublicKey getPublicKey() {
@@ -25,10 +34,9 @@ PublicKey getPublicKey() {
2534
public void verify(String[] jwtParts) throws SignatureVerificationException {
2635
try {
2736
String content = String.format("%s.%s", jwtParts[0], jwtParts[1]);
28-
Signature s = Signature.getInstance(getDescription());
29-
s.initVerify(publicKey);
30-
s.update(content.getBytes());
31-
boolean valid = s.verify(Base64.decodeBase64(jwtParts[2]));
37+
byte[] signature = Base64.decodeBase64(jwtParts[2]);
38+
boolean valid = crypto.verifySignatureFor(getDescription(), publicKey, content.getBytes(), signature);
39+
3240
if (!valid) {
3341
throw new SignatureVerificationException(this);
3442
}

lib/src/main/java/com/auth0/jwtdecodejava/impl/HeaderDeserializer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public HeaderImpl deserialize(JsonParser p, DeserializationContext ctxt) throws
2525
Map<String, JsonNode> tree = p.getCodec().readValue(p, new TypeReference<Map<String, JsonNode>>() {
2626
});
2727
if (tree == null) {
28-
throw new JWTDecodeException("Null map");
28+
throw new JWTDecodeException("Parsing the Header's JSON resulted on a Null map");
2929
}
3030
return new HeaderImpl(tree);
3131
}

lib/src/main/java/com/auth0/jwtdecodejava/impl/PayloadDeserializer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public Payload deserialize(JsonParser p, DeserializationContext ctxt) throws IOE
2929
Map<String, JsonNode> tree = p.getCodec().readValue(p, new TypeReference<Map<String, JsonNode>>() {
3030
});
3131
if (tree == null) {
32-
throw new JWTDecodeException("Null map");
32+
throw new JWTDecodeException("Parsing the Payload's JSON resulted on a Null map");
3333
}
3434

3535
String issuer = getString(tree, PublicClaims.ISSUER);
@@ -43,7 +43,7 @@ public Payload deserialize(JsonParser p, DeserializationContext ctxt) throws IOE
4343
return new PayloadImpl(issuer, subject, audience, expiresAt, notBefore, issuedAt, jwtId, tree);
4444
}
4545

46-
private String[] getStringOrArray(Map<String, JsonNode> tree, String claimName) throws JWTDecodeException {
46+
String[] getStringOrArray(Map<String, JsonNode> tree, String claimName) throws JWTDecodeException {
4747
JsonNode node = tree.get(claimName);
4848
if (node == null || node.isNull() || !(node.isArray() || node.isTextual())) {
4949
return null;

lib/src/test/java/com/auth0/jwtdecodejava/JWTDecoderTest.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public void shouldGetStringToken() throws Exception {
7474
// Parts
7575

7676
@Test
77-
public void shouldGetHeader() throws Exception {
77+
public void shouldGetAlgorithm() throws Exception {
7878
JWT jwt = JWTDecoder.decode("eyJhbGciOiJIUzI1NiJ9.e30.XmNK3GpH3Ys_7wsYBfq4C3M6goz71I7dTgUkuIa5lyQ");
7979
assertThat(jwt, is(notNullValue()));
8080
assertThat(jwt.getAlgorithm(), is("HS256"));
@@ -159,6 +159,20 @@ public void shouldGetId() throws Exception {
159159
assertThat(jwt.getId(), is("1234567890"));
160160
}
161161

162+
@Test
163+
public void shouldGetContentType() throws Exception {
164+
JWT jwt = JWTDecoder.decode("eyJhbGciOiJIUzI1NiIsImN0eSI6ImF3ZXNvbWUifQ.e30.AIm-pJDOaAyct9qKMlN-lQieqNDqc3d4erqUZc5SHAs");
165+
assertThat(jwt, is(notNullValue()));
166+
assertThat(jwt.getContentType(), is("awesome"));
167+
}
168+
169+
@Test
170+
public void shouldGetType() throws Exception {
171+
JWT jwt = JWTDecoder.decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.e30.WdFmrzx8b9v_a-r6EHC2PTAaWywgm_8LiP8RBRhYwkI");
172+
assertThat(jwt, is(notNullValue()));
173+
assertThat(jwt.getType(), is("JWS"));
174+
}
175+
162176
@Test
163177
@Ignore("Pending implementation")
164178
public void shouldBeExpired() throws Exception {

0 commit comments

Comments
 (0)