Improve configurability for AuthenticationConverter and AuthenticationProvider
Closes gh-417
This commit is contained in:
@@ -202,18 +202,22 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h
|
||||
.clientAuthentication(clientAuthentication ->
|
||||
clientAuthentication
|
||||
.authenticationConverter(authenticationConverter) <1>
|
||||
.authenticationProvider(authenticationProvider) <2>
|
||||
.authenticationSuccessHandler(authenticationSuccessHandler) <3>
|
||||
.errorResponseHandler(errorResponseHandler) <4>
|
||||
.authenticationConverters(authenticationConvertersConsumer) <2>
|
||||
.authenticationProvider(authenticationProvider) <3>
|
||||
.authenticationProviders(authenticationProvidersConsumer) <4>
|
||||
.authenticationSuccessHandler(authenticationSuccessHandler) <5>
|
||||
.errorResponseHandler(errorResponseHandler) <6>
|
||||
);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
<1> `authenticationConverter()`: The `AuthenticationConverter` (_pre-processor_) used when attempting to extract client credentials from `HttpServletRequest` to an instance of `OAuth2ClientAuthenticationToken`.
|
||||
<2> `authenticationProvider()`: The `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2ClientAuthenticationToken`. (One or more may be added to replace the defaults.)
|
||||
<3> `authenticationSuccessHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling a successful client authentication and associating the `OAuth2ClientAuthenticationToken` to the `SecurityContext`.
|
||||
<4> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling a failed client authentication and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-5.2[`OAuth2Error` response].
|
||||
<1> `authenticationConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract client credentials from `HttpServletRequest` to an instance of `OAuth2ClientAuthenticationToken`.
|
||||
<2> `authenticationConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
|
||||
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2ClientAuthenticationToken`.
|
||||
<4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
|
||||
<5> `authenticationSuccessHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling a successful client authentication and associating the `OAuth2ClientAuthenticationToken` to the `SecurityContext`.
|
||||
<6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling a failed client authentication and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-5.2[`OAuth2Error` response].
|
||||
|
||||
`OAuth2ClientAuthenticationConfigurer` configures the `OAuth2ClientAuthenticationFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
|
||||
`OAuth2ClientAuthenticationFilter` is the `Filter` that processes client authentication requests.
|
||||
|
||||
@@ -21,20 +21,24 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h
|
||||
.authorizationEndpoint(authorizationEndpoint ->
|
||||
authorizationEndpoint
|
||||
.authorizationRequestConverter(authorizationRequestConverter) <1>
|
||||
.authenticationProvider(authenticationProvider) <2>
|
||||
.authorizationResponseHandler(authorizationResponseHandler) <3>
|
||||
.errorResponseHandler(errorResponseHandler) <4>
|
||||
.consentPage("/oauth2/v1/authorize") <5>
|
||||
.authorizationRequestConverters(authorizationRequestConvertersConsumer) <2>
|
||||
.authenticationProvider(authenticationProvider) <3>
|
||||
.authenticationProviders(authenticationProvidersConsumer) <4>
|
||||
.authorizationResponseHandler(authorizationResponseHandler) <5>
|
||||
.errorResponseHandler(errorResponseHandler) <6>
|
||||
.consentPage("/oauth2/v1/authorize") <7>
|
||||
);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
<1> `authorizationRequestConverter()`: The `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1[OAuth2 authorization request] (or consent) from `HttpServletRequest` to an instance of `OAuth2AuthorizationCodeRequestAuthenticationToken`.
|
||||
<2> `authenticationProvider()`: The `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2AuthorizationCodeRequestAuthenticationToken`. (One or more may be added to replace the defaults.)
|
||||
<3> `authorizationResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2AuthorizationCodeRequestAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2[OAuth2AuthorizationResponse].
|
||||
<4> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthorizationCodeRequestAuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1[OAuth2Error response].
|
||||
<5> `consentPage()`: The `URI` of the custom consent page to redirect resource owners to if consent is required during the authorization request flow.
|
||||
<1> `authorizationRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1[OAuth2 authorization request] (or consent) from `HttpServletRequest` to an instance of `OAuth2AuthorizationCodeRequestAuthenticationToken`.
|
||||
<2> `authorizationRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
|
||||
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2AuthorizationCodeRequestAuthenticationToken`.
|
||||
<4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
|
||||
<5> `authorizationResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2AuthorizationCodeRequestAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2[OAuth2AuthorizationResponse].
|
||||
<6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthorizationCodeRequestAuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1[OAuth2Error response].
|
||||
<7> `consentPage()`: The `URI` of the custom consent page to redirect resource owners to if consent is required during the authorization request flow.
|
||||
|
||||
`OAuth2AuthorizationEndpointConfigurer` configures the `OAuth2AuthorizationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
|
||||
`OAuth2AuthorizationEndpointFilter` is the `Filter` that processes OAuth2 authorization requests (and consents).
|
||||
@@ -65,18 +69,22 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h
|
||||
.tokenEndpoint(tokenEndpoint ->
|
||||
tokenEndpoint
|
||||
.accessTokenRequestConverter(accessTokenRequestConverter) <1>
|
||||
.authenticationProvider(authenticationProvider) <2>
|
||||
.accessTokenResponseHandler(accessTokenResponseHandler) <3>
|
||||
.errorResponseHandler(errorResponseHandler) <4>
|
||||
.accessTokenRequestConverters(accessTokenRequestConvertersConsumer) <2>
|
||||
.authenticationProvider(authenticationProvider) <3>
|
||||
.authenticationProviders(authenticationProvidersConsumer) <4>
|
||||
.accessTokenResponseHandler(accessTokenResponseHandler) <5>
|
||||
.errorResponseHandler(errorResponseHandler) <6>
|
||||
);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
<1> `accessTokenRequestConverter()`: The `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3[OAuth2 access token request] from `HttpServletRequest` to an instance of `OAuth2AuthorizationGrantAuthenticationToken`.
|
||||
<2> `authenticationProvider()`: The `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2AuthorizationGrantAuthenticationToken`. (One or more may be added to replace the defaults.)
|
||||
<3> `accessTokenResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an `OAuth2AccessTokenAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-5.1[`OAuth2AccessTokenResponse`].
|
||||
<4> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-5.2[OAuth2Error response].
|
||||
<1> `accessTokenRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3[OAuth2 access token request] from `HttpServletRequest` to an instance of `OAuth2AuthorizationGrantAuthenticationToken`.
|
||||
<2> `accessTokenRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
|
||||
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2AuthorizationGrantAuthenticationToken`.
|
||||
<4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
|
||||
<5> `accessTokenResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an `OAuth2AccessTokenAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-5.1[`OAuth2AccessTokenResponse`].
|
||||
<6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-5.2[OAuth2Error response].
|
||||
|
||||
`OAuth2TokenEndpointConfigurer` configures the `OAuth2TokenEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
|
||||
`OAuth2TokenEndpointFilter` is the `Filter` that processes OAuth2 access token requests.
|
||||
@@ -110,25 +118,29 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h
|
||||
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint ->
|
||||
tokenIntrospectionEndpoint
|
||||
.introspectionRequestConverter(introspectionRequestConverter) <1>
|
||||
.authenticationProvider(authenticationProvider) <2>
|
||||
.introspectionResponseHandler(introspectionResponseHandler) <3>
|
||||
.errorResponseHandler(errorResponseHandler) <4>
|
||||
.introspectionRequestConverters(introspectionRequestConvertersConsumer) <2>
|
||||
.authenticationProvider(authenticationProvider) <3>
|
||||
.authenticationProviders(authenticationProvidersConsumer) <4>
|
||||
.introspectionResponseHandler(introspectionResponseHandler) <5>
|
||||
.errorResponseHandler(errorResponseHandler) <6>
|
||||
);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
<1> `introspectionRequestConverter()`: The `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc7662#section-2.1[OAuth2 introspection request] from `HttpServletRequest` to an instance of `OAuth2TokenIntrospectionAuthenticationToken`.
|
||||
<2> `authenticationProvider()`: The `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2TokenIntrospectionAuthenticationToken`. (One or more may be added to replace the defaults.)
|
||||
<3> `introspectionResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2TokenIntrospectionAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc7662#section-2.2[OAuth2TokenIntrospection response].
|
||||
<4> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc7662#section-2.3[OAuth2Error response].
|
||||
<1> `introspectionRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc7662#section-2.1[OAuth2 introspection request] from `HttpServletRequest` to an instance of `OAuth2TokenIntrospectionAuthenticationToken`.
|
||||
<2> `introspectionRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
|
||||
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2TokenIntrospectionAuthenticationToken`.
|
||||
<4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
|
||||
<5> `introspectionResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2TokenIntrospectionAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc7662#section-2.2[OAuth2TokenIntrospection response].
|
||||
<6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc7662#section-2.3[OAuth2Error response].
|
||||
|
||||
`OAuth2TokenIntrospectionEndpointConfigurer` configures the `OAuth2TokenIntrospectionEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
|
||||
`OAuth2TokenIntrospectionEndpointFilter` is the `Filter` that processes OAuth2 introspection requests.
|
||||
|
||||
`OAuth2TokenIntrospectionEndpointFilter` is configured with the following defaults:
|
||||
|
||||
* `*AuthenticationConverter*` -- An internal implementation that returns the `OAuth2TokenIntrospectionAuthenticationToken`.
|
||||
* `*AuthenticationConverter*` -- An `OAuth2TokenIntrospectionAuthenticationConverter`.
|
||||
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2TokenIntrospectionAuthenticationProvider`.
|
||||
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2TokenIntrospectionAuthenticationToken` and returns the `OAuth2TokenIntrospection` response.
|
||||
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
|
||||
@@ -152,26 +164,30 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h
|
||||
authorizationServerConfigurer
|
||||
.tokenRevocationEndpoint(tokenRevocationEndpoint ->
|
||||
tokenRevocationEndpoint
|
||||
.revocationRequestConverter(revocationRequestConverter) <1>
|
||||
.authenticationProvider(authenticationProvider) <2>
|
||||
.revocationResponseHandler(revocationResponseHandler) <3>
|
||||
.errorResponseHandler(errorResponseHandler) <4>
|
||||
.revocationRequestConverter(revocationRequestConverter) <1>
|
||||
.revocationRequestConverters(revocationRequestConvertersConsumer) <2>
|
||||
.authenticationProvider(authenticationProvider) <3>
|
||||
.authenticationProviders(authenticationProvidersConsumer) <4>
|
||||
.revocationResponseHandler(revocationResponseHandler) <5>
|
||||
.errorResponseHandler(errorResponseHandler) <6>
|
||||
);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
<1> `revocationRequestConverter()`: The `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc7009#section-2.1[OAuth2 revocation request] from `HttpServletRequest` to an instance of `OAuth2TokenRevocationAuthenticationToken`.
|
||||
<2> `authenticationProvider()`: The `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2TokenRevocationAuthenticationToken`. (One or more may be added to replace the defaults.)
|
||||
<3> `revocationResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2TokenRevocationAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc7009#section-2.2[OAuth2 revocation response].
|
||||
<4> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc7009#section-2.2.1[OAuth2Error response].
|
||||
<1> `revocationRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc7009#section-2.1[OAuth2 revocation request] from `HttpServletRequest` to an instance of `OAuth2TokenRevocationAuthenticationToken`.
|
||||
<2> `revocationRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
|
||||
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2TokenRevocationAuthenticationToken`.
|
||||
<4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
|
||||
<5> `revocationResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2TokenRevocationAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc7009#section-2.2[OAuth2 revocation response].
|
||||
<6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc7009#section-2.2.1[OAuth2Error response].
|
||||
|
||||
`OAuth2TokenRevocationEndpointConfigurer` configures the `OAuth2TokenRevocationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
|
||||
`OAuth2TokenRevocationEndpointFilter` is the `Filter` that processes OAuth2 revocation requests.
|
||||
|
||||
`OAuth2TokenRevocationEndpointFilter` is configured with the following defaults:
|
||||
|
||||
* `*AuthenticationConverter*` -- An internal implementation that returns the `OAuth2TokenRevocationAuthenticationToken`.
|
||||
* `*AuthenticationConverter*` -- An `OAuth2TokenRevocationAuthenticationConverter`.
|
||||
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2TokenRevocationAuthenticationProvider`.
|
||||
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2TokenRevocationAuthenticationToken` and returns the OAuth2 revocation response.
|
||||
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.security.oauth2.server.authorization.config.annotati
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -32,6 +33,8 @@ import org.springframework.security.oauth2.server.authorization.authentication.O
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2AuthorizationEndpointFilter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.DelegatingAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeRequestAuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
@@ -52,8 +55,10 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2Configurer {
|
||||
private RequestMatcher requestMatcher;
|
||||
private AuthenticationConverter authorizationRequestConverter;
|
||||
private final List<AuthenticationConverter> authorizationRequestConverters = new ArrayList<>();
|
||||
private Consumer<List<AuthenticationConverter>> authorizationRequestConvertersConsumer = (authorizationRequestConverters) -> {};
|
||||
private final List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
|
||||
private Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer = (authenticationProviders) -> {};
|
||||
private AuthenticationSuccessHandler authorizationResponseHandler;
|
||||
private AuthenticationFailureHandler errorResponseHandler;
|
||||
private String consentPage;
|
||||
@@ -66,14 +71,31 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationConverter} used when attempting to extract an Authorization Request (or Consent) from {@link HttpServletRequest}
|
||||
* Adds an {@link AuthenticationConverter} used when attempting to extract an Authorization Request (or Consent) from {@link HttpServletRequest}
|
||||
* to an instance of {@link OAuth2AuthorizationCodeRequestAuthenticationToken} used for authenticating the request.
|
||||
*
|
||||
* @param authorizationRequestConverter the {@link AuthenticationConverter} used when attempting to extract an Authorization Request (or Consent) from {@link HttpServletRequest}
|
||||
* @param authorizationRequestConverter an {@link AuthenticationConverter} used when attempting to extract an Authorization Request (or Consent) from {@link HttpServletRequest}
|
||||
* @return the {@link OAuth2AuthorizationEndpointConfigurer} for further configuration
|
||||
*/
|
||||
public OAuth2AuthorizationEndpointConfigurer authorizationRequestConverter(AuthenticationConverter authorizationRequestConverter) {
|
||||
this.authorizationRequestConverter = authorizationRequestConverter;
|
||||
Assert.notNull(authorizationRequestConverter, "authorizationRequestConverter cannot be null");
|
||||
this.authorizationRequestConverters.add(authorizationRequestConverter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code Consumer} providing access to the {@code List} of default
|
||||
* and (optionally) added {@link #authorizationRequestConverter(AuthenticationConverter) AuthenticationConverter}'s
|
||||
* allowing the ability to add, remove, or customize a specific {@link AuthenticationConverter}.
|
||||
*
|
||||
* @param authorizationRequestConvertersConsumer the {@code Consumer} providing access to the {@code List} of default and (optionally) added {@link AuthenticationConverter}'s
|
||||
* @return the {@link OAuth2AuthorizationEndpointConfigurer} for further configuration
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public OAuth2AuthorizationEndpointConfigurer authorizationRequestConverters(
|
||||
Consumer<List<AuthenticationConverter>> authorizationRequestConvertersConsumer) {
|
||||
Assert.notNull(authorizationRequestConvertersConsumer, "authorizationRequestConvertersConsumer cannot be null");
|
||||
this.authorizationRequestConvertersConsumer = authorizationRequestConvertersConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -89,6 +111,22 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code Consumer} providing access to the {@code List} of default
|
||||
* and (optionally) added {@link #authenticationProvider(AuthenticationProvider) AuthenticationProvider}'s
|
||||
* allowing the ability to add, remove, or customize a specific {@link AuthenticationProvider}.
|
||||
*
|
||||
* @param authenticationProvidersConsumer the {@code Consumer} providing access to the {@code List} of default and (optionally) added {@link AuthenticationProvider}'s
|
||||
* @return the {@link OAuth2AuthorizationEndpointConfigurer} for further configuration
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public OAuth2AuthorizationEndpointConfigurer authenticationProviders(
|
||||
Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer) {
|
||||
Assert.notNull(authenticationProvidersConsumer, "authenticationProvidersConsumer cannot be null");
|
||||
this.authenticationProvidersConsumer = authenticationProvidersConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationSuccessHandler} used for handling an {@link OAuth2AuthorizationCodeRequestAuthenticationToken}
|
||||
* and returning the {@link OAuth2AuthorizationResponse Authorization Response}.
|
||||
@@ -158,10 +196,11 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
|
||||
authorizationServerSettings.getAuthorizationEndpoint(),
|
||||
HttpMethod.POST.name()));
|
||||
|
||||
List<AuthenticationProvider> authenticationProviders =
|
||||
!this.authenticationProviders.isEmpty() ?
|
||||
this.authenticationProviders :
|
||||
createDefaultAuthenticationProviders(httpSecurity);
|
||||
List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity);
|
||||
if (!this.authenticationProviders.isEmpty()) {
|
||||
authenticationProviders.addAll(0, this.authenticationProviders);
|
||||
}
|
||||
this.authenticationProvidersConsumer.accept(authenticationProviders);
|
||||
authenticationProviders.forEach(authenticationProvider ->
|
||||
httpSecurity.authenticationProvider(postProcess(authenticationProvider)));
|
||||
}
|
||||
@@ -175,9 +214,13 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
|
||||
new OAuth2AuthorizationEndpointFilter(
|
||||
authenticationManager,
|
||||
authorizationServerSettings.getAuthorizationEndpoint());
|
||||
if (this.authorizationRequestConverter != null) {
|
||||
authorizationEndpointFilter.setAuthenticationConverter(this.authorizationRequestConverter);
|
||||
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
|
||||
if (!this.authorizationRequestConverters.isEmpty()) {
|
||||
authenticationConverters.addAll(0, this.authorizationRequestConverters);
|
||||
}
|
||||
this.authorizationRequestConvertersConsumer.accept(authenticationConverters);
|
||||
authorizationEndpointFilter.setAuthenticationConverter(
|
||||
new DelegatingAuthenticationConverter(authenticationConverters));
|
||||
if (this.authorizationResponseHandler != null) {
|
||||
authorizationEndpointFilter.setAuthenticationSuccessHandler(this.authorizationResponseHandler);
|
||||
}
|
||||
@@ -195,7 +238,15 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
|
||||
return this.requestMatcher;
|
||||
}
|
||||
|
||||
private List<AuthenticationProvider> createDefaultAuthenticationProviders(HttpSecurity httpSecurity) {
|
||||
private static List<AuthenticationConverter> createDefaultAuthenticationConverters() {
|
||||
List<AuthenticationConverter> authenticationConverters = new ArrayList<>();
|
||||
|
||||
authenticationConverters.add(new OAuth2AuthorizationCodeRequestAuthenticationConverter());
|
||||
|
||||
return authenticationConverters;
|
||||
}
|
||||
|
||||
private static List<AuthenticationProvider> createDefaultAuthenticationProviders(HttpSecurity httpSecurity) {
|
||||
List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
|
||||
|
||||
OAuth2AuthorizationCodeRequestAuthenticationProvider authorizationCodeRequestAuthenticationProvider =
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.security.oauth2.server.authorization.config.annotati
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -36,6 +37,11 @@ import org.springframework.security.oauth2.server.authorization.authentication.P
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
|
||||
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2ClientAuthenticationFilter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.ClientSecretBasicAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.ClientSecretPostAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.DelegatingAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.JwtClientAssertionAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.PublicClientAuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
@@ -55,8 +61,10 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public final class OAuth2ClientAuthenticationConfigurer extends AbstractOAuth2Configurer {
|
||||
private RequestMatcher requestMatcher;
|
||||
private AuthenticationConverter authenticationConverter;
|
||||
private final List<AuthenticationConverter> authenticationConverters = new ArrayList<>();
|
||||
private Consumer<List<AuthenticationConverter>> authenticationConvertersConsumer = (authenticationConverters) -> {};
|
||||
private final List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
|
||||
private Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer = (authenticationProviders) -> {};
|
||||
private AuthenticationSuccessHandler authenticationSuccessHandler;
|
||||
private AuthenticationFailureHandler errorResponseHandler;
|
||||
|
||||
@@ -68,14 +76,31 @@ public final class OAuth2ClientAuthenticationConfigurer extends AbstractOAuth2Co
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationConverter} used when attempting to extract client credentials from {@link HttpServletRequest}
|
||||
* Adds an {@link AuthenticationConverter} used when attempting to extract client credentials from {@link HttpServletRequest}
|
||||
* to an instance of {@link OAuth2ClientAuthenticationToken} used for authenticating the client.
|
||||
*
|
||||
* @param authenticationConverter the {@link AuthenticationConverter} used when attempting to extract client credentials from {@link HttpServletRequest}
|
||||
* @param authenticationConverter an {@link AuthenticationConverter} used when attempting to extract client credentials from {@link HttpServletRequest}
|
||||
* @return the {@link OAuth2ClientAuthenticationConfigurer} for further configuration
|
||||
*/
|
||||
public OAuth2ClientAuthenticationConfigurer authenticationConverter(AuthenticationConverter authenticationConverter) {
|
||||
this.authenticationConverter = authenticationConverter;
|
||||
Assert.notNull(authenticationConverter, "authenticationConverter cannot be null");
|
||||
this.authenticationConverters.add(authenticationConverter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code Consumer} providing access to the {@code List} of default
|
||||
* and (optionally) added {@link #authenticationConverter(AuthenticationConverter) AuthenticationConverter}'s
|
||||
* allowing the ability to add, remove, or customize a specific {@link AuthenticationConverter}.
|
||||
*
|
||||
* @param authenticationConvertersConsumer the {@code Consumer} providing access to the {@code List} of default and (optionally) added {@link AuthenticationConverter}'s
|
||||
* @return the {@link OAuth2ClientAuthenticationConfigurer} for further configuration
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public OAuth2ClientAuthenticationConfigurer authenticationConverters(
|
||||
Consumer<List<AuthenticationConverter>> authenticationConvertersConsumer) {
|
||||
Assert.notNull(authenticationConvertersConsumer, "authenticationConvertersConsumer cannot be null");
|
||||
this.authenticationConvertersConsumer = authenticationConvertersConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -91,6 +116,22 @@ public final class OAuth2ClientAuthenticationConfigurer extends AbstractOAuth2Co
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code Consumer} providing access to the {@code List} of default
|
||||
* and (optionally) added {@link #authenticationProvider(AuthenticationProvider) AuthenticationProvider}'s
|
||||
* allowing the ability to add, remove, or customize a specific {@link AuthenticationProvider}.
|
||||
*
|
||||
* @param authenticationProvidersConsumer the {@code Consumer} providing access to the {@code List} of default and (optionally) added {@link AuthenticationProvider}'s
|
||||
* @return the {@link OAuth2ClientAuthenticationConfigurer} for further configuration
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public OAuth2ClientAuthenticationConfigurer authenticationProviders(
|
||||
Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer) {
|
||||
Assert.notNull(authenticationProvidersConsumer, "authenticationProvidersConsumer cannot be null");
|
||||
this.authenticationProvidersConsumer = authenticationProvidersConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationSuccessHandler} used for handling a successful client authentication
|
||||
* and associating the {@link OAuth2ClientAuthenticationToken} to the {@link SecurityContext}.
|
||||
@@ -129,10 +170,11 @@ public final class OAuth2ClientAuthenticationConfigurer extends AbstractOAuth2Co
|
||||
authorizationServerSettings.getTokenRevocationEndpoint(),
|
||||
HttpMethod.POST.name()));
|
||||
|
||||
List<AuthenticationProvider> authenticationProviders =
|
||||
!this.authenticationProviders.isEmpty() ?
|
||||
this.authenticationProviders :
|
||||
createDefaultAuthenticationProviders(httpSecurity);
|
||||
List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity);
|
||||
if (!this.authenticationProviders.isEmpty()) {
|
||||
authenticationProviders.addAll(0, this.authenticationProviders);
|
||||
}
|
||||
this.authenticationProvidersConsumer.accept(authenticationProviders);
|
||||
authenticationProviders.forEach(authenticationProvider ->
|
||||
httpSecurity.authenticationProvider(postProcess(authenticationProvider)));
|
||||
}
|
||||
@@ -142,9 +184,13 @@ public final class OAuth2ClientAuthenticationConfigurer extends AbstractOAuth2Co
|
||||
AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class);
|
||||
OAuth2ClientAuthenticationFilter clientAuthenticationFilter = new OAuth2ClientAuthenticationFilter(
|
||||
authenticationManager, this.requestMatcher);
|
||||
if (this.authenticationConverter != null) {
|
||||
clientAuthenticationFilter.setAuthenticationConverter(this.authenticationConverter);
|
||||
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
|
||||
if (!this.authenticationConverters.isEmpty()) {
|
||||
authenticationConverters.addAll(0, this.authenticationConverters);
|
||||
}
|
||||
this.authenticationConvertersConsumer.accept(authenticationConverters);
|
||||
clientAuthenticationFilter.setAuthenticationConverter(
|
||||
new DelegatingAuthenticationConverter(authenticationConverters));
|
||||
if (this.authenticationSuccessHandler != null) {
|
||||
clientAuthenticationFilter.setAuthenticationSuccessHandler(this.authenticationSuccessHandler);
|
||||
}
|
||||
@@ -159,7 +205,18 @@ public final class OAuth2ClientAuthenticationConfigurer extends AbstractOAuth2Co
|
||||
return this.requestMatcher;
|
||||
}
|
||||
|
||||
private List<AuthenticationProvider> createDefaultAuthenticationProviders(HttpSecurity httpSecurity) {
|
||||
private static List<AuthenticationConverter> createDefaultAuthenticationConverters() {
|
||||
List<AuthenticationConverter> authenticationConverters = new ArrayList<>();
|
||||
|
||||
authenticationConverters.add(new JwtClientAssertionAuthenticationConverter());
|
||||
authenticationConverters.add(new ClientSecretBasicAuthenticationConverter());
|
||||
authenticationConverters.add(new ClientSecretPostAuthenticationConverter());
|
||||
authenticationConverters.add(new PublicClientAuthenticationConverter());
|
||||
|
||||
return authenticationConverters;
|
||||
}
|
||||
|
||||
private static List<AuthenticationProvider> createDefaultAuthenticationProviders(HttpSecurity httpSecurity) {
|
||||
List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
|
||||
|
||||
RegisteredClientRepository registeredClientRepository = OAuth2ConfigurerUtils.getRegisteredClientRepository(httpSecurity);
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
package org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -39,6 +39,10 @@ import org.springframework.security.oauth2.server.authorization.authentication.O
|
||||
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.DelegatingAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2ClientCredentialsAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2RefreshTokenAuthenticationConverter;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
@@ -57,8 +61,10 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configurer {
|
||||
private RequestMatcher requestMatcher;
|
||||
private AuthenticationConverter accessTokenRequestConverter;
|
||||
private final List<AuthenticationProvider> authenticationProviders = new LinkedList<>();
|
||||
private final List<AuthenticationConverter> accessTokenRequestConverters = new ArrayList<>();
|
||||
private Consumer<List<AuthenticationConverter>> accessTokenRequestConvertersConsumer = (accessTokenRequestConverters) -> {};
|
||||
private final List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
|
||||
private Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer = (authenticationProviders) -> {};
|
||||
private AuthenticationSuccessHandler accessTokenResponseHandler;
|
||||
private AuthenticationFailureHandler errorResponseHandler;
|
||||
|
||||
@@ -70,14 +76,31 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationConverter} used when attempting to extract an Access Token Request from {@link HttpServletRequest}
|
||||
* Adds an {@link AuthenticationConverter} used when attempting to extract an Access Token Request from {@link HttpServletRequest}
|
||||
* to an instance of {@link OAuth2AuthorizationGrantAuthenticationToken} used for authenticating the authorization grant.
|
||||
*
|
||||
* @param accessTokenRequestConverter the {@link AuthenticationConverter} used when attempting to extract an Access Token Request from {@link HttpServletRequest}
|
||||
* @param accessTokenRequestConverter an {@link AuthenticationConverter} used when attempting to extract an Access Token Request from {@link HttpServletRequest}
|
||||
* @return the {@link OAuth2TokenEndpointConfigurer} for further configuration
|
||||
*/
|
||||
public OAuth2TokenEndpointConfigurer accessTokenRequestConverter(AuthenticationConverter accessTokenRequestConverter) {
|
||||
this.accessTokenRequestConverter = accessTokenRequestConverter;
|
||||
Assert.notNull(accessTokenRequestConverter, "accessTokenRequestConverter cannot be null");
|
||||
this.accessTokenRequestConverters.add(accessTokenRequestConverter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code Consumer} providing access to the {@code List} of default
|
||||
* and (optionally) added {@link #accessTokenRequestConverter(AuthenticationConverter) AuthenticationConverter}'s
|
||||
* allowing the ability to add, remove, or customize a specific {@link AuthenticationConverter}.
|
||||
*
|
||||
* @param accessTokenRequestConvertersConsumer the {@code Consumer} providing access to the {@code List} of default and (optionally) added {@link AuthenticationConverter}'s
|
||||
* @return the {@link OAuth2TokenEndpointConfigurer} for further configuration
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public OAuth2TokenEndpointConfigurer accessTokenRequestConverters(
|
||||
Consumer<List<AuthenticationConverter>> accessTokenRequestConvertersConsumer) {
|
||||
Assert.notNull(accessTokenRequestConvertersConsumer, "accessTokenRequestConvertersConsumer cannot be null");
|
||||
this.accessTokenRequestConvertersConsumer = accessTokenRequestConvertersConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -93,6 +116,22 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code Consumer} providing access to the {@code List} of default
|
||||
* and (optionally) added {@link #authenticationProvider(AuthenticationProvider) AuthenticationProvider}'s
|
||||
* allowing the ability to add, remove, or customize a specific {@link AuthenticationProvider}.
|
||||
*
|
||||
* @param authenticationProvidersConsumer the {@code Consumer} providing access to the {@code List} of default and (optionally) added {@link AuthenticationProvider}'s
|
||||
* @return the {@link OAuth2TokenEndpointConfigurer} for further configuration
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public OAuth2TokenEndpointConfigurer authenticationProviders(
|
||||
Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer) {
|
||||
Assert.notNull(authenticationProvidersConsumer, "authenticationProvidersConsumer cannot be null");
|
||||
this.authenticationProvidersConsumer = authenticationProvidersConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationSuccessHandler} used for handling an {@link OAuth2AccessTokenAuthenticationToken}
|
||||
* and returning the {@link OAuth2AccessTokenResponse Access Token Response}.
|
||||
@@ -123,10 +162,11 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure
|
||||
this.requestMatcher = new AntPathRequestMatcher(
|
||||
authorizationServerSettings.getTokenEndpoint(), HttpMethod.POST.name());
|
||||
|
||||
List<AuthenticationProvider> authenticationProviders =
|
||||
!this.authenticationProviders.isEmpty() ?
|
||||
this.authenticationProviders :
|
||||
createDefaultAuthenticationProviders(httpSecurity);
|
||||
List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity);
|
||||
if (!this.authenticationProviders.isEmpty()) {
|
||||
authenticationProviders.addAll(0, this.authenticationProviders);
|
||||
}
|
||||
this.authenticationProvidersConsumer.accept(authenticationProviders);
|
||||
authenticationProviders.forEach(authenticationProvider ->
|
||||
httpSecurity.authenticationProvider(postProcess(authenticationProvider)));
|
||||
}
|
||||
@@ -140,9 +180,13 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure
|
||||
new OAuth2TokenEndpointFilter(
|
||||
authenticationManager,
|
||||
authorizationServerSettings.getTokenEndpoint());
|
||||
if (this.accessTokenRequestConverter != null) {
|
||||
tokenEndpointFilter.setAuthenticationConverter(this.accessTokenRequestConverter);
|
||||
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
|
||||
if (!this.accessTokenRequestConverters.isEmpty()) {
|
||||
authenticationConverters.addAll(0, this.accessTokenRequestConverters);
|
||||
}
|
||||
this.accessTokenRequestConvertersConsumer.accept(authenticationConverters);
|
||||
tokenEndpointFilter.setAuthenticationConverter(
|
||||
new DelegatingAuthenticationConverter(authenticationConverters));
|
||||
if (this.accessTokenResponseHandler != null) {
|
||||
tokenEndpointFilter.setAuthenticationSuccessHandler(this.accessTokenResponseHandler);
|
||||
}
|
||||
@@ -157,7 +201,17 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure
|
||||
return this.requestMatcher;
|
||||
}
|
||||
|
||||
private List<AuthenticationProvider> createDefaultAuthenticationProviders(HttpSecurity httpSecurity) {
|
||||
private static List<AuthenticationConverter> createDefaultAuthenticationConverters() {
|
||||
List<AuthenticationConverter> authenticationConverters = new ArrayList<>();
|
||||
|
||||
authenticationConverters.add(new OAuth2AuthorizationCodeAuthenticationConverter());
|
||||
authenticationConverters.add(new OAuth2RefreshTokenAuthenticationConverter());
|
||||
authenticationConverters.add(new OAuth2ClientCredentialsAuthenticationConverter());
|
||||
|
||||
return authenticationConverters;
|
||||
}
|
||||
|
||||
private static List<AuthenticationProvider> createDefaultAuthenticationProviders(HttpSecurity httpSecurity) {
|
||||
List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
|
||||
|
||||
OAuth2AuthorizationService authorizationService = OAuth2ConfigurerUtils.getAuthorizationService(httpSecurity);
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
package org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -33,6 +33,8 @@ import org.springframework.security.oauth2.server.authorization.authentication.O
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenIntrospectionAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenIntrospectionEndpointFilter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.DelegatingAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2TokenIntrospectionAuthenticationConverter;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
@@ -45,14 +47,17 @@ import org.springframework.util.Assert;
|
||||
* Configurer for the OAuth 2.0 Token Introspection Endpoint.
|
||||
*
|
||||
* @author Gaurav Tiwari
|
||||
* @author Joe Grandja
|
||||
* @since 0.2.3
|
||||
* @see OAuth2AuthorizationServerConfigurer#tokenIntrospectionEndpoint(Customizer)
|
||||
* @see OAuth2TokenIntrospectionEndpointFilter
|
||||
*/
|
||||
public final class OAuth2TokenIntrospectionEndpointConfigurer extends AbstractOAuth2Configurer {
|
||||
private RequestMatcher requestMatcher;
|
||||
private AuthenticationConverter introspectionRequestConverter;
|
||||
private final List<AuthenticationProvider> authenticationProviders = new LinkedList<>();
|
||||
private final List<AuthenticationConverter> introspectionRequestConverters = new ArrayList<>();
|
||||
private Consumer<List<AuthenticationConverter>> introspectionRequestConvertersConsumer = (introspectionRequestConverters) -> {};
|
||||
private final List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
|
||||
private Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer = (authenticationProviders) -> {};
|
||||
private AuthenticationSuccessHandler introspectionResponseHandler;
|
||||
private AuthenticationFailureHandler errorResponseHandler;
|
||||
|
||||
@@ -64,14 +69,31 @@ public final class OAuth2TokenIntrospectionEndpointConfigurer extends AbstractOA
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationConverter} used when attempting to extract an Introspection Request from {@link HttpServletRequest}
|
||||
* Adds an {@link AuthenticationConverter} used when attempting to extract an Introspection Request from {@link HttpServletRequest}
|
||||
* to an instance of {@link OAuth2TokenIntrospectionAuthenticationToken} used for authenticating the request.
|
||||
*
|
||||
* @param introspectionRequestConverter the {@link AuthenticationConverter} used when attempting to extract an Introspection Request from {@link HttpServletRequest}
|
||||
* @param introspectionRequestConverter an {@link AuthenticationConverter} used when attempting to extract an Introspection Request from {@link HttpServletRequest}
|
||||
* @return the {@link OAuth2TokenIntrospectionEndpointConfigurer} for further configuration
|
||||
*/
|
||||
public OAuth2TokenIntrospectionEndpointConfigurer introspectionRequestConverter(AuthenticationConverter introspectionRequestConverter) {
|
||||
this.introspectionRequestConverter = introspectionRequestConverter;
|
||||
Assert.notNull(introspectionRequestConverter, "introspectionRequestConverter cannot be null");
|
||||
this.introspectionRequestConverters.add(introspectionRequestConverter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code Consumer} providing access to the {@code List} of default
|
||||
* and (optionally) added {@link #introspectionRequestConverter(AuthenticationConverter) AuthenticationConverter}'s
|
||||
* allowing the ability to add, remove, or customize a specific {@link AuthenticationConverter}.
|
||||
*
|
||||
* @param introspectionRequestConvertersConsumer the {@code Consumer} providing access to the {@code List} of default and (optionally) added {@link AuthenticationConverter}'s
|
||||
* @return the {@link OAuth2TokenIntrospectionEndpointConfigurer} for further configuration
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public OAuth2TokenIntrospectionEndpointConfigurer introspectionRequestConverters(
|
||||
Consumer<List<AuthenticationConverter>> introspectionRequestConvertersConsumer) {
|
||||
Assert.notNull(introspectionRequestConvertersConsumer, "introspectionRequestConvertersConsumer cannot be null");
|
||||
this.introspectionRequestConvertersConsumer = introspectionRequestConvertersConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -87,6 +109,22 @@ public final class OAuth2TokenIntrospectionEndpointConfigurer extends AbstractOA
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code Consumer} providing access to the {@code List} of default
|
||||
* and (optionally) added {@link #authenticationProvider(AuthenticationProvider) AuthenticationProvider}'s
|
||||
* allowing the ability to add, remove, or customize a specific {@link AuthenticationProvider}.
|
||||
*
|
||||
* @param authenticationProvidersConsumer the {@code Consumer} providing access to the {@code List} of default and (optionally) added {@link AuthenticationProvider}'s
|
||||
* @return the {@link OAuth2TokenIntrospectionEndpointConfigurer} for further configuration
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public OAuth2TokenIntrospectionEndpointConfigurer authenticationProviders(
|
||||
Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer) {
|
||||
Assert.notNull(authenticationProvidersConsumer, "authenticationProvidersConsumer cannot be null");
|
||||
this.authenticationProvidersConsumer = authenticationProvidersConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationSuccessHandler} used for handling an {@link OAuth2TokenIntrospectionAuthenticationToken}.
|
||||
*
|
||||
@@ -116,10 +154,11 @@ public final class OAuth2TokenIntrospectionEndpointConfigurer extends AbstractOA
|
||||
this.requestMatcher = new AntPathRequestMatcher(
|
||||
authorizationServerSettings.getTokenIntrospectionEndpoint(), HttpMethod.POST.name());
|
||||
|
||||
List<AuthenticationProvider> authenticationProviders =
|
||||
!this.authenticationProviders.isEmpty() ?
|
||||
this.authenticationProviders :
|
||||
createDefaultAuthenticationProviders(httpSecurity);
|
||||
List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity);
|
||||
if (!this.authenticationProviders.isEmpty()) {
|
||||
authenticationProviders.addAll(0, this.authenticationProviders);
|
||||
}
|
||||
this.authenticationProvidersConsumer.accept(authenticationProviders);
|
||||
authenticationProviders.forEach(authenticationProvider ->
|
||||
httpSecurity.authenticationProvider(postProcess(authenticationProvider)));
|
||||
}
|
||||
@@ -132,9 +171,13 @@ public final class OAuth2TokenIntrospectionEndpointConfigurer extends AbstractOA
|
||||
OAuth2TokenIntrospectionEndpointFilter introspectionEndpointFilter =
|
||||
new OAuth2TokenIntrospectionEndpointFilter(
|
||||
authenticationManager, authorizationServerSettings.getTokenIntrospectionEndpoint());
|
||||
if (this.introspectionRequestConverter != null) {
|
||||
introspectionEndpointFilter.setAuthenticationConverter(this.introspectionRequestConverter);
|
||||
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
|
||||
if (!this.introspectionRequestConverters.isEmpty()) {
|
||||
authenticationConverters.addAll(0, this.introspectionRequestConverters);
|
||||
}
|
||||
this.introspectionRequestConvertersConsumer.accept(authenticationConverters);
|
||||
introspectionEndpointFilter.setAuthenticationConverter(
|
||||
new DelegatingAuthenticationConverter(authenticationConverters));
|
||||
if (this.introspectionResponseHandler != null) {
|
||||
introspectionEndpointFilter.setAuthenticationSuccessHandler(this.introspectionResponseHandler);
|
||||
}
|
||||
@@ -149,7 +192,15 @@ public final class OAuth2TokenIntrospectionEndpointConfigurer extends AbstractOA
|
||||
return this.requestMatcher;
|
||||
}
|
||||
|
||||
private List<AuthenticationProvider> createDefaultAuthenticationProviders(HttpSecurity httpSecurity) {
|
||||
private static List<AuthenticationConverter> createDefaultAuthenticationConverters() {
|
||||
List<AuthenticationConverter> authenticationConverters = new ArrayList<>();
|
||||
|
||||
authenticationConverters.add(new OAuth2TokenIntrospectionAuthenticationConverter());
|
||||
|
||||
return authenticationConverters;
|
||||
}
|
||||
|
||||
private static List<AuthenticationProvider> createDefaultAuthenticationProviders(HttpSecurity httpSecurity) {
|
||||
List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
|
||||
|
||||
OAuth2TokenIntrospectionAuthenticationProvider tokenIntrospectionAuthenticationProvider =
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
package org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -32,6 +32,8 @@ import org.springframework.security.oauth2.server.authorization.authentication.O
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenRevocationAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenRevocationEndpointFilter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.DelegatingAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2TokenRevocationAuthenticationConverter;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
@@ -44,14 +46,17 @@ import org.springframework.util.Assert;
|
||||
* Configurer for the OAuth 2.0 Token Revocation Endpoint.
|
||||
*
|
||||
* @author Arfat Chaus
|
||||
* @author Joe Grandja
|
||||
* @since 0.2.2
|
||||
* @see OAuth2AuthorizationServerConfigurer#tokenRevocationEndpoint
|
||||
* @see OAuth2TokenRevocationEndpointFilter
|
||||
*/
|
||||
public final class OAuth2TokenRevocationEndpointConfigurer extends AbstractOAuth2Configurer {
|
||||
private RequestMatcher requestMatcher;
|
||||
private AuthenticationConverter revocationRequestConverter;
|
||||
private final List<AuthenticationProvider> authenticationProviders = new LinkedList<>();
|
||||
private final List<AuthenticationConverter> revocationRequestConverters = new ArrayList<>();
|
||||
private Consumer<List<AuthenticationConverter>> revocationRequestConvertersConsumer = (revocationRequestConverters) -> {};
|
||||
private final List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
|
||||
private Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer = (authenticationProviders) -> {};
|
||||
private AuthenticationSuccessHandler revocationResponseHandler;
|
||||
private AuthenticationFailureHandler errorResponseHandler;
|
||||
|
||||
@@ -63,14 +68,31 @@ public final class OAuth2TokenRevocationEndpointConfigurer extends AbstractOAuth
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationConverter} used when attempting to extract a Revoke Token Request from {@link HttpServletRequest}
|
||||
* to an instance of {@link OAuth2TokenRevocationAuthenticationToken} used for authenticating the client.
|
||||
* Adds an {@link AuthenticationConverter} used when attempting to extract a Revoke Token Request from {@link HttpServletRequest}
|
||||
* to an instance of {@link OAuth2TokenRevocationAuthenticationToken} used for authenticating the request.
|
||||
*
|
||||
* @param revocationRequestConverter the {@link AuthenticationConverter} used when attempting to extract client credentials from {@link HttpServletRequest}
|
||||
* @param revocationRequestConverter an {@link AuthenticationConverter} used when attempting to extract a Revoke Token Request from {@link HttpServletRequest}
|
||||
* @return the {@link OAuth2TokenRevocationEndpointConfigurer} for further configuration
|
||||
*/
|
||||
public OAuth2TokenRevocationEndpointConfigurer revocationRequestConverter(AuthenticationConverter revocationRequestConverter) {
|
||||
this.revocationRequestConverter = revocationRequestConverter;
|
||||
Assert.notNull(revocationRequestConverter, "revocationRequestConverter cannot be null");
|
||||
this.revocationRequestConverters.add(revocationRequestConverter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code Consumer} providing access to the {@code List} of default
|
||||
* and (optionally) added {@link #revocationRequestConverter(AuthenticationConverter) AuthenticationConverter}'s
|
||||
* allowing the ability to add, remove, or customize a specific {@link AuthenticationConverter}.
|
||||
*
|
||||
* @param revocationRequestConvertersConsumer the {@code Consumer} providing access to the {@code List} of default and (optionally) added {@link AuthenticationConverter}'s
|
||||
* @return the {@link OAuth2TokenRevocationEndpointConfigurer} for further configuration
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public OAuth2TokenRevocationEndpointConfigurer revocationRequestConverters(
|
||||
Consumer<List<AuthenticationConverter>> revocationRequestConvertersConsumer) {
|
||||
Assert.notNull(revocationRequestConvertersConsumer, "revocationRequestConvertersConsumer cannot be null");
|
||||
this.revocationRequestConvertersConsumer = revocationRequestConvertersConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -86,6 +108,22 @@ public final class OAuth2TokenRevocationEndpointConfigurer extends AbstractOAuth
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code Consumer} providing access to the {@code List} of default
|
||||
* and (optionally) added {@link #authenticationProvider(AuthenticationProvider) AuthenticationProvider}'s
|
||||
* allowing the ability to add, remove, or customize a specific {@link AuthenticationProvider}.
|
||||
*
|
||||
* @param authenticationProvidersConsumer the {@code Consumer} providing access to the {@code List} of default and (optionally) added {@link AuthenticationProvider}'s
|
||||
* @return the {@link OAuth2TokenRevocationEndpointConfigurer} for further configuration
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public OAuth2TokenRevocationEndpointConfigurer authenticationProviders(
|
||||
Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer) {
|
||||
Assert.notNull(authenticationProvidersConsumer, "authenticationProvidersConsumer cannot be null");
|
||||
this.authenticationProvidersConsumer = authenticationProvidersConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationSuccessHandler} used for handling an {@link OAuth2TokenRevocationAuthenticationToken}.
|
||||
*
|
||||
@@ -115,10 +153,11 @@ public final class OAuth2TokenRevocationEndpointConfigurer extends AbstractOAuth
|
||||
this.requestMatcher = new AntPathRequestMatcher(
|
||||
authorizationServerSettings.getTokenRevocationEndpoint(), HttpMethod.POST.name());
|
||||
|
||||
List<AuthenticationProvider> authenticationProviders =
|
||||
!this.authenticationProviders.isEmpty() ?
|
||||
this.authenticationProviders :
|
||||
createDefaultAuthenticationProviders(httpSecurity);
|
||||
List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity);
|
||||
if (!this.authenticationProviders.isEmpty()) {
|
||||
authenticationProviders.addAll(0, this.authenticationProviders);
|
||||
}
|
||||
this.authenticationProvidersConsumer.accept(authenticationProviders);
|
||||
authenticationProviders.forEach(authenticationProvider ->
|
||||
httpSecurity.authenticationProvider(postProcess(authenticationProvider)));
|
||||
}
|
||||
@@ -131,9 +170,13 @@ public final class OAuth2TokenRevocationEndpointConfigurer extends AbstractOAuth
|
||||
OAuth2TokenRevocationEndpointFilter revocationEndpointFilter =
|
||||
new OAuth2TokenRevocationEndpointFilter(
|
||||
authenticationManager, authorizationServerSettings.getTokenRevocationEndpoint());
|
||||
if (this.revocationRequestConverter != null) {
|
||||
revocationEndpointFilter.setAuthenticationConverter(this.revocationRequestConverter);
|
||||
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
|
||||
if (!this.revocationRequestConverters.isEmpty()) {
|
||||
authenticationConverters.addAll(0, this.revocationRequestConverters);
|
||||
}
|
||||
this.revocationRequestConvertersConsumer.accept(authenticationConverters);
|
||||
revocationEndpointFilter.setAuthenticationConverter(
|
||||
new DelegatingAuthenticationConverter(authenticationConverters));
|
||||
if (this.revocationResponseHandler != null) {
|
||||
revocationEndpointFilter.setAuthenticationSuccessHandler(this.revocationResponseHandler);
|
||||
}
|
||||
@@ -148,7 +191,15 @@ public final class OAuth2TokenRevocationEndpointConfigurer extends AbstractOAuth
|
||||
return this.requestMatcher;
|
||||
}
|
||||
|
||||
private List<AuthenticationProvider> createDefaultAuthenticationProviders(HttpSecurity httpSecurity) {
|
||||
private static List<AuthenticationConverter> createDefaultAuthenticationConverters() {
|
||||
List<AuthenticationConverter> authenticationConverters = new ArrayList<>();
|
||||
|
||||
authenticationConverters.add(new OAuth2TokenRevocationAuthenticationConverter());
|
||||
|
||||
return authenticationConverters;
|
||||
}
|
||||
|
||||
private static List<AuthenticationProvider> createDefaultAuthenticationProviders(HttpSecurity httpSecurity) {
|
||||
List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
|
||||
|
||||
OAuth2TokenRevocationAuthenticationProvider tokenRevocationAuthenticationProvider =
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
package org.springframework.security.oauth2.server.authorization.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
@@ -34,21 +32,18 @@ import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMessageConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenIntrospection;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenIntrospectionAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenIntrospectionAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.http.converter.OAuth2TokenIntrospectionHttpMessageConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2TokenIntrospectionAuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
@@ -70,8 +65,7 @@ public final class OAuth2TokenIntrospectionEndpointFilter extends OncePerRequest
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final RequestMatcher tokenIntrospectionEndpointMatcher;
|
||||
private AuthenticationConverter authenticationConverter =
|
||||
new DefaultTokenIntrospectionAuthenticationConverter();
|
||||
private AuthenticationConverter authenticationConverter;
|
||||
private final HttpMessageConverter<OAuth2TokenIntrospection> tokenIntrospectionHttpResponseConverter =
|
||||
new OAuth2TokenIntrospectionHttpMessageConverter();
|
||||
private final HttpMessageConverter<OAuth2Error> errorHttpResponseConverter = new OAuth2ErrorHttpMessageConverter();
|
||||
@@ -100,6 +94,7 @@ public final class OAuth2TokenIntrospectionEndpointFilter extends OncePerRequest
|
||||
this.authenticationManager = authenticationManager;
|
||||
this.tokenIntrospectionEndpointMatcher = new AntPathRequestMatcher(
|
||||
tokenIntrospectionEndpointUri, HttpMethod.POST.name());
|
||||
this.authenticationConverter = new OAuth2TokenIntrospectionAuthenticationConverter();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -175,47 +170,4 @@ public final class OAuth2TokenIntrospectionEndpointFilter extends OncePerRequest
|
||||
this.errorHttpResponseConverter.write(error, null, httpResponse);
|
||||
}
|
||||
|
||||
private static void throwError(String errorCode, String parameterName) {
|
||||
OAuth2Error error = new OAuth2Error(errorCode, "OAuth 2.0 Token Introspection Parameter: " + parameterName,
|
||||
"https://datatracker.ietf.org/doc/html/rfc7662#section-2.1");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
private static class DefaultTokenIntrospectionAuthenticationConverter
|
||||
implements AuthenticationConverter {
|
||||
|
||||
@Override
|
||||
public Authentication convert(HttpServletRequest request) {
|
||||
Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);
|
||||
|
||||
// token (REQUIRED)
|
||||
String token = parameters.getFirst(OAuth2ParameterNames.TOKEN);
|
||||
if (!StringUtils.hasText(token) ||
|
||||
parameters.get(OAuth2ParameterNames.TOKEN).size() != 1) {
|
||||
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.TOKEN);
|
||||
}
|
||||
|
||||
// token_type_hint (OPTIONAL)
|
||||
String tokenTypeHint = parameters.getFirst(OAuth2ParameterNames.TOKEN_TYPE_HINT);
|
||||
if (StringUtils.hasText(tokenTypeHint) &&
|
||||
parameters.get(OAuth2ParameterNames.TOKEN_TYPE_HINT).size() != 1) {
|
||||
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.TOKEN_TYPE_HINT);
|
||||
}
|
||||
|
||||
Map<String, Object> additionalParameters = new HashMap<>();
|
||||
parameters.forEach((key, value) -> {
|
||||
if (!key.equals(OAuth2ParameterNames.TOKEN) &&
|
||||
!key.equals(OAuth2ParameterNames.TOKEN_TYPE_HINT)) {
|
||||
additionalParameters.put(key, value.get(0));
|
||||
}
|
||||
});
|
||||
|
||||
return new OAuth2TokenIntrospectionAuthenticationToken(
|
||||
token, clientPrincipal, tokenTypeHint, additionalParameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,19 +32,16 @@ import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMessageConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenRevocationAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenRevocationAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2TokenRevocationAuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
@@ -66,8 +63,7 @@ public final class OAuth2TokenRevocationEndpointFilter extends OncePerRequestFil
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final RequestMatcher tokenRevocationEndpointMatcher;
|
||||
private AuthenticationConverter authenticationConverter =
|
||||
new DefaultTokenRevocationAuthenticationConverter();
|
||||
private AuthenticationConverter authenticationConverter;
|
||||
private final HttpMessageConverter<OAuth2Error> errorHttpResponseConverter =
|
||||
new OAuth2ErrorHttpMessageConverter();
|
||||
private AuthenticationSuccessHandler authenticationSuccessHandler = this::sendRevocationSuccessResponse;
|
||||
@@ -95,6 +91,7 @@ public final class OAuth2TokenRevocationEndpointFilter extends OncePerRequestFil
|
||||
this.authenticationManager = authenticationManager;
|
||||
this.tokenRevocationEndpointMatcher = new AntPathRequestMatcher(
|
||||
tokenRevocationEndpointUri, HttpMethod.POST.name());
|
||||
this.authenticationConverter = new OAuth2TokenRevocationAuthenticationConverter();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,9 +116,9 @@ public final class OAuth2TokenRevocationEndpointFilter extends OncePerRequestFil
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationConverter} used when attempting to extract a Revoke Token Request from {@link HttpServletRequest}
|
||||
* to an instance of {@link OAuth2TokenRevocationAuthenticationToken} used for authenticating the client.
|
||||
* to an instance of {@link OAuth2TokenRevocationAuthenticationToken} used for authenticating the request.
|
||||
*
|
||||
* @param authenticationConverter the {@link AuthenticationConverter} used when attempting to extract client credentials from {@link HttpServletRequest}
|
||||
* @param authenticationConverter the {@link AuthenticationConverter} used when attempting to extract a Revoke Token Request from {@link HttpServletRequest}
|
||||
* @since 0.2.2
|
||||
*/
|
||||
public void setAuthenticationConverter(AuthenticationConverter authenticationConverter) {
|
||||
@@ -164,36 +161,4 @@ public final class OAuth2TokenRevocationEndpointFilter extends OncePerRequestFil
|
||||
this.errorHttpResponseConverter.write(error, null, httpResponse);
|
||||
}
|
||||
|
||||
private static void throwError(String errorCode, String parameterName) {
|
||||
OAuth2Error error = new OAuth2Error(errorCode, "OAuth 2.0 Token Revocation Parameter: " + parameterName,
|
||||
"https://datatracker.ietf.org/doc/html/rfc7009#section-2.1");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
private static class DefaultTokenRevocationAuthenticationConverter
|
||||
implements AuthenticationConverter {
|
||||
|
||||
@Override
|
||||
public Authentication convert(HttpServletRequest request) {
|
||||
Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);
|
||||
|
||||
// token (REQUIRED)
|
||||
String token = parameters.getFirst(OAuth2ParameterNames.TOKEN);
|
||||
if (!StringUtils.hasText(token) ||
|
||||
parameters.get(OAuth2ParameterNames.TOKEN).size() != 1) {
|
||||
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.TOKEN);
|
||||
}
|
||||
|
||||
// token_type_hint (OPTIONAL)
|
||||
String tokenTypeHint = parameters.getFirst(OAuth2ParameterNames.TOKEN_TYPE_HINT);
|
||||
if (StringUtils.hasText(tokenTypeHint) &&
|
||||
parameters.get(OAuth2ParameterNames.TOKEN_TYPE_HINT).size() != 1) {
|
||||
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.TOKEN_TYPE_HINT);
|
||||
}
|
||||
|
||||
return new OAuth2TokenRevocationAuthenticationToken(token, clientPrincipal, tokenTypeHint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2020-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.oauth2.server.authorization.web.authentication;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenIntrospectionAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenIntrospectionEndpointFilter;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Attempts to extract an Introspection Request from {@link HttpServletRequest}
|
||||
* and then converts it to an {@link OAuth2TokenIntrospectionAuthenticationToken} used for authenticating the request.
|
||||
*
|
||||
* @author Gerardo Roza
|
||||
* @author Joe Grandja
|
||||
* @since 0.4.0
|
||||
* @see AuthenticationConverter
|
||||
* @see OAuth2TokenIntrospectionAuthenticationToken
|
||||
* @see OAuth2TokenIntrospectionEndpointFilter
|
||||
*/
|
||||
public final class OAuth2TokenIntrospectionAuthenticationConverter implements AuthenticationConverter {
|
||||
|
||||
@Override
|
||||
public Authentication convert(HttpServletRequest request) {
|
||||
Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);
|
||||
|
||||
// token (REQUIRED)
|
||||
String token = parameters.getFirst(OAuth2ParameterNames.TOKEN);
|
||||
if (!StringUtils.hasText(token) ||
|
||||
parameters.get(OAuth2ParameterNames.TOKEN).size() != 1) {
|
||||
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.TOKEN);
|
||||
}
|
||||
|
||||
// token_type_hint (OPTIONAL)
|
||||
String tokenTypeHint = parameters.getFirst(OAuth2ParameterNames.TOKEN_TYPE_HINT);
|
||||
if (StringUtils.hasText(tokenTypeHint) &&
|
||||
parameters.get(OAuth2ParameterNames.TOKEN_TYPE_HINT).size() != 1) {
|
||||
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.TOKEN_TYPE_HINT);
|
||||
}
|
||||
|
||||
Map<String, Object> additionalParameters = new HashMap<>();
|
||||
parameters.forEach((key, value) -> {
|
||||
if (!key.equals(OAuth2ParameterNames.TOKEN) &&
|
||||
!key.equals(OAuth2ParameterNames.TOKEN_TYPE_HINT)) {
|
||||
additionalParameters.put(key, value.get(0));
|
||||
}
|
||||
});
|
||||
|
||||
return new OAuth2TokenIntrospectionAuthenticationToken(
|
||||
token, clientPrincipal, tokenTypeHint, additionalParameters);
|
||||
}
|
||||
|
||||
private static void throwError(String errorCode, String parameterName) {
|
||||
OAuth2Error error = new OAuth2Error(errorCode, "OAuth 2.0 Token Introspection Parameter: " + parameterName,
|
||||
"https://datatracker.ietf.org/doc/html/rfc7662#section-2.1");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2020-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.oauth2.server.authorization.web.authentication;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenRevocationAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenRevocationEndpointFilter;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Attempts to extract a Revoke Token Request from {@link HttpServletRequest}
|
||||
* and then converts it to an {@link OAuth2TokenRevocationAuthenticationToken} used for authenticating the request.
|
||||
*
|
||||
* @author Vivek Babu
|
||||
* @author Joe Grandja
|
||||
* @since 0.4.0
|
||||
* @see AuthenticationConverter
|
||||
* @see OAuth2TokenRevocationAuthenticationToken
|
||||
* @see OAuth2TokenRevocationEndpointFilter
|
||||
*/
|
||||
public final class OAuth2TokenRevocationAuthenticationConverter implements AuthenticationConverter {
|
||||
|
||||
@Override
|
||||
public Authentication convert(HttpServletRequest request) {
|
||||
Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);
|
||||
|
||||
// token (REQUIRED)
|
||||
String token = parameters.getFirst(OAuth2ParameterNames.TOKEN);
|
||||
if (!StringUtils.hasText(token) ||
|
||||
parameters.get(OAuth2ParameterNames.TOKEN).size() != 1) {
|
||||
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.TOKEN);
|
||||
}
|
||||
|
||||
// token_type_hint (OPTIONAL)
|
||||
String tokenTypeHint = parameters.getFirst(OAuth2ParameterNames.TOKEN_TYPE_HINT);
|
||||
if (StringUtils.hasText(tokenTypeHint) &&
|
||||
parameters.get(OAuth2ParameterNames.TOKEN_TYPE_HINT).size() != 1) {
|
||||
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.TOKEN_TYPE_HINT);
|
||||
}
|
||||
|
||||
return new OAuth2TokenRevocationAuthenticationToken(token, clientPrincipal, tokenTypeHint);
|
||||
}
|
||||
|
||||
private static void throwError(String errorCode, String parameterName) {
|
||||
OAuth2Error error = new OAuth2Error(errorCode, "OAuth 2.0 Token Revocation Parameter: " + parameterName,
|
||||
"https://datatracker.ietf.org/doc/html/rfc7009#section-2.1");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -107,6 +107,7 @@ import org.springframework.security.oauth2.server.authorization.token.OAuth2Refr
|
||||
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenContext;
|
||||
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
|
||||
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeRequestAuthenticationConverter;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
@@ -165,7 +166,9 @@ public class OAuth2AuthorizationCodeGrantTests {
|
||||
private static HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter =
|
||||
new OAuth2AccessTokenResponseHttpMessageConverter();
|
||||
private static AuthenticationConverter authorizationRequestConverter;
|
||||
private static Consumer<List<AuthenticationConverter>> authorizationRequestConvertersConsumer;
|
||||
private static AuthenticationProvider authorizationRequestAuthenticationProvider;
|
||||
private static Consumer<List<AuthenticationProvider>> authorizationRequestAuthenticationProvidersConsumer;
|
||||
private static AuthenticationSuccessHandler authorizationResponseHandler;
|
||||
private static AuthenticationFailureHandler authorizationErrorResponseHandler;
|
||||
private static SecurityContextRepository securityContextRepository;
|
||||
@@ -202,7 +205,9 @@ public class OAuth2AuthorizationCodeGrantTests {
|
||||
.tokenEndpoint("/test/token")
|
||||
.build();
|
||||
authorizationRequestConverter = mock(AuthenticationConverter.class);
|
||||
authorizationRequestConvertersConsumer = mock(Consumer.class);
|
||||
authorizationRequestAuthenticationProvider = mock(AuthenticationProvider.class);
|
||||
authorizationRequestAuthenticationProvidersConsumer = mock(Consumer.class);
|
||||
authorizationResponseHandler = mock(AuthenticationSuccessHandler.class);
|
||||
authorizationErrorResponseHandler = mock(AuthenticationFailureHandler.class);
|
||||
securityContextRepository = spy(new HttpSessionSecurityContextRepository());
|
||||
@@ -638,7 +643,25 @@ public class OAuth2AuthorizationCodeGrantTests {
|
||||
.andExpect(status().isOk());
|
||||
|
||||
verify(authorizationRequestConverter).convert(any());
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<List<AuthenticationConverter>> authenticationConvertersCaptor = ArgumentCaptor.forClass(List.class);
|
||||
verify(authorizationRequestConvertersConsumer).accept(authenticationConvertersCaptor.capture());
|
||||
List<AuthenticationConverter> authenticationConverters = authenticationConvertersCaptor.getValue();
|
||||
assertThat(authenticationConverters).allMatch((converter) ->
|
||||
converter == authorizationRequestConverter ||
|
||||
converter instanceof OAuth2AuthorizationCodeRequestAuthenticationConverter);
|
||||
|
||||
verify(authorizationRequestAuthenticationProvider).authenticate(eq(authorizationCodeRequestAuthenticationResult));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<List<AuthenticationProvider>> authenticationProvidersCaptor = ArgumentCaptor.forClass(List.class);
|
||||
verify(authorizationRequestAuthenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture());
|
||||
List<AuthenticationProvider> authenticationProviders = authenticationProvidersCaptor.getValue();
|
||||
assertThat(authenticationProviders).allMatch((provider) ->
|
||||
provider == authorizationRequestAuthenticationProvider ||
|
||||
provider instanceof OAuth2AuthorizationCodeRequestAuthenticationProvider);
|
||||
|
||||
verify(authorizationResponseHandler).onAuthenticationSuccess(any(), any(), eq(authorizationCodeRequestAuthenticationResult));
|
||||
}
|
||||
|
||||
@@ -999,7 +1022,9 @@ public class OAuth2AuthorizationCodeGrantTests {
|
||||
.authorizationEndpoint(authorizationEndpoint ->
|
||||
authorizationEndpoint
|
||||
.authorizationRequestConverter(authorizationRequestConverter)
|
||||
.authorizationRequestConverters(authorizationRequestConvertersConsumer)
|
||||
.authenticationProvider(authorizationRequestAuthenticationProvider)
|
||||
.authenticationProviders(authorizationRequestAuthenticationProvidersConsumer)
|
||||
.authorizationResponseHandler(authorizationResponseHandler)
|
||||
.errorResponseHandler(authorizationErrorResponseHandler));
|
||||
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
|
||||
|
||||
@@ -21,6 +21,8 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -35,6 +37,7 @@ import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -60,9 +63,15 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.jose.TestJwks;
|
||||
import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.ClientSecretAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.JwtClientAssertionAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2RefreshTokenAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.PublicClientAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
|
||||
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||
@@ -73,6 +82,13 @@ import org.springframework.security.oauth2.server.authorization.jackson2.Testing
|
||||
import org.springframework.security.oauth2.server.authorization.test.SpringTestRule;
|
||||
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
|
||||
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.ClientSecretBasicAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.ClientSecretPostAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.JwtClientAssertionAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2ClientCredentialsAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2RefreshTokenAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.PublicClientAuthenticationConverter;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
@@ -81,6 +97,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -104,7 +121,9 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
private static JWKSource<SecurityContext> jwkSource;
|
||||
private static OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer;
|
||||
private static AuthenticationConverter authenticationConverter;
|
||||
private static Consumer<List<AuthenticationConverter>> authenticationConvertersConsumer;
|
||||
private static AuthenticationProvider authenticationProvider;
|
||||
private static Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer;
|
||||
private static AuthenticationSuccessHandler authenticationSuccessHandler;
|
||||
private static AuthenticationFailureHandler authenticationFailureHandler;
|
||||
|
||||
@@ -126,7 +145,9 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
|
||||
jwtCustomizer = mock(OAuth2TokenCustomizer.class);
|
||||
authenticationConverter = mock(AuthenticationConverter.class);
|
||||
authenticationConvertersConsumer = mock(Consumer.class);
|
||||
authenticationProvider = mock(AuthenticationProvider.class);
|
||||
authenticationProvidersConsumer = mock(Consumer.class);
|
||||
authenticationSuccessHandler = mock(AuthenticationSuccessHandler.class);
|
||||
authenticationFailureHandler = mock(AuthenticationFailureHandler.class);
|
||||
db = new EmbeddedDatabaseBuilder()
|
||||
@@ -143,7 +164,9 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
public void setup() {
|
||||
reset(jwtCustomizer);
|
||||
reset(authenticationConverter);
|
||||
reset(authenticationConvertersConsumer);
|
||||
reset(authenticationProvider);
|
||||
reset(authenticationProvidersConsumer);
|
||||
reset(authenticationSuccessHandler);
|
||||
reset(authenticationFailureHandler);
|
||||
}
|
||||
@@ -234,7 +257,29 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
.andExpect(status().isOk());
|
||||
|
||||
verify(authenticationConverter).convert(any());
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<List<AuthenticationConverter>> authenticationConvertersCaptor = ArgumentCaptor.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);
|
||||
|
||||
verify(authenticationProvider).authenticate(eq(clientCredentialsAuthentication));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<List<AuthenticationProvider>> authenticationProvidersCaptor = ArgumentCaptor.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);
|
||||
|
||||
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), eq(accessTokenAuthentication));
|
||||
}
|
||||
|
||||
@@ -246,19 +291,40 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
this.registeredClientRepository.save(registeredClient);
|
||||
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
registeredClient, new ClientAuthenticationMethod("custom"), null);
|
||||
when(authenticationConverter.convert(any())).thenReturn(clientPrincipal);
|
||||
when(authenticationProvider.supports(eq(OAuth2ClientAuthenticationToken.class))).thenReturn(true);
|
||||
when(authenticationProvider.authenticate(any())).thenReturn(clientPrincipal);
|
||||
|
||||
this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
|
||||
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
|
||||
.header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth(
|
||||
registeredClient.getClientId(), registeredClient.getClientSecret())))
|
||||
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
verify(authenticationConverter).convert(any());
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<List<AuthenticationConverter>> authenticationConvertersCaptor = ArgumentCaptor.forClass(List.class);
|
||||
verify(authenticationConvertersConsumer).accept(authenticationConvertersCaptor.capture());
|
||||
List<AuthenticationConverter> authenticationConverters = authenticationConvertersCaptor.getValue();
|
||||
assertThat(authenticationConverters).allMatch((converter) ->
|
||||
converter == authenticationConverter ||
|
||||
converter instanceof JwtClientAssertionAuthenticationConverter ||
|
||||
converter instanceof ClientSecretBasicAuthenticationConverter ||
|
||||
converter instanceof ClientSecretPostAuthenticationConverter ||
|
||||
converter instanceof PublicClientAuthenticationConverter);
|
||||
|
||||
verify(authenticationProvider).authenticate(eq(clientPrincipal));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<List<AuthenticationProvider>> authenticationProvidersCaptor = ArgumentCaptor.forClass(List.class);
|
||||
verify(authenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture());
|
||||
List<AuthenticationProvider> authenticationProviders = authenticationProvidersCaptor.getValue();
|
||||
assertThat(authenticationProviders).allMatch((provider) ->
|
||||
provider == authenticationProvider ||
|
||||
provider instanceof JwtClientAssertionAuthenticationProvider ||
|
||||
provider instanceof ClientSecretAuthenticationProvider ||
|
||||
provider instanceof PublicClientAuthenticationProvider);
|
||||
|
||||
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), eq(clientPrincipal));
|
||||
}
|
||||
|
||||
@@ -341,7 +407,9 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
.tokenEndpoint(tokenEndpoint ->
|
||||
tokenEndpoint
|
||||
.accessTokenRequestConverter(authenticationConverter)
|
||||
.accessTokenRequestConverters(authenticationConvertersConsumer)
|
||||
.authenticationProvider(authenticationProvider)
|
||||
.authenticationProviders(authenticationProvidersConsumer)
|
||||
.accessTokenResponseHandler(authenticationSuccessHandler)
|
||||
.errorResponseHandler(authenticationFailureHandler));
|
||||
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
|
||||
@@ -371,7 +439,9 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
.clientAuthentication(clientAuthentication ->
|
||||
clientAuthentication
|
||||
.authenticationConverter(authenticationConverter)
|
||||
.authenticationConverters(authenticationConvertersConsumer)
|
||||
.authenticationProvider(authenticationProvider)
|
||||
.authenticationProviders(authenticationProvidersConsumer)
|
||||
.authenticationSuccessHandler(authenticationSuccessHandler)
|
||||
.errorResponseHandler(authenticationFailureHandler));
|
||||
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
@@ -72,6 +73,7 @@ import org.springframework.security.oauth2.server.authorization.OAuth2TokenIntro
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
|
||||
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenIntrospectionAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenIntrospectionAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
|
||||
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
|
||||
@@ -88,6 +90,7 @@ import org.springframework.security.oauth2.server.authorization.test.SpringTestR
|
||||
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsContext;
|
||||
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsSet;
|
||||
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2TokenIntrospectionAuthenticationConverter;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
@@ -118,7 +121,9 @@ public class OAuth2TokenIntrospectionTests {
|
||||
private static AuthorizationServerSettings authorizationServerSettings;
|
||||
private static OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer;
|
||||
private static AuthenticationConverter authenticationConverter;
|
||||
private static Consumer<List<AuthenticationConverter>> authenticationConvertersConsumer;
|
||||
private static AuthenticationProvider authenticationProvider;
|
||||
private static Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer;
|
||||
private static AuthenticationSuccessHandler authenticationSuccessHandler;
|
||||
private static AuthenticationFailureHandler authenticationFailureHandler;
|
||||
private static final HttpMessageConverter<OAuth2TokenIntrospection> tokenIntrospectionHttpResponseConverter =
|
||||
@@ -145,7 +150,9 @@ public class OAuth2TokenIntrospectionTests {
|
||||
public static void init() {
|
||||
authorizationServerSettings = AuthorizationServerSettings.builder().tokenIntrospectionEndpoint("/test/introspect").build();
|
||||
authenticationConverter = mock(AuthenticationConverter.class);
|
||||
authenticationConvertersConsumer = mock(Consumer.class);
|
||||
authenticationProvider = mock(AuthenticationProvider.class);
|
||||
authenticationProvidersConsumer = mock(Consumer.class);
|
||||
authenticationSuccessHandler = mock(AuthenticationSuccessHandler.class);
|
||||
authenticationFailureHandler = mock(AuthenticationFailureHandler.class);
|
||||
accessTokenCustomizer = mock(OAuth2TokenCustomizer.class);
|
||||
@@ -364,7 +371,25 @@ public class OAuth2TokenIntrospectionTests {
|
||||
// @formatter:on
|
||||
|
||||
verify(authenticationConverter).convert(any());
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<List<AuthenticationConverter>> authenticationConvertersCaptor = ArgumentCaptor.forClass(List.class);
|
||||
verify(authenticationConvertersConsumer).accept(authenticationConvertersCaptor.capture());
|
||||
List<AuthenticationConverter> authenticationConverters = authenticationConvertersCaptor.getValue();
|
||||
assertThat(authenticationConverters).allMatch((converter) ->
|
||||
converter == authenticationConverter ||
|
||||
converter instanceof OAuth2TokenIntrospectionAuthenticationConverter);
|
||||
|
||||
verify(authenticationProvider).authenticate(eq(tokenIntrospectionAuthentication));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<List<AuthenticationProvider>> authenticationProvidersCaptor = ArgumentCaptor.forClass(List.class);
|
||||
verify(authenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture());
|
||||
List<AuthenticationProvider> authenticationProviders = authenticationProvidersCaptor.getValue();
|
||||
assertThat(authenticationProviders).allMatch((provider) ->
|
||||
provider == authenticationProvider ||
|
||||
provider instanceof OAuth2TokenIntrospectionAuthenticationProvider);
|
||||
|
||||
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), eq(tokenIntrospectionAuthentication));
|
||||
}
|
||||
|
||||
@@ -486,7 +511,9 @@ public class OAuth2TokenIntrospectionTests {
|
||||
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint ->
|
||||
tokenIntrospectionEndpoint
|
||||
.introspectionRequestConverter(authenticationConverter)
|
||||
.introspectionRequestConverters(authenticationConvertersConsumer)
|
||||
.authenticationProvider(authenticationProvider)
|
||||
.authenticationProviders(authenticationProvidersConsumer)
|
||||
.introspectionResponseHandler(authenticationSuccessHandler)
|
||||
.errorResponseHandler(authenticationFailureHandler));
|
||||
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.security.oauth2.server.authorization.config.annotati
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.nimbusds.jose.jwk.JWKSet;
|
||||
import com.nimbusds.jose.jwk.source.JWKSource;
|
||||
@@ -27,6 +29,7 @@ import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -56,6 +59,7 @@ import org.springframework.security.oauth2.server.authorization.OAuth2Authorizat
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
|
||||
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenRevocationAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenRevocationAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
|
||||
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
|
||||
@@ -65,6 +69,7 @@ import org.springframework.security.oauth2.server.authorization.client.TestRegis
|
||||
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
|
||||
import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
|
||||
import org.springframework.security.oauth2.server.authorization.test.SpringTestRule;
|
||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2TokenRevocationAuthenticationConverter;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
@@ -93,7 +98,9 @@ public class OAuth2TokenRevocationTests {
|
||||
private static EmbeddedDatabase db;
|
||||
private static JWKSource<SecurityContext> jwkSource;
|
||||
private static AuthenticationConverter authenticationConverter;
|
||||
private static Consumer<List<AuthenticationConverter>> authenticationConvertersConsumer;
|
||||
private static AuthenticationProvider authenticationProvider;
|
||||
private static Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer;
|
||||
private static AuthenticationSuccessHandler authenticationSuccessHandler;
|
||||
private static AuthenticationFailureHandler authenticationFailureHandler;
|
||||
|
||||
@@ -117,7 +124,9 @@ public class OAuth2TokenRevocationTests {
|
||||
JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
|
||||
jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
|
||||
authenticationConverter = mock(AuthenticationConverter.class);
|
||||
authenticationConvertersConsumer = mock(Consumer.class);
|
||||
authenticationProvider = mock(AuthenticationProvider.class);
|
||||
authenticationProvidersConsumer = mock(Consumer.class);
|
||||
authenticationSuccessHandler = mock(AuthenticationSuccessHandler.class);
|
||||
authenticationFailureHandler = mock(AuthenticationFailureHandler.class);
|
||||
db = new EmbeddedDatabaseBuilder()
|
||||
@@ -218,7 +227,25 @@ public class OAuth2TokenRevocationTests {
|
||||
.andExpect(status().isOk());
|
||||
|
||||
verify(authenticationConverter).convert(any());
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<List<AuthenticationConverter>> authenticationConvertersCaptor = ArgumentCaptor.forClass(List.class);
|
||||
verify(authenticationConvertersConsumer).accept(authenticationConvertersCaptor.capture());
|
||||
List<AuthenticationConverter> authenticationConverters = authenticationConvertersCaptor.getValue();
|
||||
assertThat(authenticationConverters).allMatch((converter) ->
|
||||
converter == authenticationConverter ||
|
||||
converter instanceof OAuth2TokenRevocationAuthenticationConverter);
|
||||
|
||||
verify(authenticationProvider).authenticate(eq(tokenRevocationAuthentication));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<List<AuthenticationProvider>> authenticationProvidersCaptor = ArgumentCaptor.forClass(List.class);
|
||||
verify(authenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture());
|
||||
List<AuthenticationProvider> authenticationProviders = authenticationProvidersCaptor.getValue();
|
||||
assertThat(authenticationProviders).allMatch((provider) ->
|
||||
provider == authenticationProvider ||
|
||||
provider instanceof OAuth2TokenRevocationAuthenticationProvider);
|
||||
|
||||
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), eq(tokenRevocationAuthentication));
|
||||
}
|
||||
|
||||
@@ -304,7 +331,9 @@ public class OAuth2TokenRevocationTests {
|
||||
.tokenRevocationEndpoint(tokenRevocationEndpoint ->
|
||||
tokenRevocationEndpoint
|
||||
.revocationRequestConverter(authenticationConverter)
|
||||
.revocationRequestConverters(authenticationConvertersConsumer)
|
||||
.authenticationProvider(authenticationProvider)
|
||||
.authenticationProviders(authenticationProvidersConsumer)
|
||||
.revocationResponseHandler(authenticationSuccessHandler)
|
||||
.errorResponseHandler(authenticationFailureHandler));
|
||||
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
|
||||
|
||||
Reference in New Issue
Block a user