Apply Spring formatting to 1.3.x

Issue gh-1616
This commit is contained in:
Joe Grandja
2024-05-16 12:27:18 -04:00
parent 041b94d682
commit 320176a67b
84 changed files with 1446 additions and 1226 deletions

View File

@@ -48,23 +48,23 @@ public class OAuth2AuthorizationServerMetadataTests {
@Test
public void buildWhenAllClaimsProvidedThenCreated() {
OAuth2AuthorizationServerMetadata authorizationServerMetadata = OAuth2AuthorizationServerMetadata.builder()
.issuer("https://example.com")
.authorizationEndpoint("https://example.com/oauth2/authorize")
.tokenEndpoint("https://example.com/oauth2/token")
.tokenEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue())
.jwkSetUrl("https://example.com/oauth2/jwks")
.scope("openid")
.responseType("code")
.grantType("authorization_code")
.grantType("client_credentials")
.tokenRevocationEndpoint("https://example.com/oauth2/revoke")
.tokenRevocationEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue())
.tokenIntrospectionEndpoint("https://example.com/oauth2/introspect")
.tokenIntrospectionEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue())
.codeChallengeMethod("S256")
.tlsClientCertificateBoundAccessTokens(true)
.claim("a-claim", "a-value")
.build();
.issuer("https://example.com")
.authorizationEndpoint("https://example.com/oauth2/authorize")
.tokenEndpoint("https://example.com/oauth2/token")
.tokenEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue())
.jwkSetUrl("https://example.com/oauth2/jwks")
.scope("openid")
.responseType("code")
.grantType("authorization_code")
.grantType("client_credentials")
.tokenRevocationEndpoint("https://example.com/oauth2/revoke")
.tokenRevocationEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue())
.tokenIntrospectionEndpoint("https://example.com/oauth2/introspect")
.tokenIntrospectionEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue())
.codeChallengeMethod("S256")
.tlsClientCertificateBoundAccessTokens(true)
.claim("a-claim", "a-value")
.build();
assertThat(authorizationServerMetadata.getIssuer()).isEqualTo(url("https://example.com"));
assertThat(authorizationServerMetadata.getAuthorizationEndpoint())

View File

