Skip to content

Commit 0abcebe

Browse files
committed
allow to change the Clock used by the JWTVerifier
1 parent 24901e2 commit 0abcebe

7 files changed

Lines changed: 105 additions & 30 deletions

File tree

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 Clock();
162+
JWTVerifier verifier = verification.build(clock);
163+
```
155164

156165
### Header Claims
157166

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55
/**
66
* The Clock class is used to wrap calls to Date class.
77
*/
8-
class Clock {
8+
public class Clock {
99

10-
Clock() {
10+
public Clock() {
1111
}
1212

1313
/**
1414
* Returns a new Date representing Today's time.
1515
*
1616
* @return a new Date representing Today's time.
1717
*/
18-
Date getToday() {
18+
public Date getToday() {
1919
return new Date();
2020
}
2121
}

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: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.auth0.jwt.impl.PublicClaims;
99
import com.auth0.jwt.interfaces.Claim;
1010
import com.auth0.jwt.interfaces.DecodedJWT;
11+
import com.auth0.jwt.interfaces.Verification;
1112
import org.apache.commons.codec.binary.Base64;
1213

1314
import java.nio.charset.StandardCharsets;
@@ -35,19 +36,19 @@ public final class JWTVerifier {
3536
* @return a JWTVerifier.Verification instance to configure.
3637
* @throws IllegalArgumentException if the provided algorithm is null.
3738
*/
38-
static JWTVerifier.Verification init(Algorithm algorithm) throws IllegalArgumentException {
39-
return new Verification(algorithm);
39+
static Verification init(Algorithm algorithm) throws IllegalArgumentException {
40+
return new BaseVerification(algorithm);
4041
}
4142

4243
/**
4344
* The Verification class holds the Claims required by a JWT to be valid.
4445
*/
45-
public static class Verification {
46+
public static class BaseVerification implements Verification {
4647
private final Algorithm algorithm;
4748
private final Map<String, Object> claims;
4849
private long defaultLeeway;
4950

50-
Verification(Algorithm algorithm) throws IllegalArgumentException {
51+
BaseVerification(Algorithm algorithm) throws IllegalArgumentException {
5152
if (algorithm == null) {
5253
throw new IllegalArgumentException("The Algorithm cannot be null.");
5354
}
@@ -63,6 +64,7 @@ public static class Verification {
6364
* @param issuer the required Issuer value
6465
* @return this same Verification instance.
6566
*/
67+
@Override
6668
public Verification withIssuer(String issuer) {
6769
requireClaim(PublicClaims.ISSUER, issuer);
6870
return this;
@@ -74,6 +76,7 @@ public Verification withIssuer(String issuer) {
7476
* @param subject the required Subject value
7577
* @return this same Verification instance.
7678
*/
79+
@Override
7780
public Verification withSubject(String subject) {
7881
requireClaim(PublicClaims.SUBJECT, subject);
7982
return this;
@@ -85,6 +88,7 @@ public Verification withSubject(String subject) {
8588
* @param audience the required Audience value
8689
* @return this same Verification instance.
8790
*/
91+
@Override
8892
public Verification withAudience(String... audience) {
8993
requireClaim(PublicClaims.AUDIENCE, Arrays.asList(audience));
9094
return this;
@@ -98,6 +102,7 @@ public Verification withAudience(String... audience) {
98102
* @return this same Verification instance.
99103
* @throws IllegalArgumentException if leeway is negative.
100104
*/
105+
@Override
101106
public Verification acceptLeeway(long leeway) throws IllegalArgumentException {
102107
assertPositive(leeway);
103108
this.defaultLeeway = leeway;
@@ -112,6 +117,7 @@ public Verification acceptLeeway(long leeway) throws IllegalArgumentException {
112117
* @return this same Verification instance.
113118
* @throws IllegalArgumentException if leeway is negative.
114119
*/
120+
@Override
115121
public Verification acceptExpiresAt(long leeway) throws IllegalArgumentException {
116122
assertPositive(leeway);
117123
requireClaim(PublicClaims.EXPIRES_AT, leeway);
@@ -126,6 +132,7 @@ public Verification acceptExpiresAt(long leeway) throws IllegalArgumentException
126132
* @return this same Verification instance.
127133
* @throws IllegalArgumentException if leeway is negative.
128134
*/
135+
@Override
129136
public Verification acceptNotBefore(long leeway) throws IllegalArgumentException {
130137
assertPositive(leeway);
131138
requireClaim(PublicClaims.NOT_BEFORE, leeway);
@@ -140,6 +147,7 @@ public Verification acceptNotBefore(long leeway) throws IllegalArgumentException
140147
* @return this same Verification instance.
141148
* @throws IllegalArgumentException if leeway is negative.
142149
*/
150+
@Override
143151
public Verification acceptIssuedAt(long leeway) throws IllegalArgumentException {
144152
assertPositive(leeway);
145153
requireClaim(PublicClaims.ISSUED_AT, leeway);
@@ -152,6 +160,7 @@ public Verification acceptIssuedAt(long leeway) throws IllegalArgumentException
152160
* @param jwtId the required Id value
153161
* @return this same Verification instance.
154162
*/
163+
@Override
155164
public Verification withJWTId(String jwtId) {
156165
requireClaim(PublicClaims.JWT_ID, jwtId);
157166
return this;
@@ -165,6 +174,7 @@ public Verification withJWTId(String jwtId) {
165174
* @return this same Verification instance.
166175
* @throws IllegalArgumentException if the name is null.
167176
*/
177+
@Override
168178
public Verification withClaim(String name, Boolean value) throws IllegalArgumentException {
169179
assertNonNull(name);
170180
requireClaim(name, value);
@@ -179,6 +189,7 @@ public Verification withClaim(String name, Boolean value) throws IllegalArgument
179189
* @return this same Verification instance.
180190
* @throws IllegalArgumentException if the name is null.
181191
*/
192+
@Override
182193
public Verification withClaim(String name, Integer value) throws IllegalArgumentException {
183194
assertNonNull(name);
184195
requireClaim(name, value);
@@ -193,6 +204,7 @@ public Verification withClaim(String name, Integer value) throws IllegalArgument
193204
* @return this same Verification instance.
194205
* @throws IllegalArgumentException if the name is null.
195206
*/
207+
@Override
196208
public Verification withClaim(String name, Double value) throws IllegalArgumentException {
197209
assertNonNull(name);
198210
requireClaim(name, value);
@@ -207,6 +219,7 @@ public Verification withClaim(String name, Double value) throws IllegalArgumentE
207219
* @return this same Verification instance.
208220
* @throws IllegalArgumentException if the name is null.
209221
*/
222+
@Override
210223
public Verification withClaim(String name, String value) throws IllegalArgumentException {
211224
assertNonNull(name);
212225
requireClaim(name, value);
@@ -221,6 +234,7 @@ public Verification withClaim(String name, String value) throws IllegalArgumentE
221234
* @return this same Verification instance.
222235
* @throws IllegalArgumentException if the name is null.
223236
*/
237+
@Override
224238
public Verification withClaim(String name, Date value) throws IllegalArgumentException {
225239
assertNonNull(name);
226240
requireClaim(name, value);
@@ -235,6 +249,7 @@ public Verification withClaim(String name, Date value) throws IllegalArgumentExc
235249
* @return this same Verification instance.
236250
* @throws IllegalArgumentException if the name is null.
237251
*/
252+
@Override
238253
public Verification withArrayClaim(String name, String... items) throws IllegalArgumentException {
239254
assertNonNull(name);
240255
requireClaim(name, items);
@@ -249,6 +264,7 @@ public Verification withArrayClaim(String name, String... items) throws IllegalA
249264
* @return this same Verification instance.
250265
* @throws IllegalArgumentException if the name is null.
251266
*/
267+
@Override
252268
public Verification withArrayClaim(String name, Integer... items) throws IllegalArgumentException {
253269
assertNonNull(name);
254270
requireClaim(name, items);
@@ -260,6 +276,7 @@ public Verification withArrayClaim(String name, Integer... items) throws Illegal
260276
*
261277
* @return a new JWTVerifier instance.
262278
*/
279+
@Override
263280
public JWTVerifier build() {
264281
return this.build(new Clock());
265282
}
@@ -271,7 +288,7 @@ public JWTVerifier build() {
271288
* @param clock the instance that will handle the current time.
272289
* @return a new JWTVerifier instance with a custom Clock.
273290
*/
274-
JWTVerifier build(Clock clock) {
291+
public JWTVerifier build(Clock clock) {
275292
addLeewayToDateClaims();
276293
return new JWTVerifier(algorithm, claims, clock);
277294
}
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/JWTTest.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ public void shouldGetExpirationTime() throws Exception {
242242
when(clock.getToday()).thenReturn(expectedDate);
243243

244244
String token = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0Nzc1OTJ9.x_ZjkPkKYUV5tdvc0l8go6D_z2kez1MQcOxokXrDc3k";
245-
DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret"))
245+
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret"));
246+
DecodedJWT jwt = verification
246247
.build(clock)
247248
.verify(token);
248249

@@ -259,7 +260,8 @@ public void shouldGetNotBefore() throws Exception {
259260
when(clock.getToday()).thenReturn(expectedDate);
260261

261262
String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYmYiOjE0Nzc1OTJ9.mWYSOPoNXstjKbZkKrqgkwPOQWEx3F3gMm6PMcfuJd8";
262-
DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret"))
263+
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret"));
264+
DecodedJWT jwt = verification
263265
.build(clock)
264266
.verify(token);
265267

@@ -276,7 +278,8 @@ public void shouldGetIssuedAt() throws Exception {
276278
when(clock.getToday()).thenReturn(expectedDate);
277279

278280
String token = "eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0Nzc1OTJ9.5o1CKlLFjKKcddZzoarQ37pq7qZqNPav3sdZ_bsZaD4";
279-
DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret"))
281+
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret"));
282+
DecodedJWT jwt = verification
280283
.build(clock)
281284
.verify(token);
282285

@@ -289,7 +292,8 @@ public void shouldGetIssuedAt() throws Exception {
289292
@Test
290293
public void shouldGetId() throws Exception {
291294
String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMjM0NTY3ODkwIn0.m3zgEfVUFOd-CvL3xG5BuOWLzb0zMQZCqiVNQQOPOvA";
292-
DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret"))
295+
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret"));
296+
DecodedJWT jwt = verification
293297
.build()
294298
.verify(token);
295299

0 commit comments

Comments
 (0)