Polish gh-929

This commit is contained in:
Joe Grandja
2022-10-27 16:33:42 -04:00
parent 8d7f8b3420
commit 2ba711c83a
5 changed files with 45 additions and 42 deletions

View File

@@ -271,7 +271,7 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h
`OidcUserInfoEndpointConfigurer` provides the ability to customize the https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[OpenID Connect 1.0 UserInfo endpoint].
It defines extension points that let you customize the https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse[UserInfo response].
`OidcUserInfoEndpointConfigurer` provides the following configuration option:
`OidcUserInfoEndpointConfigurer` provides the following configuration options:
[source,java]
----
@@ -303,8 +303,8 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h
<2> `userInfoRequestConverters()`: 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 `OidcUserInfoAuthenticationToken`.
<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`" `OidcUserInfoAuthenticationToken` and returning the https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse[UserInfo response].
<6> `userInfoResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://openid.net/specs/openid-connect-core-1_0.html#UserInfoError[UserInfo Error response].
<5> `userInfoResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OidcUserInfoAuthenticationToken` and returning the https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse[UserInfo response].
<6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://openid.net/specs/openid-connect-core-1_0.html#UserInfoError[UserInfo Error response].
<7> `userInfoMapper()`: The `Function` used to extract claims from `OidcUserInfoAuthenticationContext` to an instance of `OidcUserInfo`.
`OidcUserInfoEndpointConfigurer` configures the `OidcUserInfoEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
@@ -312,9 +312,9 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h
`OidcUserInfoEndpointFilter` is configured with the following defaults:
* `*AuthenticationConverter*` -- An internal implementation that obtains the `Authentication` from the `SecurityContext` and wraps the principal in an `OidcUserInfoAuthenticationToken`.
* `*AuthenticationConverter*` -- An internal implementation that obtains the `Authentication` from the `SecurityContext` and creates an `OidcUserInfoAuthenticationToken` with the principal.
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OidcUserInfoAuthenticationProvider`, which is associated with an internal implementation of `userInfoMapper` that extracts https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims[standard claims] from the https://openid.net/specs/openid-connect-core-1_0.html#IDToken[ID Token] based on the https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims[scopes requested] during authorization.
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OidcUserInfoAuthenticationToken` and returns the UserInfo response.
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OidcUserInfoAuthenticationToken` and returns the `OidcUserInfo` response.
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
[TIP]

View File