@@ -92,8 +92,8 @@ public class TestOAuth2Authorizations {
.attribute(Principal.class.getName(),
new TestingAuthenticationToken("principal", null, "ROLE_A", "ROLE_B"));
if (accessToken != null) {
OAuth2RefreshToken refreshToken = new OAuth2RefreshToken(
"refresh-token", Instant.now(), Instant.now().plus(1, ChronoUnit.HOURS));
OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", Instant.now(),
Instant.now().plus(1, ChronoUnit.HOURS));
builder
.token(accessToken, (metadata) -> metadata.putAll(tokenMetadata(registeredClient, accessTokenClaims)))
.refreshToken(refreshToken);
@@ -102,7 +102,8 @@ public class TestOAuth2Authorizations {
return builder;
}
private static Map<String, Object> tokenMetadata(RegisteredClient registeredClient, Map<String, Object> tokenClaims) {
private static Map<String, Object> tokenMetadata(RegisteredClient registeredClient,
Map<String, Object> tokenClaims) {
Map<String, Object> tokenMetadata = new HashMap<>();
OAuth2TokenFormat accessTokenFormat = registeredClient.getTokenSettings().getAccessTokenFormat();
tokenMetadata.put(OAuth2TokenFormat.class.getName(), accessTokenFormat.getValue());

View File

@@ -34,39 +34,43 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
* @author Dmitriy Dubson
*/
public class OAuth2AccessTokenAuthenticationContextTests {
private final RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
private final OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(this.registeredClient).build();
private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret());
private final OAuth2AccessTokenAuthenticationToken accessTokenAuthenticationToken =
new OAuth2AccessTokenAuthenticationToken(this.registeredClient, this.clientPrincipal,
this.authorization.getAccessToken().getToken(), this.authorization.getRefreshToken().getToken());
private final OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(this.registeredClient)
.build();
private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(this.registeredClient,
ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret());
private final OAuth2AccessTokenAuthenticationToken accessTokenAuthenticationToken = new OAuth2AccessTokenAuthenticationToken(
this.registeredClient, this.clientPrincipal, this.authorization.getAccessToken().getToken(),
this.authorization.getRefreshToken().getToken());
@Test
public void withWhenAuthenticationNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> OAuth2AccessTokenAuthenticationContext.with(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authentication cannot be null");
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authentication cannot be null");
}
@Test
public void setWhenValueNullThenThrowIllegalArgumentException() {
OAuth2AccessTokenAuthenticationContext.Builder builder =
OAuth2AccessTokenAuthenticationContext.with(this.accessTokenAuthenticationToken);
OAuth2AccessTokenAuthenticationContext.Builder builder = OAuth2AccessTokenAuthenticationContext
.with(this.accessTokenAuthenticationToken);
assertThatThrownBy(() -> builder.accessTokenResponse(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("value cannot be null");
assertThatThrownBy(() -> builder.accessTokenResponse(null)).isInstanceOf(IllegalArgumentException.class)
.hasMessage("value cannot be null");
}
@Test
public void buildWhenAllValuesProvidedThenAllValuesAreSet() {
OAuth2AccessTokenResponse.Builder accessTokenResponseBuilder =
OAuth2AccessTokenResponse.withToken(this.accessTokenAuthenticationToken.getAccessToken().getTokenValue());
OAuth2AccessTokenAuthenticationContext context =
OAuth2AccessTokenAuthenticationContext.with(this.accessTokenAuthenticationToken)
.accessTokenResponse(accessTokenResponseBuilder)
.build();
OAuth2AccessTokenResponse.Builder accessTokenResponseBuilder = OAuth2AccessTokenResponse
.withToken(this.accessTokenAuthenticationToken.getAccessToken().getTokenValue());
OAuth2AccessTokenAuthenticationContext context = OAuth2AccessTokenAuthenticationContext
.with(this.accessTokenAuthenticationToken)
.accessTokenResponse(accessTokenResponseBuilder)
.build();
assertThat(context.<Authentication>getAuthentication()).isEqualTo(this.accessTokenAuthenticationToken);
assertThat(context.getAccessTokenResponse()).isEqualTo(accessTokenResponseBuilder);

View File

@@ -146,8 +146,8 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
@Test
public void setAuthorizationConsentRequiredWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> this.authenticationProvider.setAuthorizationConsentRequired(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authorizationConsentRequired cannot be null");
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authorizationConsentRequired cannot be null");
}
@Test
@@ -486,23 +486,24 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
@Test
public void authenticateWhenCustomAuthorizationConsentRequiredThenUsed() {
@SuppressWarnings("unchecked")
Predicate<OAuth2AuthorizationCodeRequestAuthenticationContext> authorizationConsentRequired = mock(Predicate.class);
Predicate<OAuth2AuthorizationCodeRequestAuthenticationContext> authorizationConsentRequired = mock(
Predicate.class);
this.authenticationProvider.setAuthorizationConsentRequired(authorizationConsentRequired);
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
.thenReturn(registeredClient);
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[1];
OAuth2AuthorizationCodeRequestAuthenticationToken authentication =
new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), principal,
redirectUri, STATE, registeredClient.getScopes(), null);
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), principal, redirectUri, STATE,
registeredClient.getScopes(), null);
OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult =
(OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider.authenticate(authentication);
OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication);
assertAuthorizationCodeRequestWithAuthorizationCodeResult(registeredClient, authentication, authenticationResult);
assertAuthorizationCodeRequestWithAuthorizationCodeResult(registeredClient, authentication,
authenticationResult);
verify(authorizationConsentRequired).test(any());
}

View File

@@ -145,8 +145,8 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
@Test
public void setAuthenticationValidatorWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> this.authenticationProvider.setAuthenticationValidator(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authenticationValidator cannot be null");
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authenticationValidator cannot be null");
}
@Test
@@ -325,10 +325,10 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
@Test
public void authenticateWhenCustomAuthenticationValidatorThenUsed() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
OAuth2ClientCredentialsAuthenticationToken authentication =
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, registeredClient.getScopes(), null);
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient,
ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
OAuth2ClientCredentialsAuthenticationToken authentication = new OAuth2ClientCredentialsAuthenticationToken(
clientPrincipal, registeredClient.getScopes(), null);
@SuppressWarnings("unchecked")
Consumer<OAuth2ClientCredentialsAuthenticationContext> authenticationValidator = mock(Consumer.class);

View File

@@ -70,15 +70,24 @@ import static org.mockito.Mockito.when;
* @author Steve Riesenberg
*/
public class OAuth2TokenExchangeAuthenticationProviderTests {
private static final Set<String> RESOURCES = Set.of("https://mydomain.com/resource1", "https://mydomain.com/resource2");
private static final Set<String> RESOURCES = Set.of("https://mydomain.com/resource1",
"https://mydomain.com/resource2");
private static final Set<String> AUDIENCES = Set.of("audience1", "audience2");
private static final String SUBJECT_TOKEN = "EfYu_0jEL";
private static final String ACTOR_TOKEN = "JlNE_xR1f";
private static final String ACCESS_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:access_token";
private static final String JWT_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:jwt";
private OAuth2AuthorizationService authorizationService;
private OAuth2TokenGenerator<OAuth2Token> tokenGenerator;
private OAuth2TokenExchangeAuthenticationProvider authenticationProvider;
@BeforeEach
@@ -168,7 +177,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenSubjectTokenNotFoundThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient);
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(null);
// @formatter:off
@@ -187,10 +197,12 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenSubjectTokenNotActiveThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createExpiredAccessToken(SUBJECT_TOKEN)).build();
.token(createExpiredAccessToken(SUBJECT_TOKEN))
.build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(authorization);
// @formatter:off
assertThatExceptionOfType(OAuth2AuthenticationException.class)
@@ -208,10 +220,12 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenSubjectTokenTypeJwtAndSubjectTokenFormatReferenceThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createJwtRequest(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(SUBJECT_TOKEN), withTokenFormat(OAuth2TokenFormat.REFERENCE)).build();
.token(createAccessToken(SUBJECT_TOKEN), withTokenFormat(OAuth2TokenFormat.REFERENCE))
.build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(authorization);
// @formatter:off
assertThatExceptionOfType(OAuth2AuthenticationException.class)
@@ -229,7 +243,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenSubjectPrincipalNullThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient);
// @formatter:off
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient)
@@ -254,12 +269,14 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenActorTokenNotFoundThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient);
OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(SUBJECT_TOKEN)).build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(
subjectAuthorization, (OAuth2Authorization) null);
.token(createAccessToken(SUBJECT_TOKEN))
.build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class)))
.thenReturn(subjectAuthorization, (OAuth2Authorization) null);
// @formatter:off
assertThatExceptionOfType(OAuth2AuthenticationException.class)
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
@@ -277,14 +294,17 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenActorTokenNotActiveThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient);
OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(SUBJECT_TOKEN)).build();
.token(createAccessToken(SUBJECT_TOKEN))
.build();
OAuth2Authorization actorAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createExpiredAccessToken(ACTOR_TOKEN)).build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(
subjectAuthorization, actorAuthorization);
.token(createExpiredAccessToken(ACTOR_TOKEN))
.build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class)))
.thenReturn(subjectAuthorization, actorAuthorization);
// @formatter:off
assertThatExceptionOfType(OAuth2AuthenticationException.class)
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
@@ -302,14 +322,17 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenActorTokenTypeJwtAndActorTokenFormatReferenceThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createJwtRequest(registeredClient);
OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(SUBJECT_TOKEN), withTokenFormat(OAuth2TokenFormat.SELF_CONTAINED)).build();
.token(createAccessToken(SUBJECT_TOKEN), withTokenFormat(OAuth2TokenFormat.SELF_CONTAINED))
.build();
OAuth2Authorization actorAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(ACTOR_TOKEN), withTokenFormat(OAuth2TokenFormat.REFERENCE)).build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(
subjectAuthorization, actorAuthorization);
.token(createAccessToken(ACTOR_TOKEN), withTokenFormat(OAuth2TokenFormat.REFERENCE))
.build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class)))
.thenReturn(subjectAuthorization, actorAuthorization);
// @formatter:off
assertThatExceptionOfType(OAuth2AuthenticationException.class)
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
@@ -327,7 +350,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenMayActAndActorIssClaimNotAuthorizedThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient);
Map<String, String> authorizedActorClaims = Map.of(OAuth2TokenClaimNames.ISS, "issuer",
OAuth2TokenClaimNames.SUB, "actor");
@@ -339,9 +363,10 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
Map<String, Object> actorTokenClaims = Map.of(OAuth2TokenClaimNames.ISS, "invalid-issuer",
OAuth2TokenClaimNames.SUB, "actor");
OAuth2Authorization actorAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(ACTOR_TOKEN), withClaims(actorTokenClaims)).build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(
subjectAuthorization, actorAuthorization);
.token(createAccessToken(ACTOR_TOKEN), withClaims(actorTokenClaims))
.build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class)))
.thenReturn(subjectAuthorization, actorAuthorization);
// @formatter:off
assertThatExceptionOfType(OAuth2AuthenticationException.class)
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
@@ -359,7 +384,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenMayActAndActorSubClaimNotAuthorizedThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient);
Map<String, String> authorizedActorClaims = Map.of(OAuth2TokenClaimNames.ISS, "issuer",
OAuth2TokenClaimNames.SUB, "actor");
@@ -371,9 +397,10 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
Map<String, Object> actorTokenClaims = Map.of(OAuth2TokenClaimNames.ISS, "issuer", OAuth2TokenClaimNames.SUB,
"invalid-actor");
OAuth2Authorization actorAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(ACTOR_TOKEN), withClaims(actorTokenClaims)).build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(
subjectAuthorization, actorAuthorization);
.token(createAccessToken(ACTOR_TOKEN), withClaims(actorTokenClaims))
.build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class)))
.thenReturn(subjectAuthorization, actorAuthorization);
// @formatter:off
assertThatExceptionOfType(OAuth2AuthenticationException.class)
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
@@ -391,7 +418,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenMayActAndImpersonationThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createImpersonationRequest(registeredClient);
Map<String, String> authorizedActorClaims = Map.of(OAuth2TokenClaimNames.ISS, "issuer",
OAuth2TokenClaimNames.SUB, "actor");
@@ -400,8 +428,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
.token(createAccessToken(SUBJECT_TOKEN), withClaims(Map.of("may_act", authorizedActorClaims)))
.build();
// @formatter:on
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(
subjectAuthorization);
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class)))
.thenReturn(subjectAuthorization);
// @formatter:off
assertThatExceptionOfType(OAuth2AuthenticationException.class)
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
@@ -418,15 +446,18 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenInvalidScopeInRequestThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient,
Set.of("invalid"));
OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(SUBJECT_TOKEN)).build();
.token(createAccessToken(SUBJECT_TOKEN))
.build();
OAuth2Authorization actorAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(ACTOR_TOKEN)).build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(
subjectAuthorization, actorAuthorization);
.token(createAccessToken(ACTOR_TOKEN))
.build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class)))
.thenReturn(subjectAuthorization, actorAuthorization);
// @formatter:off
assertThatExceptionOfType(OAuth2AuthenticationException.class)
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
@@ -444,14 +475,18 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenInvalidScopeInSubjectAuthorizationThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient, Set.of());
OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(SUBJECT_TOKEN)).authorizedScopes(Set.of("invalid")).build();
.token(createAccessToken(SUBJECT_TOKEN))
.authorizedScopes(Set.of("invalid"))
.build();
OAuth2Authorization actorAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(ACTOR_TOKEN)).build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(
subjectAuthorization, actorAuthorization);
.token(createAccessToken(ACTOR_TOKEN))
.build();
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class)))
.thenReturn(subjectAuthorization, actorAuthorization);
// @formatter:off
assertThatExceptionOfType(OAuth2AuthenticationException.class)
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
@@ -469,7 +504,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenNoActorTokenAndValidTokenExchangeThenReturnAccessTokenForImpersonation() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createImpersonationRequest(registeredClient);
TestingAuthenticationToken userPrincipal = new TestingAuthenticationToken("user", null, "ROLE_USER");
// @formatter:off
@@ -478,19 +514,19 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
.attribute(Principal.class.getName(), userPrincipal)
.build();
// @formatter:on
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(
subjectAuthorization);
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class)))
.thenReturn(subjectAuthorization);
OAuth2AccessToken accessToken = createAccessToken("token-value");
when(this.tokenGenerator.generate(any(OAuth2TokenContext.class))).thenReturn(accessToken);
OAuth2AccessTokenAuthenticationToken authenticationResult =
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
OAuth2AccessTokenAuthenticationToken authenticationResult = (OAuth2AccessTokenAuthenticationToken) this.authenticationProvider
.authenticate(authentication);
assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient);
assertThat(authenticationResult.getPrincipal()).isEqualTo(authentication.getPrincipal());
assertThat(authenticationResult.getAccessToken()).isEqualTo(accessToken);
assertThat(authenticationResult.getRefreshToken()).isNull();
assertThat(authenticationResult.getAdditionalParameters()).hasSize(1);
assertThat(authenticationResult.getAdditionalParameters().get(OAuth2ParameterNames.ISSUED_TOKEN_TYPE))
.isEqualTo(JWT_TOKEN_TYPE_VALUE);
.isEqualTo(JWT_TOKEN_TYPE_VALUE);
ArgumentCaptor<OAuth2Authorization> authorizationCaptor = ArgumentCaptor.forClass(OAuth2Authorization.class);
ArgumentCaptor<OAuth2TokenContext> tokenContextCaptor = ArgumentCaptor.forClass(OAuth2TokenContext.class);
@@ -521,32 +557,33 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenNoActorTokenAndPreviousActorThenReturnAccessTokenForImpersonation() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createImpersonationRequest(registeredClient);
TestingAuthenticationToken userPrincipal = new TestingAuthenticationToken("user", null, "ROLE_USER");
OAuth2TokenExchangeActor previousActor = new OAuth2TokenExchangeActor(Map.of(OAuth2TokenClaimNames.ISS, "issuer1",
OAuth2TokenClaimNames.SUB, "actor"));
OAuth2TokenExchangeCompositeAuthenticationToken subjectPrincipal =
new OAuth2TokenExchangeCompositeAuthenticationToken(userPrincipal, List.of(previousActor));
OAuth2TokenExchangeActor previousActor = new OAuth2TokenExchangeActor(
Map.of(OAuth2TokenClaimNames.ISS, "issuer1", OAuth2TokenClaimNames.SUB, "actor"));
OAuth2TokenExchangeCompositeAuthenticationToken subjectPrincipal = new OAuth2TokenExchangeCompositeAuthenticationToken(
userPrincipal, List.of(previousActor));
// @formatter:off
OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(SUBJECT_TOKEN))
.attribute(Principal.class.getName(), subjectPrincipal)
.build();
// @formatter:on
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(
subjectAuthorization);
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class)))
.thenReturn(subjectAuthorization);
OAuth2AccessToken accessToken = createAccessToken("token-value");
when(this.tokenGenerator.generate(any(OAuth2TokenContext.class))).thenReturn(accessToken);
OAuth2AccessTokenAuthenticationToken authenticationResult =
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
OAuth2AccessTokenAuthenticationToken authenticationResult = (OAuth2AccessTokenAuthenticationToken) this.authenticationProvider
.authenticate(authentication);
assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient);
assertThat(authenticationResult.getPrincipal()).isEqualTo(authentication.getPrincipal());
assertThat(authenticationResult.getAccessToken()).isEqualTo(accessToken);
assertThat(authenticationResult.getRefreshToken()).isNull();
assertThat(authenticationResult.getAdditionalParameters()).hasSize(1);
assertThat(authenticationResult.getAdditionalParameters().get(OAuth2ParameterNames.ISSUED_TOKEN_TYPE))
.isEqualTo(JWT_TOKEN_TYPE_VALUE);
.isEqualTo(JWT_TOKEN_TYPE_VALUE);
ArgumentCaptor<OAuth2Authorization> authorizationCaptor = ArgumentCaptor.forClass(OAuth2Authorization.class);
ArgumentCaptor<OAuth2TokenContext> tokenContextCaptor = ArgumentCaptor.forClass(OAuth2TokenContext.class);
@@ -577,15 +614,16 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
@Test
public void authenticateWhenActorTokenAndValidTokenExchangeThenReturnAccessTokenForDelegation() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient);
TestingAuthenticationToken userPrincipal = new TestingAuthenticationToken("user", null, "ROLE_USER");
OAuth2TokenExchangeActor actor1 = new OAuth2TokenExchangeActor(Map.of(OAuth2TokenClaimNames.ISS, "issuer1",
OAuth2TokenClaimNames.SUB, "actor1"));
OAuth2TokenExchangeActor actor2 = new OAuth2TokenExchangeActor(Map.of(OAuth2TokenClaimNames.ISS, "issuer2",
OAuth2TokenClaimNames.SUB, "actor2"));
OAuth2TokenExchangeCompositeAuthenticationToken subjectPrincipal =
new OAuth2TokenExchangeCompositeAuthenticationToken(userPrincipal, List.of(actor1));
OAuth2TokenExchangeActor actor1 = new OAuth2TokenExchangeActor(
Map.of(OAuth2TokenClaimNames.ISS, "issuer1", OAuth2TokenClaimNames.SUB, "actor1"));
OAuth2TokenExchangeActor actor2 = new OAuth2TokenExchangeActor(
Map.of(OAuth2TokenClaimNames.ISS, "issuer2", OAuth2TokenClaimNames.SUB, "actor2"));
OAuth2TokenExchangeCompositeAuthenticationToken subjectPrincipal = new OAuth2TokenExchangeCompositeAuthenticationToken(
userPrincipal, List.of(actor1));
// @formatter:off
OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createAccessToken(SUBJECT_TOKEN), withClaims(Map.of("may_act", actor2.getClaims())))
@@ -596,19 +634,19 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
.token(createAccessToken(ACTOR_TOKEN), withClaims(actor2.getClaims()))
.build();
// @formatter:on
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(
subjectAuthorization, actorAuthorization);
when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class)))
.thenReturn(subjectAuthorization, actorAuthorization);
OAuth2AccessToken accessToken = createAccessToken("token-value");
when(this.tokenGenerator.generate(any(OAuth2TokenContext.class))).thenReturn(accessToken);
OAuth2AccessTokenAuthenticationToken authenticationResult =
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
OAuth2AccessTokenAuthenticationToken authenticationResult = (OAuth2AccessTokenAuthenticationToken) this.authenticationProvider
.authenticate(authentication);
assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient);
assertThat(authenticationResult.getPrincipal()).isEqualTo(authentication.getPrincipal());
assertThat(authenticationResult.getAccessToken()).isEqualTo(accessToken);
assertThat(authenticationResult.getRefreshToken()).isNull();
assertThat(authenticationResult.getAdditionalParameters()).hasSize(1);
assertThat(authenticationResult.getAdditionalParameters().get(OAuth2ParameterNames.ISSUED_TOKEN_TYPE))
.isEqualTo(JWT_TOKEN_TYPE_VALUE);
.isEqualTo(JWT_TOKEN_TYPE_VALUE);
ArgumentCaptor<OAuth2Authorization> authorizationCaptor = ArgumentCaptor.forClass(OAuth2Authorization.class);
ArgumentCaptor<OAuth2TokenContext> tokenContextCaptor = ArgumentCaptor.forClass(OAuth2TokenContext.class);
@@ -638,8 +676,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
assertThat(authorization.getAccessToken().getToken()).isEqualTo(accessToken);
assertThat(authorization.getRefreshToken()).isNull();
OAuth2TokenExchangeCompositeAuthenticationToken authorizationPrincipal =
authorization.getAttribute(Principal.class.getName());
OAuth2TokenExchangeCompositeAuthenticationToken authorizationPrincipal = authorization
.getAttribute(Principal.class.getName());
assertThat(authorizationPrincipal).isNotNull();
assertThat(authorizationPrincipal.getSubject()).isSameAs(subjectPrincipal.getSubject());
assertThat(authorizationPrincipal.getActors()).containsExactly(actor2, actor1);
@@ -664,7 +702,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests {
clientPrincipal, ACTOR_TOKEN, ACCESS_TOKEN_TYPE_VALUE, RESOURCES, AUDIENCES, requestedScopes, null);
}
private static OAuth2TokenExchangeAuthenticationToken createImpersonationRequest(RegisteredClient registeredClient) {
private static OAuth2TokenExchangeAuthenticationToken createImpersonationRequest(
RegisteredClient registeredClient) {
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient,
ClientAuthenticationMethod.CLIENT_SECRET_BASIC, null);
return new OAuth2TokenExchangeAuthenticationToken(JWT_TOKEN_TYPE_VALUE, SUBJECT_TOKEN, ACCESS_TOKEN_TYPE_VALUE,

View File

@@ -35,17 +35,27 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
* @author Steve Riesenberg
*/
public class OAuth2TokenExchangeAuthenticationTokenTests {
private static final Set<String> RESOURCES = Set.of("https://mydomain.com/resource1", "https://mydomain.com/resource2");
private static final Set<String> RESOURCES = Set.of("https://mydomain.com/resource1",
"https://mydomain.com/resource2");
private static final Set<String> AUDIENCES = Set.of("audience1", "audience2");
private static final String SUBJECT_TOKEN = "EfYu_0jEL";
private static final String ACTOR_TOKEN = "JlNE_xR1f";
private static final String ACCESS_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:access_token";
private static final String JWT_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:jwt";
private RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret());
private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(this.registeredClient,
ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret());
private Set<String> scopes = Collections.singleton("scope1");
private Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
@Test

View File

@@ -57,8 +57,8 @@ public class OAuth2TokenExchangeCompositeAuthenticationTokenTests {
OAuth2TokenExchangeActor actor1 = new OAuth2TokenExchangeActor(Map.of("claim1", "value1"));
OAuth2TokenExchangeActor actor2 = new OAuth2TokenExchangeActor(Map.of("claim2", "value2"));
List<OAuth2TokenExchangeActor> actors = List.of(actor1, actor2);
OAuth2TokenExchangeCompositeAuthenticationToken authentication =
new OAuth2TokenExchangeCompositeAuthenticationToken(subject, actors);
OAuth2TokenExchangeCompositeAuthenticationToken authentication = new OAuth2TokenExchangeCompositeAuthenticationToken(
subject, actors);
assertThat(authentication.getSubject()).isEqualTo(subject);
assertThat(authentication.getActors()).isEqualTo(actors);
}

View File

@@ -65,18 +65,27 @@ import static org.mockito.Mockito.when;
* @author Joe Grandja
*/
public class X509ClientCertificateAuthenticationProviderTests {
// See RFC 7636: Appendix B. Example for the S256 code_challenge_method
// See RFC 7636: Appendix B. Example for the S256 code_challenge_method
// https://tools.ietf.org/html/rfc7636#appendix-B
private static final String S256_CODE_VERIFIER = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk";
private static final String S256_CODE_CHALLENGE = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM";
private static final String AUTHORIZATION_CODE = "code";
private static final OAuth2TokenType AUTHORIZATION_CODE_TOKEN_TYPE = new OAuth2TokenType(OAuth2ParameterNames.CODE);
private JWKSet selfSignedCertificateJwkSet;
private MockWebServer server;
private String clientJwkSetUrl;
private RegisteredClientRepository registeredClientRepository;
private OAuth2AuthorizationService authorizationService;
private X509ClientCertificateAuthenticationProvider authenticationProvider;
@BeforeEach
@@ -102,8 +111,8 @@ public class X509ClientCertificateAuthenticationProviderTests {
this.registeredClientRepository = mock(RegisteredClientRepository.class);
this.authorizationService = mock(OAuth2AuthorizationService.class);
this.authenticationProvider = new X509ClientCertificateAuthenticationProvider(
this.registeredClientRepository, this.authorizationService);
this.authenticationProvider = new X509ClientCertificateAuthenticationProvider(this.registeredClientRepository,
this.authorizationService);
}
@AfterEach
@@ -114,22 +123,22 @@ public class X509ClientCertificateAuthenticationProviderTests {
@Test
public void constructorWhenRegisteredClientRepositoryNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new X509ClientCertificateAuthenticationProvider(null, this.authorizationService))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("registeredClientRepository cannot be null");
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("registeredClientRepository cannot be null");
}
@Test
public void constructorWhenAuthorizationServiceNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new X509ClientCertificateAuthenticationProvider(this.registeredClientRepository, null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authorizationService cannot be null");
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authorizationService cannot be null");
}
@Test
public void setCertificateVerifierWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> this.authenticationProvider.setCertificateVerifier(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("certificateVerifier cannot be null");
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("certificateVerifier cannot be null");
}
@Test
@@ -145,36 +154,36 @@ public class X509ClientCertificateAuthenticationProviderTests {
.build();
// @formatter:on
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
.thenReturn(registeredClient);
OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId() + "-invalid", ClientAuthenticationMethod.TLS_CLIENT_AUTH,
TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains(OAuth2ParameterNames.CLIENT_ID);
});
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains(OAuth2ParameterNames.CLIENT_ID);
});
}
@Test
public void authenticateWhenUnsupportedClientAuthenticationMethodThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
.thenReturn(registeredClient);
OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), ClientAuthenticationMethod.TLS_CLIENT_AUTH,
TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("authentication_method");
});
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("authentication_method");
});
}
@Test
@@ -185,17 +194,17 @@ public class X509ClientCertificateAuthenticationProviderTests {
.build();
// @formatter:on
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
.thenReturn(registeredClient);
OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), ClientAuthenticationMethod.TLS_CLIENT_AUTH, null, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("credentials");
});
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("credentials");
});
}
@Test
@@ -211,18 +220,18 @@ public class X509ClientCertificateAuthenticationProviderTests {
.build();
// @formatter:on
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
.thenReturn(registeredClient);
OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), ClientAuthenticationMethod.TLS_CLIENT_AUTH,
TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("x509_certificate_subject_dn");
});
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("x509_certificate_subject_dn");
});
}
@Test
@@ -238,20 +247,21 @@ public class X509ClientCertificateAuthenticationProviderTests {
.build();
// @formatter:on
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
.thenReturn(registeredClient);
OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), ClientAuthenticationMethod.TLS_CLIENT_AUTH,
TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, null);
OAuth2ClientAuthenticationToken authenticationResult =
(OAuth2ClientAuthenticationToken) this.authenticationProvider.authenticate(authentication);
OAuth2ClientAuthenticationToken authenticationResult = (OAuth2ClientAuthenticationToken) this.authenticationProvider
.authenticate(authentication);
assertThat(authenticationResult.isAuthenticated()).isTrue();
assertThat(authenticationResult.getPrincipal().toString()).isEqualTo(registeredClient.getClientId());
assertThat(authenticationResult.getCredentials()).isEqualTo(TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE);
assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient);
assertThat(authenticationResult.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.TLS_CLIENT_AUTH);
assertThat(authenticationResult.getClientAuthenticationMethod())
.isEqualTo(ClientAuthenticationMethod.TLS_CLIENT_AUTH);
}
@Test
@@ -267,18 +277,19 @@ public class X509ClientCertificateAuthenticationProviderTests {
.build();
// @formatter:on
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
.thenReturn(registeredClient);
// PKI Certificate will have different issuer
OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH,
TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, null); // PKI Certificate will have different issuer
TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("x509_certificate_issuer");
});
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("x509_certificate_issuer");
});
}
@Test
@@ -289,18 +300,18 @@ public class X509ClientCertificateAuthenticationProviderTests {
.build();
// @formatter:on
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
.thenReturn(registeredClient);
OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH,
TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("client_jwk_set_url");
});
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("client_jwk_set_url");
});
}
@Test
@@ -316,18 +327,18 @@ public class X509ClientCertificateAuthenticationProviderTests {
.build();
// @formatter:on
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
.thenReturn(registeredClient);
OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH,
TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("jwk_set_uri");
});
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("jwk_set_uri");
});
}
@Test
@@ -352,7 +363,8 @@ public class X509ClientCertificateAuthenticationProviderTests {
}
@Test
public void authenticateWhenSelfSignedX509CertificateJwkSetResponseNoMatchingKeysThenThrowOAuth2AuthenticationException() throws Exception {
public void authenticateWhenSelfSignedX509CertificateJwkSetResponseNoMatchingKeysThenThrowOAuth2AuthenticationException()
throws Exception {
// @formatter:off
X509Certificate pkiCertificate = TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE[0];
RSAKey pkiRSAKey = new RSAKey.Builder((RSAPublicKey) pkiCertificate.getPublicKey())
@@ -396,18 +408,18 @@ public class X509ClientCertificateAuthenticationProviderTests {
.build();
// @formatter:on
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
.thenReturn(registeredClient);
OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH,
TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains(expectedErrorDescription);
});
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains(expectedErrorDescription);
});
}
@Test
@@ -423,20 +435,22 @@ public class X509ClientCertificateAuthenticationProviderTests {
.build();
// @formatter:on
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
.thenReturn(registeredClient);
OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH,
TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE, null);
OAuth2ClientAuthenticationToken authenticationResult =
(OAuth2ClientAuthenticationToken) this.authenticationProvider.authenticate(authentication);
OAuth2ClientAuthenticationToken authenticationResult = (OAuth2ClientAuthenticationToken) this.authenticationProvider
.authenticate(authentication);
assertThat(authenticationResult.isAuthenticated()).isTrue();
assertThat(authenticationResult.getPrincipal().toString()).isEqualTo(registeredClient.getClientId());
assertThat(authenticationResult.getCredentials()).isEqualTo(TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE);
assertThat(authenticationResult.getCredentials())
.isEqualTo(TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE);
assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient);
assertThat(authenticationResult.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH);
assertThat(authenticationResult.getClientAuthenticationMethod())
.isEqualTo(ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH);
}
@Test
@@ -452,13 +466,13 @@ public class X509ClientCertificateAuthenticationProviderTests {
.build();
// @formatter:on
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
.thenReturn(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations
.authorization(registeredClient, createPkceAuthorizationParametersS256())
.build();
.authorization(registeredClient, createPkceAuthorizationParametersS256())
.build();
when(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE)))
.thenReturn(authorization);
.thenReturn(authorization);
Map<String, Object> parameters = createPkceTokenParameters(S256_CODE_VERIFIER);
@@ -466,15 +480,16 @@ public class X509ClientCertificateAuthenticationProviderTests {
registeredClient.getClientId(), ClientAuthenticationMethod.TLS_CLIENT_AUTH,
TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, parameters);
OAuth2ClientAuthenticationToken authenticationResult =
(OAuth2ClientAuthenticationToken) this.authenticationProvider.authenticate(authentication);
OAuth2ClientAuthenticationToken authenticationResult = (OAuth2ClientAuthenticationToken) this.authenticationProvider
.authenticate(authentication);
verify(this.authorizationService).findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE));
assertThat(authenticationResult.isAuthenticated()).isTrue();
assertThat(authenticationResult.getPrincipal().toString()).isEqualTo(registeredClient.getClientId());
assertThat(authenticationResult.getCredentials()).isEqualTo(TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE);
assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient);
assertThat(authenticationResult.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.TLS_CLIENT_AUTH);
assertThat(authenticationResult.getClientAuthenticationMethod())
.isEqualTo(ClientAuthenticationMethod.TLS_CLIENT_AUTH);
}
private static Map<String, Object> createPkceAuthorizationParametersS256() {

View File

@@ -37,10 +37,15 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Joe Grandja
*/
class AuthorizationServerContextFilterTests {
private static final String SCHEME = "https";
private static final String HOST = "example.com";
private static final int PORT = 8443;
private static final String DEFAULT_ISSUER = SCHEME + "://" + HOST + ":" + PORT;
private AuthorizationServerContextFilter filter;
@Test
@@ -60,17 +65,17 @@ class AuthorizationServerContextFilterTests {
@Test
public void doFilterWhenCustomEndpointsThenIssuerResolved() throws Exception {
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder()
.authorizationEndpoint("/oauth2/v1/authorize")
.deviceAuthorizationEndpoint("/oauth2/v1/device_authorization")
.deviceVerificationEndpoint("/oauth2/v1/device_verification")
.tokenEndpoint("/oauth2/v1/token")
.jwkSetEndpoint("/oauth2/v1/jwks")
.tokenRevocationEndpoint("/oauth2/v1/revoke")
.tokenIntrospectionEndpoint("/oauth2/v1/introspect")
.oidcClientRegistrationEndpoint("/connect/v1/register")
.oidcUserInfoEndpoint("/v1/userinfo")
.oidcLogoutEndpoint("/connect/v1/logout")
.build();
.authorizationEndpoint("/oauth2/v1/authorize")
.deviceAuthorizationEndpoint("/oauth2/v1/device_authorization")
.deviceVerificationEndpoint("/oauth2/v1/device_verification")
.tokenEndpoint("/oauth2/v1/token")
.jwkSetEndpoint("/oauth2/v1/jwks")
.tokenRevocationEndpoint("/oauth2/v1/revoke")
.tokenIntrospectionEndpoint("/oauth2/v1/introspect")
.oidcClientRegistrationEndpoint("/connect/v1/register")
.oidcUserInfoEndpoint("/v1/userinfo")
.oidcLogoutEndpoint("/connect/v1/logout")
.build();
this.filter = new AuthorizationServerContextFilter(authorizationServerSettings);
String issuerPath = "/issuer2";
@@ -101,8 +106,8 @@ class AuthorizationServerContextFilterTests {
MockHttpServletResponse response = new MockHttpServletResponse();
AtomicReference<String> resolvedIssuer = new AtomicReference<>();
FilterChain filterChain = (req, resp) ->
resolvedIssuer.set(AuthorizationServerContextHolder.getContext().getIssuer());
FilterChain filterChain = (req, resp) -> resolvedIssuer
.set(AuthorizationServerContextHolder.getContext().getIssuer());
this.filter.doFilter(request, response, filterChain);

View File

@@ -55,9 +55,13 @@ import static org.mockito.Mockito.when;
* @author Joe Grandja
*/
class DefaultOAuth2TokenCustomizersTests {
private static final String ISSUER_1 = "issuer-1";
private static final String ISSUER_2 = "issuer-2";
private JwsHeader.Builder jwsHeaderBuilder;
private JwtClaimsSet.Builder jwtClaimsBuilder;
@BeforeEach
@@ -131,10 +135,10 @@ class DefaultOAuth2TokenCustomizersTests {
when(tokenExchangeAuthentication.getAudiences()).thenReturn(Collections.emptySet());
Authentication subject = new TestingAuthenticationToken("subject", null);
OAuth2TokenExchangeActor actor1 = new OAuth2TokenExchangeActor(Map.of(JwtClaimNames.ISS, ISSUER_1,
JwtClaimNames.SUB, "actor1"));
OAuth2TokenExchangeActor actor2 = new OAuth2TokenExchangeActor(Map.of(JwtClaimNames.ISS, ISSUER_2,
JwtClaimNames.SUB, "actor2"));
OAuth2TokenExchangeActor actor1 = new OAuth2TokenExchangeActor(
Map.of(JwtClaimNames.ISS, ISSUER_1, JwtClaimNames.SUB, "actor1"));
OAuth2TokenExchangeActor actor2 = new OAuth2TokenExchangeActor(
Map.of(JwtClaimNames.ISS, ISSUER_2, JwtClaimNames.SUB, "actor2"));
OAuth2TokenExchangeCompositeAuthenticationToken principal = new OAuth2TokenExchangeCompositeAuthenticationToken(
subject, List.of(actor1, actor2));
@@ -177,11 +181,10 @@ class DefaultOAuth2TokenCustomizersTests {
)
.build();
// @formatter:on
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
registeredClient, ClientAuthenticationMethod.TLS_CLIENT_AUTH,
TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE);
OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication =
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient,
ClientAuthenticationMethod.TLS_CLIENT_AUTH, TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE);
OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication = new OAuth2ClientCredentialsAuthenticationToken(
clientPrincipal, null, null);
// @formatter:off
JwtEncodingContext tokenContext = JwtEncodingContext.with(this.jwsHeaderBuilder, this.jwtClaimsBuilder)
.tokenType(OAuth2TokenType.ACCESS_TOKEN)
@@ -215,11 +218,11 @@ class DefaultOAuth2TokenCustomizersTests {
)
.build();
// @formatter:on
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
registeredClient, ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH,
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient,
ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH,
TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE);
OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication =
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication = new OAuth2ClientCredentialsAuthenticationToken(
clientPrincipal, null, null);
// @formatter:off
JwtEncodingContext tokenContext = JwtEncodingContext.with(this.jwsHeaderBuilder, this.jwtClaimsBuilder)
.tokenType(OAuth2TokenType.ACCESS_TOKEN)

View File

@@ -82,13 +82,13 @@ public class JwkSetTests {
public static void init() {
JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
db = new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.HSQL)
.setScriptEncoding("UTF-8")
.addScript("org/springframework/security/oauth2/server/authorization/oauth2-authorization-schema.sql")
.addScript("org/springframework/security/oauth2/server/authorization/client/oauth2-registered-client-schema.sql")
.build();
db = new EmbeddedDatabaseBuilder().generateUniqueName(true)
.setType(EmbeddedDatabaseType.HSQL)
.setScriptEncoding("UTF-8")
.addScript("org/springframework/security/oauth2/server/authorization/oauth2-authorization-schema.sql")
.addScript(
"org/springframework/security/oauth2/server/authorization/client/oauth2-registered-client-schema.sql")
.build();
}
@AfterEach
@@ -188,7 +188,10 @@ public class JwkSetTests {
@Bean
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().jwkSetEndpoint("/test/jwks").multipleIssuersAllowed(true).build();
return AuthorizationServerSettings.builder()
.jwkSetEndpoint("/test/jwks")
.multipleIssuersAllowed(true)
.build();
}
}

View File

@@ -918,30 +918,33 @@ public class OAuth2AuthorizationCodeGrantTests {
String issuer = "https://example.com:8443/issuer1";
MvcResult mvcResult = this.mvc.perform(get(issuer.concat(DEFAULT_AUTHORIZATION_ENDPOINT_URI))
.queryParams(getAuthorizationRequestParameters(registeredClient))
.queryParam(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE)
.queryParam(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256")
.with(user("user")))
.andExpect(status().is3xxRedirection())
.andReturn();
MvcResult mvcResult = this.mvc
.perform(get(issuer.concat(DEFAULT_AUTHORIZATION_ENDPOINT_URI))
.queryParams(getAuthorizationRequestParameters(registeredClient))
.queryParam(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE)
.queryParam(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256")
.with(user("user")))
.andExpect(status().is3xxRedirection())
.andReturn();
String authorizationCode = extractParameterFromRedirectUri(mvcResult.getResponse().getRedirectedUrl(), "code");
OAuth2Authorization authorizationCodeAuthorization = this.authorizationService.findByToken(authorizationCode, AUTHORIZATION_CODE_TOKEN_TYPE);
OAuth2Authorization authorizationCodeAuthorization = this.authorizationService.findByToken(authorizationCode,
AUTHORIZATION_CODE_TOKEN_TYPE);
this.mvc.perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI))
this.mvc
.perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI))
.params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization))
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId())
.param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER))
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store")))
.andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache")))
.andExpect(status().isOk())
.andExpect(jsonPath("$.access_token").isNotEmpty())
.andExpect(jsonPath("$.token_type").isNotEmpty())
.andExpect(jsonPath("$.expires_in").isNotEmpty())
.andExpect(jsonPath("$.refresh_token").doesNotExist())
.andExpect(jsonPath("$.scope").isNotEmpty())
.andReturn();
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store")))
.andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache")))
.andExpect(status().isOk())
.andExpect(jsonPath("$.access_token").isNotEmpty())
.andExpect(jsonPath("$.token_type").isNotEmpty())
.andExpect(jsonPath("$.expires_in").isNotEmpty())
.andExpect(jsonPath("$.refresh_token").doesNotExist())
.andExpect(jsonPath("$.scope").isNotEmpty())
.andReturn();
ArgumentCaptor<OAuth2TokenContext> tokenContextCaptor = ArgumentCaptor.forClass(OAuth2TokenContext.class);
verify(tokenGenerator).generate(tokenContextCaptor.capture());
@@ -1333,7 +1336,8 @@ public class OAuth2AuthorizationCodeGrantTests {
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
static class AuthorizationServerConfigurationWithMultipleIssuersAllowed extends AuthorizationServerConfigurationWithTokenGenerator {
static class AuthorizationServerConfigurationWithMultipleIssuersAllowed
extends AuthorizationServerConfigurationWithTokenGenerator {
@Bean
AuthorizationServerSettings authorizationServerSettings() {

View File

@@ -110,13 +110,14 @@ public class OAuth2AuthorizationServerMetadataTests {
this.spring.register(AuthorizationServerConfiguration.class).autowire();
this.mvc.perform(get(ISSUER.concat(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI)))
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath("issuer").value(ISSUER))
.andReturn();
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath("issuer").value(ISSUER))
.andReturn();
}
@Test
public void requestWhenAuthorizationServerMetadataRequestIncludesIssuerPathThenMetadataResponseHasIssuerPath() throws Exception {
public void requestWhenAuthorizationServerMetadataRequestIncludesIssuerPathThenMetadataResponseHasIssuerPath()
throws Exception {
this.spring.register(AuthorizationServerConfigurationWithMultipleIssuersAllowed.class).autowire();
String host = "https://example.com:8443";
@@ -124,23 +125,23 @@ public class OAuth2AuthorizationServerMetadataTests {
String issuerPath = "/issuer1";
String issuer = host.concat(issuerPath);
this.mvc.perform(get(host.concat(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI).concat(issuerPath)))
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath("issuer").value(issuer))
.andReturn();
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath("issuer").value(issuer))
.andReturn();
issuerPath = "/path1/issuer2";
issuer = host.concat(issuerPath);
this.mvc.perform(get(host.concat(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI).concat(issuerPath)))
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath("issuer").value(issuer))
.andReturn();
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath("issuer").value(issuer))
.andReturn();
issuerPath = "/path1/path2/issuer3";
issuer = host.concat(issuerPath);
this.mvc.perform(get(host.concat(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI).concat(issuerPath)))
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath("issuer").value(issuer))
.andReturn();
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath("issuer").value(issuer))
.andReturn();
}
// gh-616
@@ -150,9 +151,9 @@ public class OAuth2AuthorizationServerMetadataTests {
this.spring.register(AuthorizationServerConfigurationWithMetadataCustomizer.class).autowire();
this.mvc.perform(get(ISSUER.concat(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI)))
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED,
hasItems("scope1", "scope2")));
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED,
hasItems("scope1", "scope2")));
}
@EnableWebSecurity

