15
15
*/
16
16
package org .springframework .security .oauth2 .jwt ;
17
17
18
- import java .time .Clock ;
19
- import java .time .Duration ;
20
- import java .time .Instant ;
21
- import java .time .temporal .ChronoUnit ;
22
-
18
+ import org .apache .commons .logging .Log ;
19
+ import org .apache .commons .logging .LogFactory ;
23
20
import org .springframework .security .oauth2 .core .OAuth2Error ;
24
21
import org .springframework .security .oauth2 .core .OAuth2ErrorCodes ;
25
22
import org .springframework .security .oauth2 .core .OAuth2TokenValidator ;
26
23
import org .springframework .security .oauth2 .core .OAuth2TokenValidatorResult ;
27
24
import org .springframework .util .Assert ;
28
25
26
+ import java .time .Clock ;
27
+ import java .time .Duration ;
28
+ import java .time .Instant ;
29
+ import java .time .format .DateTimeFormatter ;
30
+ import java .time .temporal .ChronoUnit ;
31
+
29
32
/**
30
33
* An implementation of {@link OAuth2TokenValidator} for verifying claims in a Jwt-based access token
31
34
*
41
44
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc7519">JSON Web Token (JWT)</a>
42
45
*/
43
46
public final class JwtTimestampValidator implements OAuth2TokenValidator <Jwt > {
47
+ private final Log logger = LogFactory .getLog (getClass ());
48
+
44
49
private static final Duration DEFAULT_MAX_CLOCK_SKEW = Duration .of (60 , ChronoUnit .SECONDS );
45
50
46
51
private final Duration clockSkew ;
@@ -56,7 +61,6 @@ public JwtTimestampValidator() {
56
61
57
62
public JwtTimestampValidator (Duration clockSkew ) {
58
63
Assert .notNull (clockSkew , "clockSkew cannot be null" );
59
-
60
64
this .clockSkew = clockSkew ;
61
65
}
62
66
@@ -71,29 +75,31 @@ public OAuth2TokenValidatorResult validate(Jwt jwt) {
71
75
72
76
if (expiry != null ) {
73
77
if (Instant .now (this .clock ).minus (clockSkew ).isAfter (expiry )) {
74
- OAuth2Error error = new OAuth2Error (
75
- OAuth2ErrorCodes .INVALID_REQUEST ,
76
- String .format ("Jwt expired at %s" , jwt .getExpiresAt ()),
77
- "https://tools.ietf.org/html/rfc6750#section-3.1" );
78
- return OAuth2TokenValidatorResult .failure (error );
78
+ OAuth2Error oAuth2Error = createOAuth2Error (String .format ("Jwt expired at %s" , jwt .getExpiresAt ()));
79
+ return OAuth2TokenValidatorResult .failure (oAuth2Error );
79
80
}
80
81
}
81
82
82
83
Instant notBefore = jwt .getNotBefore ();
83
84
84
85
if (notBefore != null ) {
85
86
if (Instant .now (this .clock ).plus (clockSkew ).isBefore (notBefore )) {
86
- OAuth2Error error = new OAuth2Error (
87
- OAuth2ErrorCodes .INVALID_REQUEST ,
88
- String .format ("Jwt used before %s" , jwt .getNotBefore ()),
89
- "https://tools.ietf.org/html/rfc6750#section-3.1" );
90
- return OAuth2TokenValidatorResult .failure (error );
87
+ OAuth2Error oAuth2Error = createOAuth2Error (String .format ("Jwt used before %s" , jwt .getNotBefore ()));
88
+ return OAuth2TokenValidatorResult .failure (oAuth2Error );
91
89
}
92
90
}
93
91
94
92
return OAuth2TokenValidatorResult .success ();
95
93
}
96
94
95
+ private OAuth2Error createOAuth2Error (String reason ) {
96
+ logger .debug (reason );
97
+ return new OAuth2Error (
98
+ OAuth2ErrorCodes .INVALID_REQUEST ,
99
+ reason ,
100
+ "https://tools.ietf.org/html/rfc6750#section-3.1" );
101
+ }
102
+
97
103
/**
98
104
* '
99
105
* Use this {@link Clock} with {@link Instant#now()} for assessing
0 commit comments