X Tutup
Skip to content

Commit 9a79032

Browse files
authored
Merge pull request auth0#125 from auth0/clock-test-accessible
Make Clock customization accessible for verification
2 parents 24901e2 + 545f5c4 commit 9a79032

File tree

9 files changed

+129
-40
lines changed

9 files changed

+129
-40
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,15 @@ JWTVerifier verifier = JWT.require(Algorithm.RSA256(key))
152152
.build();
153153
```
154154

155+
If you need to test this behaviour in your lib/app cast the `Verification` instance to a `BaseVerification` to gain visibility of the `verification.build()` method that accepts a custom `Clock`. e.g.:
156+
157+
```java
158+
BaseVerification verification = (BaseVerification) JWT.require(Algorithm.RSA256(key))
159+
.acceptLeeway(1)
160+
.acceptExpiresAt(5);
161+
Clock clock = new CustomClock(); //Must implement Clock interface
162+
JWTVerifier verifier = verification.build(clock);
163+
```
155164

156165
### Header Claims
157166

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.auth0.jwt;
2+
3+
import com.auth0.jwt.interfaces.Clock;
4+
5+
import java.util.Date;
6+
7+
final class ClockImpl implements Clock {
8+
9+
ClockImpl() {
10+
}
11+
12+
@Override
13+
public Date getToday() {
14+
return new Date();
15+
}
16+
}

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,15 @@
22

33
import com.auth0.jwt.algorithms.Algorithm;
44
import com.auth0.jwt.exceptions.JWTDecodeException;
5-
import com.auth0.jwt.interfaces.Claim;
65
import com.auth0.jwt.interfaces.DecodedJWT;
7-
8-
import java.util.Date;
9-
import java.util.List;
6+
import com.auth0.jwt.interfaces.Verification;
107

118
@SuppressWarnings("WeakerAccess")
129
public abstract class JWT implements DecodedJWT {
1310

1411
/**
1512
* Decode a given JWT token.
16-
*
13+
* <p>
1714
* Note that this method <b>doesn't verify the token's signature!</b> Use it only if you trust the token or you already verified it.
1815
*
1916
* @param token with jwt format as string.
@@ -31,7 +28,7 @@ public static JWT decode(String token) throws JWTDecodeException {
3128
* @return {@link JWTVerifier} builder
3229
* @throws IllegalArgumentException if the provided algorithm is null.
3330
*/
34-
public static JWTVerifier.Verification require(Algorithm algorithm) {
31+
public static Verification require(Algorithm algorithm) {
3532
return JWTVerifier.init(algorithm);
3633
}
3734

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

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
import com.auth0.jwt.exceptions.SignatureVerificationException;
88
import com.auth0.jwt.impl.PublicClaims;
99
import com.auth0.jwt.interfaces.Claim;
10+
import com.auth0.jwt.interfaces.Clock;
1011
import com.auth0.jwt.interfaces.DecodedJWT;
12+
import com.auth0.jwt.interfaces.Verification;
1113
import org.apache.commons.codec.binary.Base64;
1214

1315
import java.nio.charset.StandardCharsets;
@@ -35,19 +37,19 @@ public final class JWTVerifier {
3537
* @return a JWTVerifier.Verification instance to configure.
3638
* @throws IllegalArgumentException if the provided algorithm is null.
3739
*/
38-
static JWTVerifier.Verification init(Algorithm algorithm) throws IllegalArgumentException {
39-
return new Verification(algorithm);
40+
static Verification init(Algorithm algorithm) throws IllegalArgumentException {
41+
return new BaseVerification(algorithm);
4042
}
4143

4244
/**
4345
* The Verification class holds the Claims required by a JWT to be valid.
4446
*/
45-
public static class Verification {
47+
public static class BaseVerification implements Verification {
4648
private final Algorithm algorithm;
4749
private final Map<String, Object> claims;
4850
private long defaultLeeway;
4951

50-
Verification(Algorithm algorithm) throws IllegalArgumentException {
52+
BaseVerification(Algorithm algorithm) throws IllegalArgumentException {
5153
if (algorithm == null) {
5254
throw new IllegalArgumentException("The Algorithm cannot be null.");
5355
}
@@ -63,6 +65,7 @@ public static class Verification {
6365
* @param issuer the required Issuer value
6466
* @return this same Verification instance.
6567
*/
68+
@Override
6669
public Verification withIssuer(String issuer) {
6770
requireClaim(PublicClaims.ISSUER, issuer);
6871
return this;
@@ -74,6 +77,7 @@ public Verification withIssuer(String issuer) {
7477
* @param subject the required Subject value
7578
* @return this same Verification instance.
7679
*/
80+
@Override
7781
public Verification withSubject(String subject) {
7882
requireClaim(PublicClaims.SUBJECT, subject);
7983
return this;
@@ -85,6 +89,7 @@ public Verification withSubject(String subject) {
8589
* @param audience the required Audience value
8690
* @return this same Verification instance.
8791
*/
92+
@Override
8893
public Verification withAudience(String... audience) {
8994
requireClaim(PublicClaims.AUDIENCE, Arrays.asList(audience));
9095
return this;
@@ -98,6 +103,7 @@ public Verification withAudience(String... audience) {
98103
* @return this same Verification instance.
99104
* @throws IllegalArgumentException if leeway is negative.
100105
*/
106+
@Override
101107
public Verification acceptLeeway(long leeway) throws IllegalArgumentException {
102108
assertPositive(leeway);
103109
this.defaultLeeway = leeway;
@@ -112,6 +118,7 @@ public Verification acceptLeeway(long leeway) throws IllegalArgumentException {
112118
* @return this same Verification instance.
113119
* @throws IllegalArgumentException if leeway is negative.
114120
*/
121+
@Override
115122
public Verification acceptExpiresAt(long leeway) throws IllegalArgumentException {
116123
assertPositive(leeway);
117124
requireClaim(PublicClaims.EXPIRES_AT, leeway);
@@ -126,6 +133,7 @@ public Verification acceptExpiresAt(long leeway) throws IllegalArgumentException
126133
* @return this same Verification instance.
127134
* @throws IllegalArgumentException if leeway is negative.
128135
*/
136+
@Override
129137
public Verification acceptNotBefore(long leeway) throws IllegalArgumentException {
130138
assertPositive(leeway);
131139
requireClaim(PublicClaims.NOT_BEFORE, leeway);
@@ -140,6 +148,7 @@ public Verification acceptNotBefore(long leeway) throws IllegalArgumentException
140148
* @return this same Verification instance.
141149
* @throws IllegalArgumentException if leeway is negative.
142150
*/
151+
@Override
143152
public Verification acceptIssuedAt(long leeway) throws IllegalArgumentException {
144153
assertPositive(leeway);
145154
requireClaim(PublicClaims.ISSUED_AT, leeway);
@@ -152,6 +161,7 @@ public Verification acceptIssuedAt(long leeway) throws IllegalArgumentException
152161
* @param jwtId the required Id value
153162
* @return this same Verification instance.
154163
*/
164+
@Override
155165
public Verification withJWTId(String jwtId) {
156166
requireClaim(PublicClaims.JWT_ID, jwtId);
157167
return this;
@@ -165,6 +175,7 @@ public Verification withJWTId(String jwtId) {
165175
* @return this same Verification instance.
166176
* @throws IllegalArgumentException if the name is null.
167177
*/
178+
@Override
168179
public Verification withClaim(String name, Boolean value) throws IllegalArgumentException {
169180
assertNonNull(name);
170181
requireClaim(name, value);
@@ -179,6 +190,7 @@ public Verification withClaim(String name, Boolean value) throws IllegalArgument
179190
* @return this same Verification instance.
180191
* @throws IllegalArgumentException if the name is null.
181192
*/
193+
@Override
182194
public Verification withClaim(String name, Integer value) throws IllegalArgumentException {
183195
assertNonNull(name);
184196
requireClaim(name, value);
@@ -193,6 +205,7 @@ public Verification withClaim(String name, Integer value) throws IllegalArgument
193205
* @return this same Verification instance.
194206
* @throws IllegalArgumentException if the name is null.
195207
*/
208+
@Override
196209
public Verification withClaim(String name, Double value) throws IllegalArgumentException {
197210
assertNonNull(name);
198211
requireClaim(name, value);
@@ -207,6 +220,7 @@ public Verification withClaim(String name, Double value) throws IllegalArgumentE
207220
* @return this same Verification instance.
208221
* @throws IllegalArgumentException if the name is null.
209222
*/
223+
@Override
210224
public Verification withClaim(String name, String value) throws IllegalArgumentException {
211225
assertNonNull(name);
212226
requireClaim(name, value);
@@ -221,6 +235,7 @@ public Verification withClaim(String name, String value) throws IllegalArgumentE
221235
* @return this same Verification instance.
222236
* @throws IllegalArgumentException if the name is null.
223237
*/
238+
@Override
224239
public Verification withClaim(String name, Date value) throws IllegalArgumentException {
225240
assertNonNull(name);
226241
requireClaim(name, value);
@@ -235,6 +250,7 @@ public Verification withClaim(String name, Date value) throws IllegalArgumentExc
235250
* @return this same Verification instance.
236251
* @throws IllegalArgumentException if the name is null.
237252
*/
253+
@Override
238254
public Verification withArrayClaim(String name, String... items) throws IllegalArgumentException {
239255
assertNonNull(name);
240256
requireClaim(name, items);
@@ -249,6 +265,7 @@ public Verification withArrayClaim(String name, String... items) throws IllegalA
249265
* @return this same Verification instance.
250266
* @throws IllegalArgumentException if the name is null.
251267
*/
268+
@Override
252269
public Verification withArrayClaim(String name, Integer... items) throws IllegalArgumentException {
253270
assertNonNull(name);
254271
requireClaim(name, items);
@@ -260,8 +277,9 @@ public Verification withArrayClaim(String name, Integer... items) throws Illegal
260277
*
261278
* @return a new JWTVerifier instance.
262279
*/
280+
@Override
263281
public JWTVerifier build() {
264-
return this.build(new Clock());
282+
return this.build(new ClockImpl());
265283
}
266284

267285
/**
@@ -271,7 +289,7 @@ public JWTVerifier build() {
271289
* @param clock the instance that will handle the current time.
272290
* @return a new JWTVerifier instance with a custom Clock.
273291
*/
274-
JWTVerifier build(Clock clock) {
292+
public JWTVerifier build(Clock clock) {
275293
addLeewayToDateClaims();
276294
return new JWTVerifier(algorithm, claims, clock);
277295
}
Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
1-
package com.auth0.jwt;
1+
package com.auth0.jwt.interfaces;
22

33
import java.util.Date;
44

55
/**
66
* The Clock class is used to wrap calls to Date class.
77
*/
8-
class Clock {
9-
10-
Clock() {
11-
}
8+
public interface Clock {
129

1310
/**
1411
* Returns a new Date representing Today's time.
1512
*
1613
* @return a new Date representing Today's time.
1714
*/
18-
Date getToday() {
19-
return new Date();
20-
}
15+
Date getToday();
2116
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.auth0.jwt.interfaces;
2+
3+
import com.auth0.jwt.JWTVerifier;
4+
5+
import java.util.Date;
6+
7+
public interface Verification {
8+
Verification withIssuer(String issuer);
9+
10+
Verification withSubject(String subject);
11+
12+
Verification withAudience(String... audience);
13+
14+
Verification acceptLeeway(long leeway) throws IllegalArgumentException;
15+
16+
Verification acceptExpiresAt(long leeway) throws IllegalArgumentException;
17+
18+
Verification acceptNotBefore(long leeway) throws IllegalArgumentException;
19+
20+
Verification acceptIssuedAt(long leeway) throws IllegalArgumentException;
21+
22+
Verification withJWTId(String jwtId);
23+
24+
Verification withClaim(String name, Boolean value) throws IllegalArgumentException;
25+
26+
Verification withClaim(String name, Integer value) throws IllegalArgumentException;
27+
28+
Verification withClaim(String name, Double value) throws IllegalArgumentException;
29+
30+
Verification withClaim(String name, String value) throws IllegalArgumentException;
31+
32+
Verification withClaim(String name, Date value) throws IllegalArgumentException;
33+
34+
Verification withArrayClaim(String name, String... items) throws IllegalArgumentException;
35+
36+
Verification withArrayClaim(String name, Integer... items) throws IllegalArgumentException;
37+
38+
JWTVerifier build();
39+
}

lib/src/test/java/com/auth0/jwt/ClockTest.java renamed to lib/src/test/java/com/auth0/jwt/ClockImplTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
package com.auth0.jwt;
22

3+
import com.auth0.jwt.interfaces.Clock;
34
import org.junit.Test;
45

56
import java.util.Date;
67

7-
import static org.hamcrest.Matchers.equalTo;
88
import static org.hamcrest.Matchers.is;
99
import static org.hamcrest.Matchers.notNullValue;
1010
import static org.junit.Assert.*;
1111

12-
public class ClockTest {
12+
public class ClockImplTest {
1313

1414
@Test
1515
public void shouldGetToday() throws Exception{
16-
Clock clock = new Clock();
16+
Clock clock = new ClockImpl();
1717
Date clockToday = clock.getToday();
1818
assertThat(clockToday, is(notNullValue()));
1919
}

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.auth0.jwt;
22

33
import com.auth0.jwt.algorithms.Algorithm;
4+
import com.auth0.jwt.interfaces.Clock;
45
import com.auth0.jwt.interfaces.DecodedJWT;
56
import org.hamcrest.collection.IsCollectionWithSize;
67
import org.hamcrest.core.IsCollectionContaining;
@@ -242,7 +243,8 @@ public void shouldGetExpirationTime() throws Exception {
242243
when(clock.getToday()).thenReturn(expectedDate);
243244

244245
String token = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0Nzc1OTJ9.x_ZjkPkKYUV5tdvc0l8go6D_z2kez1MQcOxokXrDc3k";
245-
DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret"))
246+
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret"));
247+
DecodedJWT jwt = verification
246248
.build(clock)
247249
.verify(token);
248250

@@ -259,7 +261,8 @@ public void shouldGetNotBefore() throws Exception {
259261
when(clock.getToday()).thenReturn(expectedDate);
260262

261263
String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYmYiOjE0Nzc1OTJ9.mWYSOPoNXstjKbZkKrqgkwPOQWEx3F3gMm6PMcfuJd8";
262-
DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret"))
264+
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret"));
265+
DecodedJWT jwt = verification
263266
.build(clock)
264267
.verify(token);
265268

@@ -276,7 +279,8 @@ public void shouldGetIssuedAt() throws Exception {
276279
when(clock.getToday()).thenReturn(expectedDate);
277280

278281
String token = "eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0Nzc1OTJ9.5o1CKlLFjKKcddZzoarQ37pq7qZqNPav3sdZ_bsZaD4";
279-
DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret"))
282+
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret"));
283+
DecodedJWT jwt = verification
280284
.build(clock)
281285
.verify(token);
282286

@@ -289,7 +293,8 @@ public void shouldGetIssuedAt() throws Exception {
289293
@Test
290294
public void shouldGetId() throws Exception {
291295
String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMjM0NTY3ODkwIn0.m3zgEfVUFOd-CvL3xG5BuOWLzb0zMQZCqiVNQQOPOvA";
292-
DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret"))
296+
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret"));
297+
DecodedJWT jwt = verification
293298
.build()
294299
.verify(token);
295300

0 commit comments

Comments
 (0)
X Tutup