View File

@@ -298,14 +298,14 @@ public class OAuth2ClientCredentialsGrantTests {
// @formatter:on
this.registeredClientRepository.save(registeredClient);
this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
.with(x509(TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE))
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId())
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.param(OAuth2ParameterNames.SCOPE, "scope1 scope2"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.access_token").isNotEmpty())
.andExpect(jsonPath("$.scope").value("scope1 scope2"));
this.mvc
.perform(post(DEFAULT_TOKEN_ENDPOINT_URI).with(x509(TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE))
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId())
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.param(OAuth2ParameterNames.SCOPE, "scope1 scope2"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.access_token").isNotEmpty())
.andExpect(jsonPath("$.scope").value("scope1 scope2"));
verify(jwtCustomizer).customize(any());
}
@@ -344,13 +344,12 @@ public class OAuth2ClientCredentialsGrantTests {
.forClass(List.class);
verify(authenticationConvertersConsumer).accept(authenticationConvertersCaptor.capture());
List<AuthenticationConverter> authenticationConverters = authenticationConvertersCaptor.getValue();
assertThat(authenticationConverters).allMatch((converter) ->
converter == authenticationConverter ||
converter instanceof OAuth2AuthorizationCodeAuthenticationConverter ||
converter instanceof OAuth2RefreshTokenAuthenticationConverter ||
converter instanceof OAuth2ClientCredentialsAuthenticationConverter ||
converter instanceof OAuth2DeviceCodeAuthenticationConverter ||
converter instanceof OAuth2TokenExchangeAuthenticationConverter);
assertThat(authenticationConverters).allMatch((converter) -> converter == authenticationConverter
|| converter instanceof OAuth2AuthorizationCodeAuthenticationConverter
|| converter instanceof OAuth2RefreshTokenAuthenticationConverter
|| converter instanceof OAuth2ClientCredentialsAuthenticationConverter
|| converter instanceof OAuth2DeviceCodeAuthenticationConverter
|| converter instanceof OAuth2TokenExchangeAuthenticationConverter);
verify(authenticationProvider).authenticate(eq(clientCredentialsAuthentication));
@@ -359,13 +358,12 @@ public class OAuth2ClientCredentialsGrantTests {
.forClass(List.class);
verify(authenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture());
List<AuthenticationProvider> authenticationProviders = authenticationProvidersCaptor.getValue();
assertThat(authenticationProviders).allMatch((provider) ->
provider == authenticationProvider ||
provider instanceof OAuth2AuthorizationCodeAuthenticationProvider ||
provider instanceof OAuth2RefreshTokenAuthenticationProvider ||
provider instanceof OAuth2ClientCredentialsAuthenticationProvider ||
provider instanceof OAuth2DeviceCodeAuthenticationProvider ||
provider instanceof OAuth2TokenExchangeAuthenticationProvider);
assertThat(authenticationProviders).allMatch((provider) -> provider == authenticationProvider
|| provider instanceof OAuth2AuthorizationCodeAuthenticationProvider
|| provider instanceof OAuth2RefreshTokenAuthenticationProvider
|| provider instanceof OAuth2ClientCredentialsAuthenticationProvider
|| provider instanceof OAuth2DeviceCodeAuthenticationProvider
|| provider instanceof OAuth2TokenExchangeAuthenticationProvider);
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), eq(accessTokenAuthentication));
}
@@ -395,13 +393,12 @@ public class OAuth2ClientCredentialsGrantTests {
.forClass(List.class);
verify(authenticationConvertersConsumer).accept(authenticationConvertersCaptor.capture());
List<AuthenticationConverter> authenticationConverters = authenticationConvertersCaptor.getValue();
assertThat(authenticationConverters).allMatch((converter) ->
converter == authenticationConverter ||
converter instanceof JwtClientAssertionAuthenticationConverter ||
converter instanceof X509ClientCertificateAuthenticationConverter ||
converter instanceof ClientSecretBasicAuthenticationConverter ||
converter instanceof ClientSecretPostAuthenticationConverter ||
converter instanceof PublicClientAuthenticationConverter);
assertThat(authenticationConverters).allMatch((converter) -> converter == authenticationConverter
|| converter instanceof JwtClientAssertionAuthenticationConverter
|| converter instanceof X509ClientCertificateAuthenticationConverter
|| converter instanceof ClientSecretBasicAuthenticationConverter
|| converter instanceof ClientSecretPostAuthenticationConverter
|| converter instanceof PublicClientAuthenticationConverter);
verify(authenticationProvider).authenticate(eq(clientPrincipal));
@@ -410,12 +407,11 @@ public class OAuth2ClientCredentialsGrantTests {
.forClass(List.class);
verify(authenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture());
List<AuthenticationProvider> authenticationProviders = authenticationProvidersCaptor.getValue();
assertThat(authenticationProviders).allMatch((provider) ->
provider == authenticationProvider ||
provider instanceof JwtClientAssertionAuthenticationProvider ||
provider instanceof X509ClientCertificateAuthenticationProvider ||
provider instanceof ClientSecretAuthenticationProvider ||
provider instanceof PublicClientAuthenticationProvider);
assertThat(authenticationProviders).allMatch((provider) -> provider == authenticationProvider
|| provider instanceof JwtClientAssertionAuthenticationProvider
|| provider instanceof X509ClientCertificateAuthenticationProvider
|| provider instanceof ClientSecretAuthenticationProvider
|| provider instanceof PublicClientAuthenticationProvider);
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), eq(clientPrincipal));
}
@@ -429,14 +425,15 @@ public class OAuth2ClientCredentialsGrantTests {
String issuer = "https://example.com:8443/issuer1";
this.mvc.perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI))
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.param(OAuth2ParameterNames.SCOPE, "scope1 scope2")
.header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth(
registeredClient.getClientId(), registeredClient.getClientSecret())))
.andExpect(status().isOk())
.andExpect(jsonPath("$.access_token").isNotEmpty())
.andExpect(jsonPath("$.scope").value("scope1 scope2"));
this.mvc
.perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI))
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.param(OAuth2ParameterNames.SCOPE, "scope1 scope2")
.header(HttpHeaders.AUTHORIZATION,
"Basic " + encodeBasicAuth(registeredClient.getClientId(), registeredClient.getClientSecret())))
.andExpect(status().isOk())
.andExpect(jsonPath("$.access_token").isNotEmpty())
.andExpect(jsonPath("$.scope").value("scope1 scope2"));
ArgumentCaptor<JwtEncodingContext> jwtEncodingContextCaptor = ArgumentCaptor.forClass(JwtEncodingContext.class);
verify(jwtCustomizer).customize(jwtEncodingContextCaptor.capture());

