| 
					
				 | 
			
			
				@@ -15,17 +15,20 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 package org.springframework.security.oauth2.jwt; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.time.Clock; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.time.Duration; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.time.Instant; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.time.temporal.ChronoUnit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.apache.commons.logging.Log; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.apache.commons.logging.LogFactory; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.security.oauth2.core.OAuth2Error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.security.oauth2.core.OAuth2ErrorCodes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.security.oauth2.core.OAuth2TokenValidator; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.util.Assert; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.time.Clock; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.time.Duration; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.time.Instant; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.time.format.DateTimeFormatter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.time.temporal.ChronoUnit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * An implementation of {@link OAuth2TokenValidator} for verifying claims in a Jwt-based access token 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -41,6 +44,8 @@ import org.springframework.util.Assert; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * @see <a target="_blank" href="https://tools.ietf.org/html/rfc7519">JSON Web Token (JWT)</a> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 public final class JwtTimestampValidator implements OAuth2TokenValidator<Jwt> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private final Log logger = LogFactory.getLog(getClass()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	private static final Duration DEFAULT_MAX_CLOCK_SKEW = Duration.of(60, ChronoUnit.SECONDS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	private final Duration clockSkew; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -56,7 +61,6 @@ public final class JwtTimestampValidator implements OAuth2TokenValidator<Jwt> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	public JwtTimestampValidator(Duration clockSkew) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		Assert.notNull(clockSkew, "clockSkew cannot be null"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		this.clockSkew = clockSkew; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -71,11 +75,8 @@ public final class JwtTimestampValidator implements OAuth2TokenValidator<Jwt> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if (expiry != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			if (Instant.now(this.clock).minus(clockSkew).isAfter(expiry)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				OAuth2Error error = new OAuth2Error( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						OAuth2ErrorCodes.INVALID_REQUEST, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						String.format("Jwt expired at %s", jwt.getExpiresAt()), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						"https://tools.ietf.org/html/rfc6750#section-3.1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				return OAuth2TokenValidatorResult.failure(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				OAuth2Error oAuth2Error = createOAuth2Error(String.format("Jwt expired at %s", jwt.getExpiresAt())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return OAuth2TokenValidatorResult.failure(oAuth2Error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -83,17 +84,22 @@ public final class JwtTimestampValidator implements OAuth2TokenValidator<Jwt> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if (notBefore != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			if (Instant.now(this.clock).plus(clockSkew).isBefore(notBefore)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				OAuth2Error error = new OAuth2Error( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						OAuth2ErrorCodes.INVALID_REQUEST, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						String.format("Jwt used before %s", jwt.getNotBefore()), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						"https://tools.ietf.org/html/rfc6750#section-3.1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				return OAuth2TokenValidatorResult.failure(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				OAuth2Error oAuth2Error = createOAuth2Error(String.format("Jwt used before %s", jwt.getNotBefore())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return OAuth2TokenValidatorResult.failure(oAuth2Error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		return OAuth2TokenValidatorResult.success(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private OAuth2Error createOAuth2Error(String reason) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		logger.debug(reason); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return new OAuth2Error( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				OAuth2ErrorCodes.INVALID_REQUEST, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				reason, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				"https://tools.ietf.org/html/rfc6750#section-3.1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 * ' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 * Use this {@link Clock} with {@link Instant#now()} for assessing 
			 |