Эх сурвалжийг харах

Ensure ID Token is active before processing logout request

Issue gh-1077
Joe Grandja 2 жил өмнө
parent
commit
597abe18c3

+ 6 - 1
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcLogoutAuthenticationProvider.java

@@ -91,6 +91,11 @@ public final class OidcLogoutAuthenticationProvider implements AuthenticationPro
 			this.logger.trace("Retrieved authorization with ID Token");
 		}
 
+		OAuth2Authorization.Token<OidcIdToken> authorizedIdToken = authorization.getToken(OidcIdToken.class);
+		if (!authorizedIdToken.isActive()) {
+			throwError(OAuth2ErrorCodes.INVALID_TOKEN, "id_token_hint");
+		}
+
 		RegisteredClient registeredClient = this.registeredClientRepository.findById(
 				authorization.getRegisteredClientId());
 
@@ -98,7 +103,7 @@ public final class OidcLogoutAuthenticationProvider implements AuthenticationPro
 			this.logger.trace("Retrieved registered client");
 		}
 
-		OidcIdToken idToken = authorization.getToken(OidcIdToken.class).getToken();
+		OidcIdToken idToken = authorizedIdToken.getToken();
 
 		// Validate client identity
 		List<String> audClaim = idToken.getAudience();

+ 35 - 0
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcLogoutAuthenticationProviderTests.java

@@ -129,6 +129,41 @@ public class OidcLogoutAuthenticationProviderTests {
 				eq(authentication.getIdTokenHint()), eq(ID_TOKEN_TOKEN_TYPE));
 	}
 
+	@Test
+	public void authenticateWhenIdTokenNotActiveThenThrowOAuth2AuthenticationException() {
+		TestingAuthenticationToken principal = new TestingAuthenticationToken("principal", "credentials");
+		RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
+		OidcIdToken idToken =  OidcIdToken.withTokenValue("id-token")
+				.issuer("https://provider.com")
+				.subject(principal.getName())
+				.issuedAt(Instant.now().minusSeconds(60).truncatedTo(ChronoUnit.MILLIS))
+				.expiresAt(Instant.now().plusSeconds(60).truncatedTo(ChronoUnit.MILLIS))
+				.build();
+		OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient)
+				.principalName(principal.getName())
+				.token(idToken, (metadata) -> {
+					metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, idToken.getClaims());
+					metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true);
+				})
+				.build();
+		when(this.authorizationService.findByToken(eq(idToken.getTokenValue()), eq(ID_TOKEN_TOKEN_TYPE)))
+				.thenReturn(authorization);
+
+		OidcLogoutAuthenticationToken authentication = new OidcLogoutAuthenticationToken(
+				idToken.getTokenValue(), principal, "session-1", null, null, null);
+
+		assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
+				.isInstanceOf(OAuth2AuthenticationException.class)
+				.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
+				.satisfies(error -> {
+					assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_TOKEN);
+					assertThat(error.getDescription()).contains("id_token_hint");
+				});
+
+		verify(this.authorizationService).findByToken(
+				eq(authentication.getIdTokenHint()), eq(ID_TOKEN_TOKEN_TYPE));
+	}
+
 	@Test
 	public void authenticateWhenMissingAudienceThenThrowOAuth2AuthenticationException() {
 		TestingAuthenticationToken principal = new TestingAuthenticationToken("principal", "credentials");