View File

@@ -247,9 +247,9 @@ public class OAuth2DeviceCodeGrantTests {
String userCode = deviceAuthorizationResponse.getUserCode().getTokenValue();
assertThat(userCode).matches("[A-Z]{4}-[A-Z]{4}");
assertThat(deviceAuthorizationResponse.getVerificationUri())
.isEqualTo("https://example.com:8443/oauth2/device_verification");
.isEqualTo("https://example.com:8443/oauth2/device_verification");
assertThat(deviceAuthorizationResponse.getVerificationUriComplete())
.isEqualTo("https://example.com:8443/oauth2/device_verification?user_code=" + userCode);
.isEqualTo("https://example.com:8443/oauth2/device_verification?user_code=" + userCode);
String deviceCode = deviceAuthorizationResponse.getDeviceCode().getTokenValue();
OAuth2Authorization authorization = this.authorizationService.findByToken(deviceCode, DEVICE_CODE_TOKEN_TYPE);

View File

@@ -94,18 +94,24 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*/
@ExtendWith(SpringTestContextExtension.class)
public class OAuth2TokenExchangeGrantTests {
private static final String DEFAULT_TOKEN_ENDPOINT_URI = "/oauth2/token";
private static final String RESOURCE = "https://mydomain.com/resource";
private static final String AUDIENCE = "audience";
private static final String SUBJECT_TOKEN = "EfYu_0jEL";
private static final String ACTOR_TOKEN = "JlNE_xR1f";
private static final String ACCESS_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:access_token";
private static final String JWT_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:jwt";
public final SpringTestContext spring = new SpringTestContext();
private final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenResponseHttpMessageConverter =
new OAuth2AccessTokenResponseHttpMessageConverter();
private final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenResponseHttpMessageConverter = new OAuth2AccessTokenResponseHttpMessageConverter();
@Autowired
private MockMvc mvc;
@@ -152,7 +158,8 @@ public class OAuth2TokenExchangeGrantTests {
this.spring.register(AuthorizationServerConfiguration.class).autowire();
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
this.registeredClientRepository.save(registeredClient);
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
@@ -168,23 +175,27 @@ public class OAuth2TokenExchangeGrantTests {
}
@Test
public void requestWhenAccessTokenRequestValidAndNoActorTokenThenReturnAccessTokenResponseForImpersonation() throws Exception {
public void requestWhenAccessTokenRequestValidAndNoActorTokenThenReturnAccessTokenResponseForImpersonation()
throws Exception {
this.spring.register(AuthorizationServerConfiguration.class).autowire();
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
this.registeredClientRepository.save(registeredClient);
UsernamePasswordAuthenticationToken userPrincipal = createUserPrincipal("user");
OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient)
.attribute(Principal.class.getName(), userPrincipal).build();
.attribute(Principal.class.getName(), userPrincipal)
.build();
this.authorizationService.save(subjectAuthorization);
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.set(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.TOKEN_EXCHANGE.getValue());
parameters.set(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId());
parameters.set(OAuth2ParameterNames.REQUESTED_TOKEN_TYPE, JWT_TOKEN_TYPE_VALUE);
parameters.set(OAuth2ParameterNames.SUBJECT_TOKEN, subjectAuthorization.getAccessToken().getToken().getTokenValue());
parameters.set(OAuth2ParameterNames.SUBJECT_TOKEN,
subjectAuthorization.getAccessToken().getToken().getTokenValue());
parameters.set(OAuth2ParameterNames.SUBJECT_TOKEN_TYPE, JWT_TOKEN_TYPE_VALUE);
parameters.set(OAuth2ParameterNames.RESOURCE, RESOURCE);
parameters.set(OAuth2ParameterNames.AUDIENCE, AUDIENCE);
@@ -208,8 +219,8 @@ public class OAuth2TokenExchangeGrantTests {
MockHttpServletResponse servletResponse = mvcResult.getResponse();
MockClientHttpResponse httpResponse = new MockClientHttpResponse(servletResponse.getContentAsByteArray(),
HttpStatus.OK);
OAuth2AccessTokenResponse accessTokenResponse =
this.accessTokenResponseHttpMessageConverter.read(OAuth2AccessTokenResponse.class, httpResponse);
OAuth2AccessTokenResponse accessTokenResponse = this.accessTokenResponseHttpMessageConverter
.read(OAuth2AccessTokenResponse.class, httpResponse);
String accessToken = accessTokenResponse.getAccessToken().getTokenValue();
OAuth2Authorization authorization = this.authorizationService.findByToken(accessToken,
@@ -217,19 +228,22 @@ public class OAuth2TokenExchangeGrantTests {
assertThat(authorization).isNotNull();
assertThat(authorization.getAccessToken()).isNotNull();
assertThat(authorization.getAccessToken().getClaims()).isNotNull();
// We do not populate claims (e.g. `aud`) based on the resource or audience parameters
// We do not populate claims (e.g. `aud`) based on the resource or audience
// parameters
assertThat(authorization.getAccessToken().getClaims().get(OAuth2TokenClaimNames.AUD))
.isEqualTo(List.of(registeredClient.getClientId()));
.isEqualTo(List.of(registeredClient.getClientId()));
assertThat(authorization.getRefreshToken()).isNull();
assertThat(authorization.<Authentication>getAttribute(Principal.class.getName())).isEqualTo(userPrincipal);
}
@Test
public void requestWhenAccessTokenRequestValidAndActorTokenThenReturnAccessTokenResponseForDelegation() throws Exception {
public void requestWhenAccessTokenRequestValidAndActorTokenThenReturnAccessTokenResponseForDelegation()
throws Exception {
this.spring.register(AuthorizationServerConfiguration.class).autowire();
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
this.registeredClientRepository.save(registeredClient);
UsernamePasswordAuthenticationToken userPrincipal = createUserPrincipal("user");
@@ -284,8 +298,8 @@ public class OAuth2TokenExchangeGrantTests {
MockHttpServletResponse servletResponse = mvcResult.getResponse();
MockClientHttpResponse httpResponse = new MockClientHttpResponse(servletResponse.getContentAsByteArray(),
HttpStatus.OK);
OAuth2AccessTokenResponse accessTokenResponse =
this.accessTokenResponseHttpMessageConverter.read(OAuth2AccessTokenResponse.class, httpResponse);
OAuth2AccessTokenResponse accessTokenResponse = this.accessTokenResponseHttpMessageConverter
.read(OAuth2AccessTokenResponse.class, httpResponse);
String accessToken = accessTokenResponse.getAccessToken().getTokenValue();
OAuth2Authorization authorization = this.authorizationService.findByToken(accessToken,
@@ -296,7 +310,7 @@ public class OAuth2TokenExchangeGrantTests {
assertThat(authorization.getAccessToken().getClaims().get("act")).isNotNull();
assertThat(authorization.getRefreshToken()).isNull();
assertThat(authorization.<Authentication>getAttribute(Principal.class.getName()))
.isInstanceOf(OAuth2TokenExchangeCompositeAuthenticationToken.class);
.isInstanceOf(OAuth2TokenExchangeCompositeAuthenticationToken.class);
}
private static OAuth2AccessToken createAccessToken(String tokenValue) {
@@ -363,6 +377,7 @@ public class OAuth2TokenExchangeGrantTests {
PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
}

View File

@@ -437,11 +437,10 @@ public class OAuth2TokenIntrospectionTests {
OAuth2AccessToken accessToken = authorization.getAccessToken().getToken();
Authentication clientPrincipal = new OAuth2ClientAuthenticationToken(
introspectRegisteredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, introspectRegisteredClient.getClientSecret());
OAuth2TokenIntrospectionAuthenticationToken tokenIntrospectionAuthentication =
new OAuth2TokenIntrospectionAuthenticationToken(
accessToken.getTokenValue(), clientPrincipal, null, null);
Authentication clientPrincipal = new OAuth2ClientAuthenticationToken(introspectRegisteredClient,
ClientAuthenticationMethod.CLIENT_SECRET_BASIC, introspectRegisteredClient.getClientSecret());
OAuth2TokenIntrospectionAuthenticationToken tokenIntrospectionAuthentication = new OAuth2TokenIntrospectionAuthenticationToken(
accessToken.getTokenValue(), clientPrincipal, null, null);
when(authenticationConverter.convert(any())).thenReturn(tokenIntrospectionAuthentication);
when(authenticationProvider.supports(eq(OAuth2TokenIntrospectionAuthenticationToken.class))).thenReturn(true);
@@ -600,10 +599,12 @@ public class OAuth2TokenIntrospectionTests {
}
// @formatter:on
@Override
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).tokenIntrospectionEndpoint("/test/introspect").build();
return AuthorizationServerSettings.builder()
.multipleIssuersAllowed(true)
.tokenIntrospectionEndpoint("/test/introspect")
.build();
}
}

View File

@@ -387,7 +387,8 @@ public class OidcClientRegistrationTests {
when(authenticationProvider.authenticate(any())).thenThrow(new OAuth2AuthenticationException("error"));
this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_CLIENT_REGISTRATION_ENDPOINT_URI))
.param(OAuth2ParameterNames.CLIENT_ID, "invalid").with(jwt()));
.param(OAuth2ParameterNames.CLIENT_ID, "invalid")
.with(jwt()));
verify(authenticationFailureHandler).onAuthenticationFailure(any(), any(), any());
verifyNoInteractions(authenticationSuccessHandler);
@@ -411,14 +412,16 @@ public class OidcClientRegistrationTests {
OidcClientRegistration clientRegistrationResponse = registerClient(clientRegistration);
this.mvc.perform(post(ISSUER.concat(DEFAULT_TOKEN_ENDPOINT_URI))
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.param(OAuth2ParameterNames.SCOPE, "scope1")
.with(httpBasic(clientRegistrationResponse.getClientId(), clientRegistrationResponse.getClientSecret())))
.andExpect(status().isOk())
.andExpect(jsonPath("$.access_token").isNotEmpty())
.andExpect(jsonPath("$.scope").value("scope1"))
.andReturn();
this.mvc
.perform(post(ISSUER.concat(DEFAULT_TOKEN_ENDPOINT_URI))
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.param(OAuth2ParameterNames.SCOPE, "scope1")
.with(httpBasic(clientRegistrationResponse.getClientId(),
clientRegistrationResponse.getClientSecret())))
.andExpect(status().isOk())
.andExpect(jsonPath("$.access_token").isNotEmpty())
.andExpect(jsonPath("$.scope").value("scope1"))
.andReturn();
}
// gh-1344
@@ -445,12 +448,12 @@ public class OidcClientRegistrationTests {
Instant issuedAt = Instant.now();
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS);
JwtClaimsSet jwtClaimsSet = JwtClaimsSet.builder()
.issuer(clientRegistrationResponse.getClientId())
.subject(clientRegistrationResponse.getClientId())
.audience(Collections.singletonList(asUrl(ISSUER, this.authorizationServerSettings.getTokenEndpoint())))
.issuedAt(issuedAt)
.expiresAt(expiresAt)
.build();
.issuer(clientRegistrationResponse.getClientId())
.subject(clientRegistrationResponse.getClientId())
.audience(Collections.singletonList(asUrl(ISSUER, this.authorizationServerSettings.getTokenEndpoint())))
.issuedAt(issuedAt)
.expiresAt(expiresAt)
.build();
JWKSet jwkSet = new JWKSet(
TestJwks.jwk(new SecretKeySpec(clientRegistrationResponse.getClientSecret().getBytes(), "HS256"))
@@ -460,15 +463,17 @@ public class OidcClientRegistrationTests {
Jwt jwtAssertion = jwtClientAssertionEncoder.encode(JwtEncoderParameters.from(jwsHeader, jwtClaimsSet));
this.mvc.perform(post(ISSUER.concat(DEFAULT_TOKEN_ENDPOINT_URI))
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.param(OAuth2ParameterNames.SCOPE, "scope1")
.param(OAuth2ParameterNames.CLIENT_ASSERTION_TYPE, "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
.param(OAuth2ParameterNames.CLIENT_ASSERTION, jwtAssertion.getTokenValue())
.param(OAuth2ParameterNames.CLIENT_ID, clientRegistrationResponse.getClientId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.access_token").isNotEmpty())
.andExpect(jsonPath("$.scope").value("scope1"));
this.mvc
.perform(post(ISSUER.concat(DEFAULT_TOKEN_ENDPOINT_URI))
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.param(OAuth2ParameterNames.SCOPE, "scope1")
.param(OAuth2ParameterNames.CLIENT_ASSERTION_TYPE,
"urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
.param(OAuth2ParameterNames.CLIENT_ASSERTION, jwtAssertion.getTokenValue())
.param(OAuth2ParameterNames.CLIENT_ID, clientRegistrationResponse.getClientId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.access_token").isNotEmpty())
.andExpect(jsonPath("$.scope").value("scope1"));
}
@Test
@@ -533,7 +538,8 @@ public class OidcClientRegistrationTests {
// @formatter:on
Jwt jwtAssertion = jwtClientAssertionEncoder.encode(JwtEncoderParameters.from(jwsHeader, jwtClaimsSet));
MvcResult mvcResult = this.mvc.perform(post(ISSUER.concat(DEFAULT_TOKEN_ENDPOINT_URI))
MvcResult mvcResult = this.mvc
.perform(post(ISSUER.concat(DEFAULT_TOKEN_ENDPOINT_URI))
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.param(OAuth2ParameterNames.SCOPE, clientRegistrationScope)
.param(OAuth2ParameterNames.CLIENT_ASSERTION_TYPE,
@@ -553,8 +559,8 @@ public class OidcClientRegistrationTests {
httpHeaders.setBearerAuth(accessToken.getTokenValue());
// Register the client
mvcResult = this.mvc.perform(post(ISSUER.concat(DEFAULT_OIDC_CLIENT_REGISTRATION_ENDPOINT_URI))
.headers(httpHeaders)
mvcResult = this.mvc
.perform(post(ISSUER.concat(DEFAULT_OIDC_CLIENT_REGISTRATION_ENDPOINT_URI)).headers(httpHeaders)
.contentType(MediaType.APPLICATION_JSON)
.content(getClientRegistrationRequestContent(clientRegistration)))
.andExpect(status().isCreated())
@@ -569,11 +575,11 @@ public class OidcClientRegistrationTests {
Instant issuedAt = Instant.now();
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS);
return JwtClaimsSet.builder()
.issuer(registeredClient.getClientId())
.subject(registeredClient.getClientId())
.audience(Collections.singletonList(asUrl(ISSUER, this.authorizationServerSettings.getTokenEndpoint())))
.issuedAt(issuedAt)
.expiresAt(expiresAt);
.issuer(registeredClient.getClientId())
.subject(registeredClient.getClientId())
.audience(Collections.singletonList(asUrl(ISSUER, this.authorizationServerSettings.getTokenEndpoint())))
.issuedAt(issuedAt)
.expiresAt(expiresAt);
}
private static String asUrl(String uri, String path) {
@@ -753,9 +759,7 @@ public class OidcClientRegistrationTests {
@Bean
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder()
.multipleIssuersAllowed(true)
.build();
return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();
}
@Bean

View File

@@ -80,28 +80,29 @@ public class OidcProviderConfigurationTests {
this.spring.register(AuthorizationServerConfiguration.class).autowire();
this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)))
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(ISSUER));
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(ISSUER));
}
@Test
public void requestWhenConfigurationRequestIncludesIssuerPathThenConfigurationResponseHasIssuerPath() throws Exception {
public void requestWhenConfigurationRequestIncludesIssuerPathThenConfigurationResponseHasIssuerPath()
throws Exception {
this.spring.register(AuthorizationServerConfigurationWithMultipleIssuersAllowed.class).autowire();
String issuer = "https://example.com:8443/issuer1";
this.mvc.perform(get(issuer.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)))
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(issuer));
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(issuer));
issuer = "https://example.com:8443/path1/issuer2";
this.mvc.perform(get(issuer.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)))
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(issuer));
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(issuer));
issuer = "https://example.com:8443/path1/path2/issuer3";
this.mvc.perform(get(issuer.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)))
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(issuer));
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(issuer));
}
// gh-632
@@ -109,10 +110,9 @@ public class OidcProviderConfigurationTests {
public void requestWhenConfigurationRequestAndUserAuthenticatedThenReturnConfigurationResponse() throws Exception {
this.spring.register(AuthorizationServerConfiguration.class).autowire();
this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))
.with(user("user")))
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(ISSUER));
this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)).with(user("user")))
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(ISSUER));
}
// gh-616
@@ -122,9 +122,9 @@ public class OidcProviderConfigurationTests {
this.spring.register(AuthorizationServerConfigurationWithProviderConfigurationCustomizer.class).autowire();
this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)))
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED,
hasItems(OidcScopes.OPENID, OidcScopes.PROFILE, OidcScopes.EMAIL)));
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED,
hasItems(OidcScopes.OPENID, OidcScopes.PROFILE, OidcScopes.EMAIL)));
}
@Test
@@ -133,9 +133,10 @@ public class OidcProviderConfigurationTests {
this.spring.register(AuthorizationServerConfigurationWithClientRegistrationEnabled.class).autowire();
this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)))
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(ISSUER))
.andExpect(jsonPath("$.registration_endpoint").value(ISSUER.concat(this.authorizationServerSettings.getOidcClientRegistrationEndpoint())));
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(ISSUER))
.andExpect(jsonPath("$.registration_endpoint")
.value(ISSUER.concat(this.authorizationServerSettings.getOidcClientRegistrationEndpoint())));
}
private ResultMatcher[] defaultConfigurationMatchers(String issuer) {
@@ -235,9 +236,7 @@ public class OidcProviderConfigurationTests {
@Bean
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder()
.issuer(ISSUER)
.build();
return AuthorizationServerSettings.builder().issuer(ISSUER).build();
}
}
@@ -248,9 +247,7 @@ public class OidcProviderConfigurationTests {
@Bean
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder()
.multipleIssuersAllowed(true)
.build();
return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();
}
}