@@ -61,7 +61,7 @@ import org.springframework.util.Assert;
public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configurer {
private RequestMatcher requestMatcher;
private final List<AuthenticationConverter> userInfoRequestConverters = new ArrayList<>();
private Consumer<List<AuthenticationConverter>> userInfoRequestConvertersConsumer = (authenticationConverters) -> {};
private Consumer<List<AuthenticationConverter>> userInfoRequestConvertersConsumer = (userInfoRequestConverters) -> {};
private final List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
private Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer = (authenticationProviders) -> {};
private AuthenticationSuccessHandler userInfoResponseHandler;
@@ -76,10 +76,10 @@ public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configur
}
/**
* Sets the {@link AuthenticationConverter} used when attempting to extract the OAuth2 Access Token from {@link HttpServletRequest}
* to an instance of {@link OidcUserInfoAuthenticationToken} used for authenticating the User Info request.
* Adds an {@link AuthenticationConverter} used when attempting to extract an UserInfo Request from {@link HttpServletRequest}
* to an instance of {@link OidcUserInfoAuthenticationToken} used for authenticating the request.
*
* @param userInfoRequestConverter the {@link AuthenticationConverter} used when attempting to extract an OIDC User Info from {@link HttpServletRequest}
* @param userInfoRequestConverter an {@link AuthenticationConverter} used when attempting to extract an UserInfo Request from {@link HttpServletRequest}
* @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
* @since 0.4.0
*/
@@ -106,9 +106,9 @@ public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configur
}
/**
* Adds an {@link AuthenticationProvider} used for authenticating a type of {@link OidcUserInfoAuthenticationToken}.
* Adds an {@link AuthenticationProvider} used for authenticating an {@link OidcUserInfoAuthenticationToken}.
*
* @param authenticationProvider a {@link AuthenticationProvider} used for authenticating a type of {@link OidcUserInfoAuthenticationToken}
* @param authenticationProvider an {@link AuthenticationProvider} used for authenticating an {@link OidcUserInfoAuthenticationToken}
* @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
* @since 0.4.0
*/
@@ -135,8 +135,8 @@ public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configur
}
/**
* Sets the {@link AuthenticationSuccessHandler} used for handling an {@link OidcUserInfoAuthenticationToken} and
* returning the {@link OidcUserInfo User Info Response}.
* Sets the {@link AuthenticationSuccessHandler} used for handling an {@link OidcUserInfoAuthenticationToken}
* and returning the {@link OidcUserInfo UserInfo Response}.
*
* @param userInfoResponseHandler the {@link AuthenticationSuccessHandler} used for handling an {@link OidcUserInfoAuthenticationToken}
* @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
@@ -148,8 +148,8 @@ public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configur
}
/**
* Sets the {@link AuthenticationFailureHandler} used for handling an {@link OAuth2AuthenticationException} and
* returning the {@link OAuth2Error Error Response}.
* Sets the {@link AuthenticationFailureHandler} used for handling an {@link OAuth2AuthenticationException}
* and returning the {@link OAuth2Error Error Response}.
*
* @param errorResponseHandler the {@link AuthenticationFailureHandler} used for handling an {@link OAuth2AuthenticationException}
* @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
@@ -190,12 +190,10 @@ public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configur
new AntPathRequestMatcher(userInfoEndpointUri, HttpMethod.POST.name()));
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)));
}
@@ -232,20 +230,23 @@ public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configur
private static List<AuthenticationConverter> createDefaultAuthenticationConverters() {
List<AuthenticationConverter> authenticationConverters = new ArrayList<>();
authenticationConverters.add(
(request) -> {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return new OidcUserInfoAuthenticationToken(authentication);
}
);
return authenticationConverters;
}
private List<AuthenticationProvider> createDefaultAuthenticationProviders(HttpSecurity httpSecurity) {
List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
OidcUserInfoAuthenticationProvider oidcUserInfoAuthenticationProvider = new OidcUserInfoAuthenticationProvider(
OAuth2ConfigurerUtils.getAuthorizationService(httpSecurity));
OidcUserInfoAuthenticationProvider oidcUserInfoAuthenticationProvider =
new OidcUserInfoAuthenticationProvider(
OAuth2ConfigurerUtils.getAuthorizationService(httpSecurity));
if (this.userInfoMapper != null) {
oidcUserInfoAuthenticationProvider.setUserInfoMapper(this.userInfoMapper);
}

View File

@@ -35,6 +35,7 @@ import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMessageConverter;
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
import org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcUserInfoAuthenticationProvider;
import org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcUserInfoAuthenticationToken;
import org.springframework.security.oauth2.server.authorization.oidc.http.converter.OidcUserInfoHttpMessageConverter;
import org.springframework.security.web.authentication.AuthenticationConverter;
@@ -51,8 +52,10 @@ import org.springframework.web.filter.OncePerRequestFilter;
*
* @author Ido Salomon
* @author Steve Riesenberg
* @author Daniel Garnier-Moiroux
* @since 0.2.1
* @see OidcUserInfo
* @see OidcUserInfoAuthenticationProvider
* @see <a href="https://openid.net/specs/openid-connect-core-1_0.html#UserInfo">5.3. UserInfo Endpoint</a>
*/
public final class OidcUserInfoEndpointFilter extends OncePerRequestFilter {
@@ -64,14 +67,11 @@ public final class OidcUserInfoEndpointFilter extends OncePerRequestFilter {
private final AuthenticationManager authenticationManager;
private final RequestMatcher userInfoEndpointMatcher;
private AuthenticationConverter authenticationConverter = this::createAuthentication;
private final HttpMessageConverter<OidcUserInfo> userInfoHttpMessageConverter =
new OidcUserInfoHttpMessageConverter();
private final HttpMessageConverter<OAuth2Error> errorHttpResponseConverter =
new OAuth2ErrorHttpMessageConverter();
private AuthenticationConverter authenticationConverter = this::createAuthentication;
private AuthenticationSuccessHandler authenticationSuccessHandler = this::sendUserInfoResponse;
private AuthenticationFailureHandler authenticationFailureHandler = this::sendErrorResponse;
@@ -111,8 +111,8 @@ public final class OidcUserInfoEndpointFilter extends OncePerRequestFilter {
try {
Authentication userInfoAuthentication = this.authenticationConverter.convert(request);
OidcUserInfoAuthenticationToken userInfoAuthenticationResult =
(OidcUserInfoAuthenticationToken) this.authenticationManager.authenticate(userInfoAuthentication);
Authentication userInfoAuthenticationResult =
this.authenticationManager.authenticate(userInfoAuthentication);
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, userInfoAuthenticationResult);
} catch (OAuth2AuthenticationException ex) {
@@ -130,10 +130,10 @@ public final class OidcUserInfoEndpointFilter extends OncePerRequestFilter {
}
/**
* Sets the {@link AuthenticationConverter} used when attempting to extract the OAuth2 Access Token from {@link HttpServletRequest}
* to an instance of {@link OidcUserInfoAuthenticationToken} used for authenticating the User Info request.
* Sets the {@link AuthenticationConverter} used when attempting to extract an UserInfo Request from {@link HttpServletRequest}
* to an instance of {@link OidcUserInfoAuthenticationToken} used for authenticating the request.
*
* @param authenticationConverter the {@link AuthenticationConverter} used when attempting to extract an OIDC User Info from {@link HttpServletRequest}
* @param authenticationConverter the {@link AuthenticationConverter} used when attempting to extract an UserInfo Request from {@link HttpServletRequest}
* @since 0.4.0
*/
public void setAuthenticationConverter(AuthenticationConverter authenticationConverter) {
@@ -142,10 +142,10 @@ public final class OidcUserInfoEndpointFilter extends OncePerRequestFilter {
}
/**
* Sets the {@link AuthenticationSuccessHandler} used for handling an {@link OidcUserInfoAuthenticationToken} and
* returning the {@link OidcUserInfo OIDC User Info}.
* Sets the {@link AuthenticationSuccessHandler} used for handling an {@link OidcUserInfoAuthenticationToken}
* and returning the {@link OidcUserInfo UserInfo Response}.
*
* @param authenticationSuccessHandler the {@link AuthenticationSuccessHandler} for handling an {@link OidcUserInfoAuthenticationToken}
* @param authenticationSuccessHandler the {@link AuthenticationSuccessHandler} used for handling an {@link OidcUserInfoAuthenticationToken}
* @since 0.4.0
*/
public void setAuthenticationSuccessHandler(AuthenticationSuccessHandler authenticationSuccessHandler) {

View File

@@ -208,6 +208,7 @@ public class OidcUserInfoTests {
.header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken.getTokenValue()))
.andExpect(status().is2xxSuccessful());
// @formatter:on
verify(userInfoMapper).apply(any());
verify(authenticationConverter).convert(any());
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), any());
@@ -228,7 +229,7 @@ public class OidcUserInfoTests {
}
@Test
public void requestWhenUserInfoEndpointCustomizedThenAuthenticationProviderUsed() throws Exception {
public void requestWhenUserInfoEndpointCustomizedWithAuthenticationProviderThenUsed() throws Exception {
this.spring.register(CustomUserInfoConfiguration.class).autowire();
OAuth2Authorization authorization = createAuthorization();
@@ -247,6 +248,7 @@ public class OidcUserInfoTests {
.header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken.getTokenValue()))
.andExpect(status().is2xxSuccessful());
// @formatter:on
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), any());
verify(authenticationProvider).authenticate(any());
verifyNoInteractions(authenticationFailureHandler);
@@ -254,8 +256,9 @@ public class OidcUserInfoTests {
}
@Test
public void requestWhenUserInfoEndpointCustomizedAndErrorThenUsed() throws Exception {
public void requestWhenUserInfoEndpointCustomizedWithAuthenticationFailureHandlerThenUsed() throws Exception {
this.spring.register(CustomUserInfoConfiguration.class).autowire();
when(userInfoMapper.apply(any())).thenReturn(createUserInfo());
doAnswer(
invocation -> {
@@ -267,13 +270,12 @@ public class OidcUserInfoTests {
).when(authenticationFailureHandler).onAuthenticationFailure(any(), any(), any());
OAuth2AccessToken accessToken = createAuthorization().getAccessToken().getToken();
// @formatter:off
this.mvc.perform(get(DEFAULT_OIDC_USER_INFO_ENDPOINT_URI)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken.getTokenValue()))
.andExpect(status().is4xxClientError());
// @formatter:on
verify(authenticationFailureHandler).onAuthenticationFailure(any(), any(), any());
verifyNoInteractions(authenticationSuccessHandler);
verifyNoInteractions(userInfoMapper);

View File

@@ -88,21 +88,21 @@ public class OidcUserInfoEndpointFilterTests {
}
@Test
public void setAuthenticationConverterNullThenThrowIllegalArgumentException() {
public void setAuthenticationConverterWhenNullThenThrowIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.filter.setAuthenticationConverter(null))
.withMessage("authenticationConverter cannot be null");
}
@Test
public void setAuthenticationSuccessHandlerNullThenThrowIllegalArgumentException() {
public void setAuthenticationSuccessHandlerWhenNullThenThrowIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.filter.setAuthenticationSuccessHandler(null))
.withMessage("authenticationSuccessHandler cannot be null");
}
@Test
public void setAuthenticationFailureHandlerNullThenThrowIllegalArgumentException() {
public void setAuthenticationFailureHandlerWhenNullThenThrowIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.filter.setAuthenticationFailureHandler(null))
.withMessage("authenticationFailureHandler cannot be null");
@@ -201,7 +201,7 @@ public class OidcUserInfoEndpointFilterTests {
}
@Test
public void doFilterWhenCustomAuthenticationConverterThenUses() throws Exception {
public void doFilterWhenCustomAuthenticationConverterThenUsed() throws Exception {
Authentication principal = new TestingAuthenticationToken("principal", "credentials");
OidcUserInfoAuthenticationToken authentication = new OidcUserInfoAuthenticationToken(principal);
AuthenticationConverter authenticationConverter = mock(AuthenticationConverter.class);
@@ -220,13 +220,14 @@ public class OidcUserInfoEndpointFilterTests {
this.filter.doFilter(request, response, filterChain);
verifyNoInteractions(filterChain);
verify(authenticationConverter).convert(request);
verify(this.authenticationManager).authenticate(authentication);
assertUserInfoResponse(response.getContentAsString());
}
@Test
public void doFilterWhenCustomAuthenticationSuccessHandlerThenUses() throws Exception {
public void doFilterWhenCustomAuthenticationSuccessHandlerThenUsed() throws Exception {
AuthenticationSuccessHandler successHandler = mock(AuthenticationSuccessHandler.class);
this.filter.setAuthenticationSuccessHandler(successHandler);
@@ -249,7 +250,7 @@ public class OidcUserInfoEndpointFilterTests {
}
@Test
public void doFilterWhenCustomFailureHandlerThenUses() throws Exception {
public void doFilterWhenCustomAuthenticationFailureHandlerThenUsed() throws Exception {
AuthenticationFailureHandler failureHandler = mock(AuthenticationFailureHandler.class);
this.filter.setAuthenticationFailureHandler(failureHandler);
@@ -269,7 +270,6 @@ public class OidcUserInfoEndpointFilterTests {
this.filter.doFilter(request, response, filterChain);
verifyNoInteractions(filterChain);
verify(failureHandler).onAuthenticationFailure(request, response, authenticationException);
}