View File

@@ -324,12 +324,13 @@ public class OidcTests {
String issuer = "https://example.com:8443/issuer1";
// Login
MultiValueMap<String, String> authorizationRequestParameters = getAuthorizationRequestParameters(registeredClient);
MvcResult mvcResult = this.mvc.perform(get(issuer.concat(DEFAULT_AUTHORIZATION_ENDPOINT_URI))
.queryParams(authorizationRequestParameters)
.with(user("user")))
.andExpect(status().is3xxRedirection())
.andReturn();
MultiValueMap<String, String> authorizationRequestParameters = getAuthorizationRequestParameters(
registeredClient);
MvcResult mvcResult = this.mvc
.perform(get(issuer.concat(DEFAULT_AUTHORIZATION_ENDPOINT_URI)).queryParams(authorizationRequestParameters)
.with(user("user")))
.andExpect(status().is3xxRedirection())
.andReturn();
MockHttpSession session = (MockHttpSession) mvcResult.getRequest().getSession();
assertThat(session.isNew()).isTrue();
@@ -340,12 +341,13 @@ public class OidcTests {
AUTHORIZATION_CODE_TOKEN_TYPE);
// Get ID Token
mvcResult = this.mvc.perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI))
.params(getTokenRequestParameters(registeredClient, authorization))
.header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth(
registeredClient.getClientId(), registeredClient.getClientSecret())))
.andExpect(status().isOk())
.andReturn();
mvcResult = this.mvc
.perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI))
.params(getTokenRequestParameters(registeredClient, authorization))
.header(HttpHeaders.AUTHORIZATION,
"Basic " + encodeBasicAuth(registeredClient.getClientId(), registeredClient.getClientSecret())))
.andExpect(status().isOk())
.andReturn();
MockHttpServletResponse servletResponse = mvcResult.getResponse();
MockClientHttpResponse httpResponse = new MockClientHttpResponse(servletResponse.getContentAsByteArray(),
@@ -356,11 +358,11 @@ public class OidcTests {
String idToken = (String) accessTokenResponse.getAdditionalParameters().get(OidcParameterNames.ID_TOKEN);
// Logout
mvcResult = this.mvc.perform(post(issuer.concat(DEFAULT_OIDC_LOGOUT_ENDPOINT_URI))
.param("id_token_hint", idToken)
.session(session))
.andExpect(status().is3xxRedirection())
.andReturn();
mvcResult = this.mvc
.perform(post(issuer.concat(DEFAULT_OIDC_LOGOUT_ENDPOINT_URI)).param("id_token_hint", idToken)
.session(session))
.andExpect(status().is3xxRedirection())
.andReturn();
redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
assertThat(redirectedUrl).matches("/");

View File

@@ -526,9 +526,7 @@ public class OidcUserInfoTests {
@Bean
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder()
.multipleIssuersAllowed(true)
.build();
return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();
}
}

View File

@@ -63,8 +63,8 @@ public class OidcProviderConfigurationEndpointFilterTests {
@Test
public void doFilterWhenNotConfigurationRequestThenNotProcessed() throws Exception {
AuthorizationServerContextHolder.setContext(
new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null));
AuthorizationServerContextHolder
.setContext(new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null));
String requestUri = "/path";
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
@@ -79,8 +79,8 @@ public class OidcProviderConfigurationEndpointFilterTests {
@Test
public void doFilterWhenConfigurationRequestPostThenNotProcessed() throws Exception {
AuthorizationServerContextHolder.setContext(
new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null));
AuthorizationServerContextHolder
.setContext(new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null));
String requestUri = DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
@@ -137,18 +137,25 @@ public class OidcProviderConfigurationEndpointFilterTests {
assertThat(providerConfigurationResponse).contains("\"jwks_uri\":\"https://example.com/oauth2/v1/jwks\"");
assertThat(providerConfigurationResponse).contains("\"scopes_supported\":[\"openid\"]");
assertThat(providerConfigurationResponse).contains("\"response_types_supported\":[\"code\"]");
assertThat(providerConfigurationResponse).contains("\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"refresh_token\",\"urn:ietf:params:oauth:grant-type:device_code\",\"urn:ietf:params:oauth:grant-type:token-exchange\"]");
assertThat(providerConfigurationResponse).contains("\"revocation_endpoint\":\"https://example.com/oauth2/v1/revoke\"");
assertThat(providerConfigurationResponse).contains("\"revocation_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]");
assertThat(providerConfigurationResponse).contains("\"introspection_endpoint\":\"https://example.com/oauth2/v1/introspect\"");
assertThat(providerConfigurationResponse).contains("\"introspection_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]");
assertThat(providerConfigurationResponse).contains(
"\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"refresh_token\",\"urn:ietf:params:oauth:grant-type:device_code\",\"urn:ietf:params:oauth:grant-type:token-exchange\"]");
assertThat(providerConfigurationResponse)
.contains("\"revocation_endpoint\":\"https://example.com/oauth2/v1/revoke\"");
assertThat(providerConfigurationResponse).contains(
"\"revocation_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]");
assertThat(providerConfigurationResponse)
.contains("\"introspection_endpoint\":\"https://example.com/oauth2/v1/introspect\"");
assertThat(providerConfigurationResponse).contains(
"\"introspection_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]");
assertThat(providerConfigurationResponse).contains("\"code_challenge_methods_supported\":[\"S256\"]");
assertThat(providerConfigurationResponse).contains("\"tls_client_certificate_bound_access_tokens\":true");
assertThat(providerConfigurationResponse).contains("\"subject_types_supported\":[\"public\"]");
assertThat(providerConfigurationResponse).contains("\"id_token_signing_alg_values_supported\":[\"RS256\"]");
assertThat(providerConfigurationResponse).contains("\"userinfo_endpoint\":\"https://example.com/userinfo\"");
assertThat(providerConfigurationResponse).contains("\"end_session_endpoint\":\"https://example.com/connect/logout\"");
assertThat(providerConfigurationResponse).contains("\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]");
assertThat(providerConfigurationResponse)
.contains("\"end_session_endpoint\":\"https://example.com/connect/logout\"");
assertThat(providerConfigurationResponse).contains(
"\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]");
}
@Test

View File

@@ -86,13 +86,16 @@ public class AuthorizationServerSettingsTests {
public void buildWhenIssuerSetAndMultipleIssuersAllowedTrueThenThrowIllegalArgumentException() {
String issuer = "https://example.com:9000";
assertThatIllegalArgumentException()
.isThrownBy(() -> AuthorizationServerSettings.builder().issuer(issuer).multipleIssuersAllowed(true).build())
.withMessage("The issuer identifier (" + issuer + ") cannot be set when isMultipleIssuersAllowed() is true.");
.isThrownBy(() -> AuthorizationServerSettings.builder().issuer(issuer).multipleIssuersAllowed(true).build())
.withMessage(
"The issuer identifier (" + issuer + ") cannot be set when isMultipleIssuersAllowed() is true.");
}
@Test
public void buildWhenIssuerNotSetAndMultipleIssuersAllowedTrueThenDefaultsAreSet() {
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder()
.multipleIssuersAllowed(true)
.build();
assertThat(authorizationServerSettings.getIssuer()).isNull();
assertThat(authorizationServerSettings.isMultipleIssuersAllowed()).isTrue();

View File

@@ -65,9 +65,10 @@ public class ClientSettingsTests {
@Test
public void x509CertificateSubjectDNWhenProvidedThenSet() {
ClientSettings clientSettings = ClientSettings.builder()
.x509CertificateSubjectDN("CN=demo-client-sample, OU=Spring Samples, O=Spring, C=US")
.build();
assertThat(clientSettings.getX509CertificateSubjectDN()).isEqualTo("CN=demo-client-sample, OU=Spring Samples, O=Spring, C=US");
.x509CertificateSubjectDN("CN=demo-client-sample, OU=Spring Samples, O=Spring, C=US")
.build();
assertThat(clientSettings.getX509CertificateSubjectDN())
.isEqualTo("CN=demo-client-sample, OU=Spring Samples, O=Spring, C=US");
}
@Test

View File

@@ -153,18 +153,16 @@ public class TokenSettingsTests {
@Test
public void x509CertificateBoundAccessTokensWhenTrueThenSet() {
TokenSettings tokenSettings = TokenSettings.builder()
.x509CertificateBoundAccessTokens(true)
.build();
TokenSettings tokenSettings = TokenSettings.builder().x509CertificateBoundAccessTokens(true).build();
assertThat(tokenSettings.isX509CertificateBoundAccessTokens()).isTrue();
}
@Test
public void settingWhenCustomThenSet() {
TokenSettings tokenSettings = TokenSettings.builder()
.setting("name1", "value1")
.settings(settings -> settings.put("name2", "value2"))
.build();
.setting("name1", "value1")
.settings(settings -> settings.put("name2", "value2"))
.build();
assertThat(tokenSettings.getSettings()).hasSize(10);
assertThat(tokenSettings.<String>getSetting("name1")).isEqualTo("value1");
assertThat(tokenSettings.<String>getSetting("name2")).isEqualTo("value2");

View File

@@ -29,22 +29,25 @@ public final class TestX509Certificates {
// Generate the Root certificate (Trust Anchor or most-trusted CA)
KeyPair rootKeyPair = X509CertificateUtils.generateRSAKeyPair();
String distinguishedName = "CN=spring-samples-trusted-ca, OU=Spring Samples, O=Spring, C=US";
X509Certificate rootCertificate = X509CertificateUtils.createTrustAnchorCertificate(rootKeyPair, distinguishedName);
X509Certificate rootCertificate = X509CertificateUtils.createTrustAnchorCertificate(rootKeyPair,
distinguishedName);
// Generate the CA (intermediary) certificate
KeyPair caKeyPair = X509CertificateUtils.generateRSAKeyPair();
distinguishedName = "CN=spring-samples-ca, OU=Spring Samples, O=Spring, C=US";
X509Certificate caCertificate = X509CertificateUtils.createCACertificate(
rootCertificate, rootKeyPair.getPrivate(), caKeyPair.getPublic(), distinguishedName);
X509Certificate caCertificate = X509CertificateUtils.createCACertificate(rootCertificate,
rootKeyPair.getPrivate(), caKeyPair.getPublic(), distinguishedName);
// Generate certificate for demo-client-sample
KeyPair demoClientKeyPair = X509CertificateUtils.generateRSAKeyPair();
distinguishedName = "CN=demo-client-sample, OU=Spring Samples, O=Spring, C=US";
X509Certificate demoClientCertificate = X509CertificateUtils.createEndEntityCertificate(
caCertificate, caKeyPair.getPrivate(), demoClientKeyPair.getPublic(), distinguishedName);
X509Certificate demoClientCertificate = X509CertificateUtils.createEndEntityCertificate(caCertificate,
caKeyPair.getPrivate(), demoClientKeyPair.getPublic(), distinguishedName);
DEMO_CLIENT_PKI_CERTIFICATE = new X509Certificate[] { demoClientCertificate, caCertificate, rootCertificate };
} catch (Exception ex) {
DEMO_CLIENT_PKI_CERTIFICATE = new X509Certificate[] { demoClientCertificate, caCertificate,
rootCertificate };
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
@@ -55,10 +58,12 @@ public final class TestX509Certificates {
// Generate self-signed certificate for demo-client-sample
KeyPair keyPair = X509CertificateUtils.generateRSAKeyPair();
String distinguishedName = "CN=demo-client-sample, OU=Spring Samples, O=Spring, C=US";
X509Certificate demoClientSelfSignedCertificate = X509CertificateUtils.createTrustAnchorCertificate(keyPair, distinguishedName);
X509Certificate demoClientSelfSignedCertificate = X509CertificateUtils.createTrustAnchorCertificate(keyPair,
distinguishedName);
DEMO_CLIENT_SELF_SIGNED_CERTIFICATE = new X509Certificate[] { demoClientSelfSignedCertificate };
} catch (Exception ex) {
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}

View File

@@ -44,15 +44,20 @@ import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
* @author Joe Grandja
*/
public final class X509CertificateUtils {
private static final String BC_PROVIDER = "BC";
private static final String SHA256_RSA_SIGNATURE_ALGORITHM = "SHA256withRSA";
private static final Date DEFAULT_START_DATE;
private static final Date DEFAULT_END_DATE;
static {
Security.addProvider(new BouncyCastleProvider());
// Setup default certificate start date to yesterday and end date for 1 year validity
// Setup default certificate start date to yesterday and end date for 1 year
// validity
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, -1);
DEFAULT_START_DATE = calendar.getTime();
@@ -69,34 +74,31 @@ public final class X509CertificateUtils {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", BC_PROVIDER);
keyPairGenerator.initialize(new RSAKeyGenParameterSpec(2048, RSAKeyGenParameterSpec.F4));
keyPair = keyPairGenerator.generateKeyPair();
} catch (Exception ex) {
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
return keyPair;
}
public static X509Certificate createTrustAnchorCertificate(KeyPair keyPair, String distinguishedName) throws Exception {
public static X509Certificate createTrustAnchorCertificate(KeyPair keyPair, String distinguishedName)
throws Exception {
X500Principal subject = new X500Principal(distinguishedName);
BigInteger serialNum = new BigInteger(Long.toString(new SecureRandom().nextLong()));
X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(
subject,
serialNum,
DEFAULT_START_DATE,
DEFAULT_END_DATE,
subject,
keyPair.getPublic());
X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(subject, serialNum, DEFAULT_START_DATE,
DEFAULT_END_DATE, subject, keyPair.getPublic());
// Add Extensions
JcaX509ExtensionUtils extensionUtils = new JcaX509ExtensionUtils();
certBuilder
// A BasicConstraints to mark root certificate as CA certificate
.addExtension(Extension.basicConstraints, true, new BasicConstraints(true))
.addExtension(Extension.subjectKeyIdentifier, false,
extensionUtils.createSubjectKeyIdentifier(keyPair.getPublic()));
// A BasicConstraints to mark root certificate as CA certificate
.addExtension(Extension.basicConstraints, true, new BasicConstraints(true))
.addExtension(Extension.subjectKeyIdentifier, false,
extensionUtils.createSubjectKeyIdentifier(keyPair.getPublic()));
ContentSigner signer = new JcaContentSignerBuilder(SHA256_RSA_SIGNATURE_ALGORITHM)
.setProvider(BC_PROVIDER).build(keyPair.getPrivate());
ContentSigner signer = new JcaContentSignerBuilder(SHA256_RSA_SIGNATURE_ALGORITHM).setProvider(BC_PROVIDER)
.build(keyPair.getPrivate());
JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(BC_PROVIDER);
@@ -109,32 +111,26 @@ public final class X509CertificateUtils {
X500Principal subject = new X500Principal(distinguishedName);
BigInteger serialNum = new BigInteger(Long.toString(new SecureRandom().nextLong()));
X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(
signerCert.getSubjectX500Principal(),
serialNum,
DEFAULT_START_DATE,
DEFAULT_END_DATE,
subject,
certKey);
X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(signerCert.getSubjectX500Principal(),
serialNum, DEFAULT_START_DATE, DEFAULT_END_DATE, subject, certKey);
// Add Extensions
JcaX509ExtensionUtils extensionUtils = new JcaX509ExtensionUtils();
certBuilder
// A BasicConstraints to mark as CA certificate and how many CA certificates can follow it in the chain
// (with 0 meaning the chain ends with the next certificate in the chain).
.addExtension(Extension.basicConstraints, true, new BasicConstraints(0))
// KeyUsage specifies what the public key in the certificate can be used for.
// In this case, it can be used for signing other certificates and/or
// signing Certificate Revocation Lists (CRLs).
.addExtension(Extension.keyUsage, true,
new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign))
.addExtension(Extension.authorityKeyIdentifier, false,
extensionUtils.createAuthorityKeyIdentifier(signerCert))
.addExtension(Extension.subjectKeyIdentifier, false,
extensionUtils.createSubjectKeyIdentifier(certKey));
// A BasicConstraints to mark as CA certificate and how many CA certificates
// can follow it in the chain
// (with 0 meaning the chain ends with the next certificate in the chain).
.addExtension(Extension.basicConstraints, true, new BasicConstraints(0))
// KeyUsage specifies what the public key in the certificate can be used for.
// In this case, it can be used for signing other certificates and/or
// signing Certificate Revocation Lists (CRLs).
.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign))
.addExtension(Extension.authorityKeyIdentifier, false,
extensionUtils.createAuthorityKeyIdentifier(signerCert))
.addExtension(Extension.subjectKeyIdentifier, false, extensionUtils.createSubjectKeyIdentifier(certKey));
ContentSigner signer = new JcaContentSignerBuilder(SHA256_RSA_SIGNATURE_ALGORITHM)
.setProvider(BC_PROVIDER).build(signerKey);
ContentSigner signer = new JcaContentSignerBuilder(SHA256_RSA_SIGNATURE_ALGORITHM).setProvider(BC_PROVIDER)
.build(signerKey);
JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(BC_PROVIDER);
@@ -147,26 +143,18 @@ public final class X509CertificateUtils {
X500Principal subject = new X500Principal(distinguishedName);
BigInteger serialNum = new BigInteger(Long.toString(new SecureRandom().nextLong()));
X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(
signerCert.getSubjectX500Principal(),
serialNum,
DEFAULT_START_DATE,
DEFAULT_END_DATE,
subject,
certKey);
X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(signerCert.getSubjectX500Principal(),
serialNum, DEFAULT_START_DATE, DEFAULT_END_DATE, subject, certKey);
JcaX509ExtensionUtils extensionUtils = new JcaX509ExtensionUtils();
certBuilder
.addExtension(Extension.basicConstraints, true, new BasicConstraints(false))
.addExtension(Extension.keyUsage, true,
new KeyUsage(KeyUsage.digitalSignature))
.addExtension(Extension.authorityKeyIdentifier, false,
extensionUtils.createAuthorityKeyIdentifier(signerCert))
.addExtension(Extension.subjectKeyIdentifier, false,
extensionUtils.createSubjectKeyIdentifier(certKey));
certBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(false))
.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature))
.addExtension(Extension.authorityKeyIdentifier, false,
extensionUtils.createAuthorityKeyIdentifier(signerCert))
.addExtension(Extension.subjectKeyIdentifier, false, extensionUtils.createSubjectKeyIdentifier(certKey));
ContentSigner signer = new JcaContentSignerBuilder(SHA256_RSA_SIGNATURE_ALGORITHM)
.setProvider(BC_PROVIDER).build(signerKey);
ContentSigner signer = new JcaContentSignerBuilder(SHA256_RSA_SIGNATURE_ALGORITHM).setProvider(BC_PROVIDER)
.build(signerKey);
JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(BC_PROVIDER);

View File

@@ -63,8 +63,8 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
@Test
public void doFilterWhenNotAuthorizationServerMetadataRequestThenNotProcessed() throws Exception {
AuthorizationServerContextHolder.setContext(
new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null));
AuthorizationServerContextHolder
.setContext(new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null));
String requestUri = "/path";
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
@@ -79,8 +79,8 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
@Test
public void doFilterWhenAuthorizationServerMetadataRequestPostThenNotProcessed() throws Exception {
AuthorizationServerContextHolder.setContext(
new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null));
AuthorizationServerContextHolder
.setContext(new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null));
String requestUri = DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
@@ -126,16 +126,24 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
assertThat(response.getContentType()).isEqualTo(MediaType.APPLICATION_JSON_VALUE);
String authorizationServerMetadataResponse = response.getContentAsString();
assertThat(authorizationServerMetadataResponse).contains("\"issuer\":\"https://example.com\"");
assertThat(authorizationServerMetadataResponse).contains("\"authorization_endpoint\":\"https://example.com/oauth2/v1/authorize\"");
assertThat(authorizationServerMetadataResponse).contains("\"token_endpoint\":\"https://example.com/oauth2/v1/token\"");
assertThat(authorizationServerMetadataResponse).contains("\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]");
assertThat(authorizationServerMetadataResponse)
.contains("\"authorization_endpoint\":\"https://example.com/oauth2/v1/authorize\"");
assertThat(authorizationServerMetadataResponse)
.contains("\"token_endpoint\":\"https://example.com/oauth2/v1/token\"");
assertThat(authorizationServerMetadataResponse).contains(
"\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]");
assertThat(authorizationServerMetadataResponse).contains("\"jwks_uri\":\"https://example.com/oauth2/v1/jwks\"");
assertThat(authorizationServerMetadataResponse).contains("\"response_types_supported\":[\"code\"]");
assertThat(authorizationServerMetadataResponse).contains("\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"refresh_token\",\"urn:ietf:params:oauth:grant-type:device_code\",\"urn:ietf:params:oauth:grant-type:token-exchange\"]");
assertThat(authorizationServerMetadataResponse).contains("\"revocation_endpoint\":\"https://example.com/oauth2/v1/revoke\"");
assertThat(authorizationServerMetadataResponse).contains("\"revocation_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]");
assertThat(authorizationServerMetadataResponse).contains("\"introspection_endpoint\":\"https://example.com/oauth2/v1/introspect\"");
assertThat(authorizationServerMetadataResponse).contains("\"introspection_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]");
assertThat(authorizationServerMetadataResponse).contains(
"\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"refresh_token\",\"urn:ietf:params:oauth:grant-type:device_code\",\"urn:ietf:params:oauth:grant-type:token-exchange\"]");
assertThat(authorizationServerMetadataResponse)
.contains("\"revocation_endpoint\":\"https://example.com/oauth2/v1/revoke\"");
assertThat(authorizationServerMetadataResponse).contains(
"\"revocation_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]");
assertThat(authorizationServerMetadataResponse)
.contains("\"introspection_endpoint\":\"https://example.com/oauth2/v1/introspect\"");
assertThat(authorizationServerMetadataResponse).contains(
"\"introspection_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]");
assertThat(authorizationServerMetadataResponse).contains("\"code_challenge_methods_supported\":[\"S256\"]");
assertThat(authorizationServerMetadataResponse).contains("\"tls_client_certificate_bound_access_tokens\":true");
}

View File

@@ -452,17 +452,16 @@ public class OAuth2TokenEndpointFilterTests {
@Test
public void doFilterWhenTokenExchangeRequestThenAccessTokenResponse() throws Exception {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build();
Authentication clientPrincipal = new OAuth2ClientAuthenticationToken(
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
OAuth2AccessToken accessToken = new OAuth2AccessToken(
OAuth2AccessToken.TokenType.BEARER, "token",
.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)
.build();
Authentication clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient,
ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token",
Instant.now(), Instant.now().plus(Duration.ofHours(1)),
new HashSet<>(Arrays.asList("scope1", "scope2")));
OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", Instant.now());
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
new OAuth2AccessTokenAuthenticationToken(
registeredClient, clientPrincipal, accessToken, refreshToken);
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = new OAuth2AccessTokenAuthenticationToken(
registeredClient, clientPrincipal, accessToken, refreshToken);
when(this.authenticationManager.authenticate(any())).thenReturn(accessTokenAuthentication);
@@ -478,24 +477,22 @@ public class OAuth2TokenEndpointFilterTests {
verifyNoInteractions(filterChain);
ArgumentCaptor<OAuth2TokenExchangeAuthenticationToken> tokenExchangeAuthenticationCaptor =
ArgumentCaptor.forClass(OAuth2TokenExchangeAuthenticationToken.class);
ArgumentCaptor<OAuth2TokenExchangeAuthenticationToken> tokenExchangeAuthenticationCaptor = ArgumentCaptor
.forClass(OAuth2TokenExchangeAuthenticationToken.class);
verify(this.authenticationManager).authenticate(tokenExchangeAuthenticationCaptor.capture());
OAuth2TokenExchangeAuthenticationToken tokenExchangeAuthenticationToken =
tokenExchangeAuthenticationCaptor.getValue();
OAuth2TokenExchangeAuthenticationToken tokenExchangeAuthenticationToken = tokenExchangeAuthenticationCaptor
.getValue();
assertThat(tokenExchangeAuthenticationToken.getSubjectToken()).isEqualTo("subject-token");
assertThat(tokenExchangeAuthenticationToken.getSubjectTokenType()).isEqualTo(ACCESS_TOKEN_TYPE);
assertThat(tokenExchangeAuthenticationToken.getPrincipal()).isEqualTo(clientPrincipal);
assertThat(tokenExchangeAuthenticationToken.getScopes()).isEqualTo(registeredClient.getScopes());
assertThat(tokenExchangeAuthenticationToken.getAdditionalParameters())
.containsExactly(entry("custom-param-1", "custom-value-1"),
entry("custom-param-2", new String[] { "custom-value-1", "custom-value-2" }));
assertThat(tokenExchangeAuthenticationToken.getDetails())
.asInstanceOf(type(WebAuthenticationDetails.class))
.extracting(WebAuthenticationDetails::getRemoteAddress)
.isEqualTo(REMOTE_ADDRESS);
assertThat(tokenExchangeAuthenticationToken.getAdditionalParameters()).containsExactly(
entry("custom-param-1", "custom-value-1"),
entry("custom-param-2", new String[] { "custom-value-1", "custom-value-2" }));
assertThat(tokenExchangeAuthenticationToken.getDetails()).asInstanceOf(type(WebAuthenticationDetails.class))
.extracting(WebAuthenticationDetails::getRemoteAddress)
.isEqualTo(REMOTE_ADDRESS);
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response);
@@ -503,10 +500,10 @@ public class OAuth2TokenEndpointFilterTests {
OAuth2AccessToken accessTokenResult = accessTokenResponse.getAccessToken();
assertThat(accessTokenResult.getTokenType()).isEqualTo(accessToken.getTokenType());
assertThat(accessTokenResult.getTokenValue()).isEqualTo(accessToken.getTokenValue());
assertThat(accessTokenResult.getIssuedAt()).isBetween(
accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1));
assertThat(accessTokenResult.getExpiresAt()).isBetween(
accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1));
assertThat(accessTokenResult.getIssuedAt()).isBetween(accessToken.getIssuedAt().minusSeconds(1),
accessToken.getIssuedAt().plusSeconds(1));
assertThat(accessTokenResult.getExpiresAt()).isBetween(accessToken.getExpiresAt().minusSeconds(1),
accessToken.getExpiresAt().plusSeconds(1));
assertThat(accessTokenResult.getScopes()).isEqualTo(accessToken.getScopes());
OAuth2RefreshToken refreshTokenResult = accessTokenResponse.getRefreshToken();

View File

@@ -53,13 +53,16 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
* @author Dmitriy Dubson
*/
public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests {
private final RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
private final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter =
new OAuth2AccessTokenResponseHttpMessageConverter();
private final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter = new OAuth2AccessTokenResponseHttpMessageConverter();
private final OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret());
private final OAuth2AccessTokenResponseAuthenticationSuccessHandler authenticationSuccessHandler =
new OAuth2AccessTokenResponseAuthenticationSuccessHandler();
this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC,
this.registeredClient.getClientSecret());
private final OAuth2AccessTokenResponseAuthenticationSuccessHandler authenticationSuccessHandler = new OAuth2AccessTokenResponseAuthenticationSuccessHandler();
@Test
public void setAccessTokenResponseCustomizerWhenNullThenThrowIllegalArgumentException() {
@@ -79,23 +82,22 @@ public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests {
OAuth2AccessToken accessToken = authorization.getAccessToken().getToken();
OAuth2RefreshToken refreshToken = authorization.getRefreshToken().getToken();
Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
Authentication authentication = new OAuth2AccessTokenAuthenticationToken(
this.registeredClient, this.clientPrincipal, accessToken, refreshToken, additionalParameters);
Authentication authentication = new OAuth2AccessTokenAuthenticationToken(this.registeredClient,
this.clientPrincipal, accessToken, refreshToken, additionalParameters);
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, authentication);
OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response);
assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo(accessToken.getTokenValue());
assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(accessToken.getTokenType());
assertThat(accessTokenResponse.getAccessToken().getIssuedAt()).isBetween(
accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1));
assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(
accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1));
assertThat(accessTokenResponse.getAccessToken().getIssuedAt())
.isBetween(accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1));
assertThat(accessTokenResponse.getAccessToken().getExpiresAt())
.isBetween(accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1));
assertThat(accessTokenResponse.getRefreshToken()).isNotNull();
assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo(refreshToken.getTokenValue());
assertThat(accessTokenResponse.getAdditionalParameters()).containsExactlyInAnyOrderEntriesOf(
Map.of("param1", "value1")
);
assertThat(accessTokenResponse.getAdditionalParameters())
.containsExactlyInAnyOrderEntriesOf(Map.of("param1", "value1"));
}
@Test
@@ -103,16 +105,17 @@ public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests {
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
assertThatThrownBy(() ->
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, new TestingAuthenticationToken(this.clientPrincipal, null)))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.extracting("errorCode")
.isEqualTo(OAuth2ErrorCodes.SERVER_ERROR);
assertThatThrownBy(() -> this.authenticationSuccessHandler.onAuthenticationSuccess(request, response,
new TestingAuthenticationToken(this.clientPrincipal, null)))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.extracting("errorCode")
.isEqualTo(OAuth2ErrorCodes.SERVER_ERROR);
}
@Test
public void onAuthenticationSuccessWhenAccessTokenResponseCustomizerSetThenAccessTokenResponseCustomized() throws Exception {
public void onAuthenticationSuccessWhenAccessTokenResponseCustomizerSetThenAccessTokenResponseCustomized()
throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
@@ -120,8 +123,8 @@ public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests {
OAuth2AccessToken accessToken = authorization.getAccessToken().getToken();
OAuth2RefreshToken refreshToken = authorization.getRefreshToken().getToken();
Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
Authentication authentication = new OAuth2AccessTokenAuthenticationToken(
this.registeredClient, this.clientPrincipal, accessToken, refreshToken, additionalParameters);
Authentication authentication = new OAuth2AccessTokenAuthenticationToken(this.registeredClient,
this.clientPrincipal, accessToken, refreshToken, additionalParameters);
Consumer<OAuth2AccessTokenAuthenticationContext> accessTokenResponseCustomizer = (authenticationContext) -> {
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = authenticationContext.getAuthentication();
@@ -136,20 +139,19 @@ public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests {
OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response);
assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo(accessToken.getTokenValue());
assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(accessToken.getTokenType());
assertThat(accessTokenResponse.getAccessToken().getIssuedAt()).isBetween(
accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1));
assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(
accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1));
assertThat(accessTokenResponse.getAccessToken().getIssuedAt())
.isBetween(accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1));
assertThat(accessTokenResponse.getAccessToken().getExpiresAt())
.isBetween(accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1));
assertThat(accessTokenResponse.getRefreshToken()).isNotNull();
assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo(refreshToken.getTokenValue());
assertThat(accessTokenResponse.getAdditionalParameters()).containsExactlyInAnyOrderEntriesOf(
Map.of("param1", "value1", "authorization_id", "id")
);
assertThat(accessTokenResponse.getAdditionalParameters())
.containsExactlyInAnyOrderEntriesOf(Map.of("param1", "value1", "authorization_id", "id"));
}
private OAuth2AccessTokenResponse readAccessTokenResponse(MockHttpServletResponse response) throws Exception {
MockClientHttpResponse httpResponse = new MockClientHttpResponse(
response.getContentAsByteArray(), HttpStatus.valueOf(response.getStatus()));
MockClientHttpResponse httpResponse = new MockClientHttpResponse(response.getContentAsByteArray(),
HttpStatus.valueOf(response.getStatus()));
return this.accessTokenHttpResponseConverter.read(OAuth2AccessTokenResponse.class, httpResponse);
}

View File

@@ -41,11 +41,17 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
* @author Steve Riesenberg
*/
public class OAuth2TokenExchangeAuthenticationConverterTests {
private static final String CLIENT_ID = "client-1";
private static final String TOKEN_URI = "/oauth2/token";
private static final String SUBJECT_TOKEN = "EfYu_0jEL";
private static final String ACTOR_TOKEN = "JlNE_xR1f";
private static final String ACCESS_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:access_token";
private static final String JWT_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:jwt";
private OAuth2TokenExchangeAuthenticationConverter converter;
@@ -222,7 +228,6 @@ public class OAuth2TokenExchangeAuthenticationConverterTests {
// @formatter:on
}
@Test
public void convertWhenMultipleActorTokenParametersThenInvalidRequestError() {
MockHttpServletRequest request = createRequest();
@@ -312,8 +317,8 @@ public class OAuth2TokenExchangeAuthenticationConverterTests {
securityContext.setAuthentication(new TestingAuthenticationToken(CLIENT_ID, null));
SecurityContextHolder.setContext(securityContext);
OAuth2TokenExchangeAuthenticationToken authentication =
(OAuth2TokenExchangeAuthenticationToken) this.converter.convert(request);
OAuth2TokenExchangeAuthenticationToken authentication = (OAuth2TokenExchangeAuthenticationToken) this.converter
.convert(request);
assertThat(authentication).isNotNull();
assertThat(authentication.getResources()).containsExactly("https://mydomain.com/resource1",
"https://mydomain.com/resource2");

View File

@@ -39,6 +39,7 @@ import static org.assertj.core.api.Assertions.entry;
* @author Joe Grandja
*/
public class X509ClientCertificateAuthenticationConverterTests {
private final X509ClientCertificateAuthenticationConverter converter = new X509ClientCertificateAuthenticationConverter();
@Test
@@ -51,8 +52,7 @@ public class X509ClientCertificateAuthenticationConverterTests {
@Test
public void convertWhenEmptyX509CertificateThenReturnNull() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setAttribute("jakarta.servlet.request.X509Certificate",
new X509Certificate[0]);
request.setAttribute("jakarta.servlet.request.X509Certificate", new X509Certificate[0]);
Authentication authentication = this.converter.convert(request);
assertThat(authentication).isNull();
}
@@ -62,11 +62,10 @@ public class X509ClientCertificateAuthenticationConverterTests {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setAttribute("jakarta.servlet.request.X509Certificate",
TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE);
assertThatThrownBy(() -> this.converter.convert(request))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.extracting("errorCode")
.isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST);
assertThatThrownBy(() -> this.converter.convert(request)).isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.extracting("errorCode")
.isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST);
}
@Test
@@ -76,11 +75,10 @@ public class X509ClientCertificateAuthenticationConverterTests {
TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE);
request.addParameter(OAuth2ParameterNames.CLIENT_ID, "client-1");
request.addParameter(OAuth2ParameterNames.CLIENT_ID, "client-2");
assertThatThrownBy(() -> this.converter.convert(request))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.extracting("errorCode")
.isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST);
assertThatThrownBy(() -> this.converter.convert(request)).isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.extracting("errorCode")
.isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST);
}
@Test
@@ -93,16 +91,16 @@ public class X509ClientCertificateAuthenticationConverterTests {
request.addParameter(OAuth2ParameterNames.CODE, "code");
request.addParameter("custom-param-1", "custom-value-1");
request.addParameter("custom-param-2", "custom-value-1", "custom-value-2");
OAuth2ClientAuthenticationToken authentication = (OAuth2ClientAuthenticationToken) this.converter.convert(request);
OAuth2ClientAuthenticationToken authentication = (OAuth2ClientAuthenticationToken) this.converter
.convert(request);
assertThat(authentication.getPrincipal()).isEqualTo("client-1");
assertThat(authentication.getCredentials()).isEqualTo(TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE);
assertThat(authentication.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.TLS_CLIENT_AUTH);
assertThat(authentication.getAdditionalParameters())
.containsOnly(
entry(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue()),
entry(OAuth2ParameterNames.CODE, "code"),
entry("custom-param-1", "custom-value-1"),
entry("custom-param-2", new String[] {"custom-value-1", "custom-value-2"}));
assertThat(authentication.getClientAuthenticationMethod())
.isEqualTo(ClientAuthenticationMethod.TLS_CLIENT_AUTH);
assertThat(authentication.getAdditionalParameters()).containsOnly(
entry(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue()),
entry(OAuth2ParameterNames.CODE, "code"), entry("custom-param-1", "custom-value-1"),
entry("custom-param-2", new String[] { "custom-value-1", "custom-value-2" }));
}
@Test
@@ -115,16 +113,16 @@ public class X509ClientCertificateAuthenticationConverterTests {
request.addParameter(OAuth2ParameterNames.CODE, "code");
request.addParameter("custom-param-1", "custom-value-1");
request.addParameter("custom-param-2", "custom-value-1", "custom-value-2");
OAuth2ClientAuthenticationToken authentication = (OAuth2ClientAuthenticationToken) this.converter.convert(request);
OAuth2ClientAuthenticationToken authentication = (OAuth2ClientAuthenticationToken) this.converter
.convert(request);
assertThat(authentication.getPrincipal()).isEqualTo("client-1");
assertThat(authentication.getCredentials()).isEqualTo(TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE);
assertThat(authentication.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH);
assertThat(authentication.getAdditionalParameters())
.containsOnly(
entry(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue()),
entry(OAuth2ParameterNames.CODE, "code"),
entry("custom-param-1", "custom-value-1"),
entry("custom-param-2", new String[] {"custom-value-1", "custom-value-2"}));
assertThat(authentication.getClientAuthenticationMethod())
.isEqualTo(ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH);
assertThat(authentication.getAdditionalParameters()).containsOnly(
entry(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue()),
entry(OAuth2ParameterNames.CODE, "code"), entry("custom-param-1", "custom-value-1"),
entry("custom-param-2", new String[] { "custom-value-1", "custom-value-2" }));
}
}