Polish gh-1068

Issue gh-1077
This commit is contained in:
Joe Grandja
2023-03-08 14:06:52 -05:00
parent 5b690dfb3a
commit 5f39c85264
24 changed files with 292 additions and 157 deletions

View File

@@ -282,7 +282,7 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
* Sets the {@link SessionRegistry} used to track OpenID Connect sessions.
*
* @param sessionRegistry the {@link SessionRegistry} used to track OpenID Connect sessions
* @since 1.1.0
* @since 1.1
*/
public void setSessionRegistry(SessionRegistry sessionRegistry) {
Assert.notNull(sessionRegistry, "sessionRegistry cannot be null");

View File

@@ -152,7 +152,7 @@ public class RegisteredClient implements Serializable {
* that the End-User's User Agent be redirected to after a logout has been performed.
*
* @return the {@code Set} of post logout redirect URI(s)
* @since 1.1.0
* @since 1.1
*/
public Set<String> getPostLogoutRedirectUris() {
return this.postLogoutRedirectUris;
@@ -447,7 +447,7 @@ public class RegisteredClient implements Serializable {
*
* @param postLogoutRedirectUri the post logout redirect URI
* @return the {@link Builder}
* @since 1.1.0
* @since 1.1
*/
public Builder postLogoutRedirectUri(String postLogoutRedirectUri) {
this.postLogoutRedirectUris.add(postLogoutRedirectUri);
@@ -460,7 +460,7 @@ public class RegisteredClient implements Serializable {
*
* @param postLogoutRedirectUrisConsumer a {@link Consumer} of the post logout redirect URI(s)
* @return the {@link Builder}
* @since 1.1.0
* @since 1.1
*/
public Builder postLogoutRedirectUris(Consumer<Set<String>> postLogoutRedirectUrisConsumer) {
postLogoutRedirectUrisConsumer.accept(this.postLogoutRedirectUris);

View File

@@ -23,14 +23,19 @@ import java.util.Map;
import com.nimbusds.jose.jwk.source.JWKSource;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.GenericApplicationListenerAdapter;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer;
import org.springframework.security.context.DelegatingApplicationListener;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.OAuth2Token;
@@ -270,7 +275,8 @@ public final class OAuth2AuthorizationServerConfigurer
if (isOidcEnabled()) {
// Add OpenID Connect session tracking capabilities.
SessionRegistry sessionRegistry = OAuth2ConfigurerUtils.getSessionRegistry(httpSecurity);
initSessionRegistry(httpSecurity);
SessionRegistry sessionRegistry = httpSecurity.getSharedObject(SessionRegistry.class);
OAuth2AuthorizationEndpointConfigurer authorizationEndpointConfigurer =
getConfigurer(OAuth2AuthorizationEndpointConfigurer.class);
authorizationEndpointConfigurer.setSessionAuthenticationStrategy((authentication, request, response) -> {
@@ -388,4 +394,23 @@ public final class OAuth2AuthorizationServerConfigurer
}
}
private static void initSessionRegistry(HttpSecurity httpSecurity) {
SessionRegistry sessionRegistry = OAuth2ConfigurerUtils.getOptionalBean(httpSecurity, SessionRegistry.class);
if (sessionRegistry == null) {
sessionRegistry = new SessionRegistryImpl();
registerDelegateApplicationListener(httpSecurity, (SessionRegistryImpl) sessionRegistry);
}
httpSecurity.setSharedObject(SessionRegistry.class, sessionRegistry);
}
private static void registerDelegateApplicationListener(HttpSecurity httpSecurity, ApplicationListener<?> delegate) {
DelegatingApplicationListener delegatingApplicationListener =
OAuth2ConfigurerUtils.getOptionalBean(httpSecurity, DelegatingApplicationListener.class);
if (delegatingApplicationListener == null) {
return;
}
SmartApplicationListener smartListener = new GenericApplicationListenerAdapter(delegate);
delegatingApplicationListener.addListener(smartListener);
}
}

View File

@@ -24,14 +24,8 @@ import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.GenericApplicationListenerAdapter;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.core.ResolvableType;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.context.DelegatingApplicationListener;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.oauth2.core.OAuth2Token;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
@@ -186,28 +180,6 @@ final class OAuth2ConfigurerUtils {
return authorizationServerSettings;
}
static SessionRegistry getSessionRegistry(HttpSecurity httpSecurity) {
SessionRegistry sessionRegistry = httpSecurity.getSharedObject(SessionRegistry.class);
if (sessionRegistry == null) {
sessionRegistry = getOptionalBean(httpSecurity, SessionRegistry.class);
if (sessionRegistry == null) {
sessionRegistry = new SessionRegistryImpl();
registerDelegateApplicationListener(httpSecurity, (SessionRegistryImpl) sessionRegistry);
}
httpSecurity.setSharedObject(SessionRegistry.class, sessionRegistry);
}
return sessionRegistry;
}
private static void registerDelegateApplicationListener(HttpSecurity httpSecurity, ApplicationListener<?> delegate) {
DelegatingApplicationListener delegatingApplicationListener = getOptionalBean(httpSecurity, DelegatingApplicationListener.class);
if (delegatingApplicationListener == null) {
return;
}
SmartApplicationListener smartListener = new GenericApplicationListenerAdapter(delegate);
delegatingApplicationListener.addListener(smartListener);
}
static <T> T getBean(HttpSecurity httpSecurity, Class<T> type) {
return httpSecurity.getSharedObject(ApplicationContext.class).getBean(type);
}

View File

@@ -220,11 +220,13 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure
OAuth2AuthorizationService authorizationService = OAuth2ConfigurerUtils.getAuthorizationService(httpSecurity);
OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator = OAuth2ConfigurerUtils.getTokenGenerator(httpSecurity);
SessionRegistry sessionRegistry = OAuth2ConfigurerUtils.getSessionRegistry(httpSecurity);
OAuth2AuthorizationCodeAuthenticationProvider authorizationCodeAuthenticationProvider =
new OAuth2AuthorizationCodeAuthenticationProvider(authorizationService, tokenGenerator);
authorizationCodeAuthenticationProvider.setSessionRegistry(sessionRegistry);
SessionRegistry sessionRegistry = httpSecurity.getSharedObject(SessionRegistry.class);
if (sessionRegistry != null) {
authorizationCodeAuthenticationProvider.setSessionRegistry(sessionRegistry);
}
authenticationProviders.add(authorizationCodeAuthenticationProvider);
OAuth2RefreshTokenAuthenticationProvider refreshTokenAuthenticationProvider =

View File

@@ -72,7 +72,7 @@ public final class OidcConfigurer extends AbstractOAuth2Configurer {
*
* @param logoutEndpointCustomizer the {@link Customizer} providing access to the {@link OidcLogoutEndpointConfigurer}
* @return the {@link OidcConfigurer} for further configuration
* @since 1.1.0
* @since 1.1
*/
public OidcConfigurer logoutEndpoint(Customizer<OidcLogoutEndpointConfigurer> logoutEndpointCustomizer) {
logoutEndpointCustomizer.customize(getConfigurer(OidcLogoutEndpointConfigurer.class));

View File

@@ -26,6 +26,7 @@ import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcLogoutAuthenticationProvider;
@@ -47,7 +48,7 @@ import org.springframework.util.Assert;
* Configurer for OpenID Connect 1.0 RP-Initiated Logout Endpoint.
*
* @author Joe Grandja
* @since 1.1.0
* @since 1.1
* @see OidcConfigurer#logoutEndpoint
* @see OidcLogoutEndpointFilter
*/
@@ -210,7 +211,7 @@ public final class OidcLogoutEndpointConfigurer extends AbstractOAuth2Configurer
new OidcLogoutAuthenticationProvider(
OAuth2ConfigurerUtils.getRegisteredClientRepository(httpSecurity),
OAuth2ConfigurerUtils.getAuthorizationService(httpSecurity),
OAuth2ConfigurerUtils.getSessionRegistry(httpSecurity));
httpSecurity.getSharedObject(SessionRegistry.class));
authenticationProviders.add(oidcLogoutAuthenticationProvider);
return authenticationProviders;

View File

@@ -101,7 +101,7 @@ public interface OidcClientMetadataClaimAccessor extends ClaimAccessor {
* that the End-User's User Agent be redirected to after a logout has been performed.
*
* @return the post logout redirection {@code URI} values used by the Client
* @since 1.1.0
* @since 1.1
*/
default List<String> getPostLogoutRedirectUris() {
return getClaimAsStringList(OidcClientMetadataClaimNames.POST_LOGOUT_REDIRECT_URIS);

View File

@@ -66,7 +66,7 @@ public final class OidcClientMetadataClaimNames {
* {@code post_logout_redirect_uris} - the post logout redirection {@code URI} values used by the Client.
* The {@code post_logout_redirect_uri} parameter is used by the client when requesting
* that the End-User's User Agent be redirected to after a logout has been performed.
* @since 1.1.0
* @since 1.1
*/
public static final String POST_LOGOUT_REDIRECT_URIS = "post_logout_redirect_uris";

View File

@@ -176,7 +176,7 @@ public final class OidcClientRegistration implements OidcClientMetadataClaimAcce
*
* @param postLogoutRedirectUri the post logout redirection {@code URI} used by the Client
* @return the {@link Builder} for further configuration
* @since 1.1.0
* @since 1.1
*/
public Builder postLogoutRedirectUri(String postLogoutRedirectUri) {
addClaimToClaimList(OidcClientMetadataClaimNames.POST_LOGOUT_REDIRECT_URIS, postLogoutRedirectUri);
@@ -189,7 +189,7 @@ public final class OidcClientRegistration implements OidcClientMetadataClaimAcce
*
* @param postLogoutRedirectUrisConsumer a {@code Consumer} of the post logout redirection {@code URI} values used by the Client
* @return the {@link Builder} for further configuration
* @since 1.1.0
* @since 1.1
*/
public Builder postLogoutRedirectUris(Consumer<List<String>> postLogoutRedirectUrisConsumer) {
acceptClaimValues(OidcClientMetadataClaimNames.POST_LOGOUT_REDIRECT_URIS, postLogoutRedirectUrisConsumer);

View File

@@ -136,7 +136,7 @@ public final class OidcProviderConfiguration extends AbstractOAuth2Authorization
*
* @param endSessionEndpoint the {@code URL} of the OpenID Connect 1.0 End Session Endpoint
* @return the {@link Builder} for further configuration
* @since 1.1.0
* @since 1.1
*/
public Builder endSessionEndpoint(String endSessionEndpoint) {
return claim(OidcProviderMetadataClaimNames.END_SESSION_ENDPOINT, endSessionEndpoint);

View File

@@ -72,7 +72,7 @@ public interface OidcProviderMetadataClaimAccessor extends OAuth2AuthorizationSe
* Returns the {@code URL} of the OpenID Connect 1.0 End Session Endpoint {@code (end_session_endpoint)}.
*
* @return the {@code URL} of the OpenID Connect 1.0 End Session Endpoint
* @since 1.1.0
* @since 1.1
*/
default URL getEndSessionEndpoint() {
return getClaimAsURL(OidcProviderMetadataClaimNames.END_SESSION_ENDPOINT);

View File

@@ -49,7 +49,7 @@ public final class OidcProviderMetadataClaimNames extends OAuth2AuthorizationSer
/**
* {@code end_session_endpoint} - the {@code URL} of the OpenID Connect 1.0 End Session Endpoint
* @since 1.1.0
* @since 1.1
*/
public static final String END_SESSION_ENDPOINT = "end_session_endpoint";

View File

@@ -46,7 +46,7 @@ import org.springframework.util.StringUtils;
* An {@link AuthenticationProvider} implementation for OpenID Connect 1.0 RP-Initiated Logout Endpoint.
*
* @author Joe Grandja
* @since 1.1.0
* @since 1.1
* @see RegisteredClientRepository
* @see OAuth2AuthorizationService
* @see SessionRegistry
@@ -83,7 +83,7 @@ public final class OidcLogoutAuthenticationProvider implements AuthenticationPro
(OidcLogoutAuthenticationToken) authentication;
OAuth2Authorization authorization = this.authorizationService.findByToken(
oidcLogoutAuthentication.getIdToken(), ID_TOKEN_TOKEN_TYPE);
oidcLogoutAuthentication.getIdTokenHint(), ID_TOKEN_TOKEN_TYPE);
if (authorization == null) {
throwError(OAuth2ErrorCodes.INVALID_TOKEN, "id_token_hint");
}
@@ -120,18 +120,24 @@ public final class OidcLogoutAuthenticationProvider implements AuthenticationPro
this.logger.trace("Validated logout request parameters");
}
// Validate user session
SessionInformation sessionInformation = null;
// Validate user identity
Authentication userPrincipal = (Authentication) oidcLogoutAuthentication.getPrincipal();
if (isPrincipalAuthenticated(userPrincipal) &&
StringUtils.hasText(oidcLogoutAuthentication.getSessionId())) {
sessionInformation = findSessionInformation(
userPrincipal, oidcLogoutAuthentication.getSessionId());
if (sessionInformation != null) {
String sidClaim = idToken.getClaim("sid");
if (!StringUtils.hasText(sidClaim) ||
!sidClaim.equals(sessionInformation.getSessionId())) {
throwError(OAuth2ErrorCodes.INVALID_TOKEN, "sid");
if (isPrincipalAuthenticated(userPrincipal)) {
if (!StringUtils.hasText(idToken.getSubject()) ||
!idToken.getSubject().equals(userPrincipal.getName())) {
throwError(OAuth2ErrorCodes.INVALID_TOKEN, IdTokenClaimNames.SUB);
}
// Check for active session
if (StringUtils.hasText(oidcLogoutAuthentication.getSessionId())) {
SessionInformation sessionInformation = findSessionInformation(
userPrincipal, oidcLogoutAuthentication.getSessionId());
if (sessionInformation != null) {
String sidClaim = idToken.getClaim("sid");
if (!StringUtils.hasText(sidClaim) ||
!sidClaim.equals(sessionInformation.getSessionId())) {
throwError(OAuth2ErrorCodes.INVALID_TOKEN, "sid");
}
}
}
}
@@ -140,8 +146,8 @@ public final class OidcLogoutAuthenticationProvider implements AuthenticationPro
this.logger.trace("Authenticated logout request");
}
return new OidcLogoutAuthenticationToken(oidcLogoutAuthentication.getIdToken(), userPrincipal,
sessionInformation, oidcLogoutAuthentication.getClientId(),
return new OidcLogoutAuthenticationToken(idToken, userPrincipal,
oidcLogoutAuthentication.getSessionId(), oidcLogoutAuthentication.getClientId(),
oidcLogoutAuthentication.getPostLogoutRedirectUri(), oidcLogoutAuthentication.getState());
}

View File

@@ -20,7 +20,7 @@ import java.util.Collections;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
import org.springframework.security.oauth2.server.authorization.util.SpringAuthorizationServerVersion;
import org.springframework.util.Assert;
@@ -28,16 +28,16 @@ import org.springframework.util.Assert;
* An {@link Authentication} implementation used for OpenID Connect 1.0 RP-Initiated Logout Endpoint.
*
* @author Joe Grandja
* @since 1.1.0
* @since 1.1
* @see AbstractAuthenticationToken
* @see OidcLogoutAuthenticationProvider
*/
public class OidcLogoutAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = SpringAuthorizationServerVersion.SERIAL_VERSION_UID;
private final String idToken;
private final String idTokenHint;
private final OidcIdToken idToken;
private final Authentication principal;
private final String sessionId;
private final SessionInformation sessionInformation;
private final String clientId;
private final String postLogoutRedirectUri;
private final String state;
@@ -45,22 +45,22 @@ public class OidcLogoutAuthenticationToken extends AbstractAuthenticationToken {
/**
* Constructs an {@code OidcLogoutAuthenticationToken} using the provided parameters.
*
* @param idToken the ID Token previously issued by the Provider to the Client and used as a hint about the End-User's current authenticated session with the Client
* @param idTokenHint the ID Token previously issued by the Provider to the Client and used as a hint about the End-User's current authenticated session with the Client
* @param principal the authenticated principal representing the End-User
* @param sessionId the End-User's current authenticated session identifier with the Client
* @param sessionId the End-User's current authenticated session identifier with the Provider
* @param clientId the client identifier the ID Token was issued to
* @param postLogoutRedirectUri the URI which the Client is requesting that the End-User's User Agent be redirected to after a logout has been performed
* @param state the opaque value used by the Client to maintain state between the logout request and the callback to the {@code postLogoutRedirectUri}
*/
public OidcLogoutAuthenticationToken(String idToken, Authentication principal, @Nullable String sessionId,
public OidcLogoutAuthenticationToken(String idTokenHint, Authentication principal, @Nullable String sessionId,
@Nullable String clientId, @Nullable String postLogoutRedirectUri, @Nullable String state) {
super(Collections.emptyList());
Assert.hasText(idToken, "idToken cannot be empty");
Assert.hasText(idTokenHint, "idTokenHint cannot be empty");
Assert.notNull(principal, "principal cannot be null");
this.idToken = idToken;
this.idTokenHint = idTokenHint;
this.idToken = null;
this.principal = principal;
this.sessionId = sessionId;
this.sessionInformation = null;
this.clientId = clientId;
this.postLogoutRedirectUri = postLogoutRedirectUri;
this.state = state;
@@ -70,22 +70,22 @@ public class OidcLogoutAuthenticationToken extends AbstractAuthenticationToken {
/**
* Constructs an {@code OidcLogoutAuthenticationToken} using the provided parameters.
*
* @param idToken the ID Token previously issued by the Provider to the Client and used as a hint about the End-User's current authenticated session with the Client
* @param idToken the ID Token previously issued by the Provider to the Client
* @param principal the authenticated principal representing the End-User
* @param sessionInformation the End-User's current authenticated session information with the Client
* @param sessionId the End-User's current authenticated session identifier with the Provider
* @param clientId the client identifier the ID Token was issued to
* @param postLogoutRedirectUri the URI which the Client is requesting that the End-User's User Agent be redirected to after a logout has been performed
* @param state the opaque value used by the Client to maintain state between the logout request and the callback to the {@code postLogoutRedirectUri}
*/
public OidcLogoutAuthenticationToken(String idToken, Authentication principal, @Nullable SessionInformation sessionInformation,
public OidcLogoutAuthenticationToken(OidcIdToken idToken, Authentication principal, @Nullable String sessionId,
@Nullable String clientId, @Nullable String postLogoutRedirectUri, @Nullable String state) {
super(Collections.emptyList());
Assert.hasText(idToken, "idToken cannot be empty");
Assert.notNull(idToken, "idToken cannot be null");
Assert.notNull(principal, "principal cannot be null");
this.idTokenHint = idToken.getTokenValue();
this.idToken = idToken;
this.principal = principal;
this.sessionId = sessionInformation != null ? sessionInformation.getSessionId() : null;
this.sessionInformation = sessionInformation;
this.sessionId = sessionId;
this.clientId = clientId;
this.postLogoutRedirectUri = postLogoutRedirectUri;
this.state = state;
@@ -95,7 +95,7 @@ public class OidcLogoutAuthenticationToken extends AbstractAuthenticationToken {
/**
* Returns the authenticated principal representing the End-User.
*
* @return the authenticated principal
* @return the authenticated principal representing the End-User
*/
@Override
public Object getPrincipal() {
@@ -113,30 +113,30 @@ public class OidcLogoutAuthenticationToken extends AbstractAuthenticationToken {
*
* @return the ID Token previously issued by the Provider to the Client
*/
public String getIdToken() {
public String getIdTokenHint() {
return this.idTokenHint;
}
/**
* Returns the ID Token previously issued by the Provider to the Client.
*
* @return the ID Token previously issued by the Provider to the Client
*/
@Nullable
public OidcIdToken getIdToken() {
return this.idToken;
}
/**
* Returns the End-User's current authenticated session identifier with the Client.
* Returns the End-User's current authenticated session identifier with the Provider.
*
* @return the End-User's current authenticated session identifier
* @return the End-User's current authenticated session identifier with the Provider
*/
@Nullable
public String getSessionId() {
return this.sessionId;
}
/**
* Returns the End-User's current authenticated session information with the Client.
*
* @return the End-User's current authenticated session information
*/
@Nullable
public SessionInformation getSessionInformation() {
return this.sessionInformation;
}
/**
* Returns the client identifier the ID Token was issued to.
*

View File

@@ -26,6 +26,7 @@ import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.log.LogMessage;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
@@ -58,7 +59,7 @@ import org.springframework.web.util.UriUtils;
* A {@code Filter} that processes OpenID Connect 1.0 RP-Initiated Logout Requests.
*
* @author Joe Grandja
* @since 1.1.0
* @since 1.1
* @see OidcLogoutAuthenticationConverter
* @see OidcLogoutAuthenticationProvider
* @see <a href="https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout">2. RP-Initiated Logout</a>
@@ -182,7 +183,7 @@ public final class OidcLogoutEndpointFilter extends OncePerRequestFilter {
OidcLogoutAuthenticationToken oidcLogoutAuthentication = (OidcLogoutAuthenticationToken) authentication;
// Check for active user session
if (oidcLogoutAuthentication.getSessionInformation() != null) {
if (isSessionActive(oidcLogoutAuthentication)) {
// Perform logout
this.logoutHandler.logout(request, response,
(Authentication) oidcLogoutAuthentication.getPrincipal());
@@ -215,4 +216,15 @@ public final class OidcLogoutEndpointFilter extends OncePerRequestFilter {
response.sendError(HttpStatus.BAD_REQUEST.value(), error.toString());
}
private static boolean isSessionActive(OidcLogoutAuthenticationToken oidcLogoutAuthentication) {
return isPrincipalAuthenticated((Authentication) oidcLogoutAuthentication.getPrincipal()) &&
StringUtils.hasText(oidcLogoutAuthentication.getSessionId());
}
private static boolean isPrincipalAuthenticated(Authentication principal) {
return principal != null &&
!AnonymousAuthenticationToken.class.isAssignableFrom(principal.getClass()) &&
principal.isAuthenticated();
}
}

View File

@@ -40,7 +40,7 @@ import org.springframework.util.StringUtils;
* and then converts to an {@link OidcLogoutAuthenticationToken} used for authenticating the request.
*
* @author Joe Grandja
* @since 1.1.0
* @since 1.1
* @see AuthenticationConverter
* @see OidcLogoutAuthenticationToken
* @see OidcLogoutEndpointFilter

View File

@@ -130,7 +130,7 @@ public final class AuthorizationServerSettings extends AbstractSettings {
* Returns the OpenID Connect 1.0 Logout endpoint. The default is {@code /connect/logout}.
*
* @return the OpenID Connect 1.0 Logout endpoint
* @since 1.1.0
* @since 1.1
*/
public String getOidcLogoutEndpoint() {
return getSetting(ConfigurationSettingNames.AuthorizationServer.OIDC_LOGOUT_ENDPOINT);
@@ -282,7 +282,7 @@ public final class AuthorizationServerSettings extends AbstractSettings {
*
* @param oidcLogoutEndpoint the OpenID Connect 1.0 Logout endpoint
* @return the {@link Builder} for further configuration
* @since 1.1.0
* @since 1.1
*/
public Builder oidcLogoutEndpoint(String oidcLogoutEndpoint) {
return setting(ConfigurationSettingNames.AuthorizationServer.OIDC_LOGOUT_ENDPOINT, oidcLogoutEndpoint);

View File

@@ -128,7 +128,7 @@ public final class ConfigurationSettingNames {
/**
* Set the OpenID Connect 1.0 Logout endpoint.
* @since 1.1.0
* @since 1.1
*/
public static final String OIDC_LOGOUT_ENDPOINT = AUTHORIZATION_SERVER_SETTINGS_NAMESPACE.concat("oidc-logout-endpoint");

View File

@@ -249,7 +249,7 @@ public final class OAuth2AuthorizationEndpointFilter extends OncePerRequestFilte
* If OpenID Connect is enabled, the default implementation tracks OpenID Connect sessions using a {@link SessionRegistry}.
*
* @param sessionAuthenticationStrategy the {@link SessionAuthenticationStrategy} used for handling an {@link OAuth2AuthorizationCodeRequestAuthenticationToken}
* @since 1.1.0
* @since 1.1
*/
public void setSessionAuthenticationStrategy(SessionAuthenticationStrategy sessionAuthenticationStrategy) {
Assert.notNull(sessionAuthenticationStrategy, "sessionAuthenticationStrategy cannot be null");

View File

@@ -54,6 +54,8 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
@@ -131,6 +133,7 @@ public class OidcTests {
private static JWKSource<SecurityContext> jwkSource;
private static HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter =
new OAuth2AccessTokenResponseHttpMessageConverter();
private static SessionRegistry sessionRegistry;
public final SpringTestContext spring = new SpringTestContext();
@@ -163,6 +166,7 @@ public class OidcTests {
.addScript("org/springframework/security/oauth2/server/authorization/oauth2-authorization-schema.sql")
.addScript("org/springframework/security/oauth2/server/authorization/client/oauth2-registered-client-schema.sql")
.build();
sessionRegistry = spy(new SessionRegistryImpl());
}
@AfterEach
@@ -187,8 +191,8 @@ public class OidcTests {
MultiValueMap<String, String> authorizationRequestParameters = getAuthorizationRequestParameters(registeredClient);
MvcResult mvcResult = this.mvc.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI)
.params(authorizationRequestParameters)
.with(user("user").roles("A", "B")))
.params(authorizationRequestParameters)
.with(user("user").roles("A", "B")))
.andExpect(status().is3xxRedirection())
.andReturn();
String redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
@@ -199,9 +203,9 @@ public class OidcTests {
OAuth2Authorization authorization = this.authorizationService.findByToken(authorizationCode, AUTHORIZATION_CODE_TOKEN_TYPE);
mvcResult = this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
.params(getTokenRequestParameters(registeredClient, authorization))
.header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth(
registeredClient.getClientId(), registeredClient.getClientSecret())))
.params(getTokenRequestParameters(registeredClient, authorization))
.header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth(
registeredClient.getClientId(), registeredClient.getClientSecret())))
.andExpect(status().isOk())
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store")))
.andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache")))
@@ -259,8 +263,7 @@ public class OidcTests {
mvcResult = this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
.params(getTokenRequestParameters(registeredClient, authorization))
.header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth(
registeredClient.getClientId(), registeredClient.getClientSecret()))
.session(session))
registeredClient.getClientId(), registeredClient.getClientSecret())))
.andExpect(status().isOk())
.andReturn();
@@ -283,6 +286,85 @@ public class OidcTests {
assertThat(session.isInvalid()).isTrue();
}
@Test
public void requestWhenLogoutRequestWithOtherUsersIdTokenThenNotLogout() throws Exception {
this.spring.register(AuthorizationServerConfiguration.class).autowire();
// Login user1
RegisteredClient registeredClient1 = TestRegisteredClients.registeredClient().scope(OidcScopes.OPENID).build();
this.registeredClientRepository.save(registeredClient1);
MultiValueMap<String, String> authorizationRequestParameters = getAuthorizationRequestParameters(registeredClient1);
MvcResult mvcResult = this.mvc.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI)
.params(authorizationRequestParameters)
.with(user("user1")))
.andExpect(status().is3xxRedirection())
.andReturn();
MockHttpSession user1Session = (MockHttpSession) mvcResult.getRequest().getSession();
assertThat(user1Session.isNew()).isTrue();
String redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
String authorizationCode = extractParameterFromRedirectUri(redirectedUrl, "code");
OAuth2Authorization user1Authorization = this.authorizationService.findByToken(authorizationCode, AUTHORIZATION_CODE_TOKEN_TYPE);
mvcResult = this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
.params(getTokenRequestParameters(registeredClient1, user1Authorization))
.header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth(
registeredClient1.getClientId(), registeredClient1.getClientSecret())))
.andExpect(status().isOk())
.andReturn();
MockHttpServletResponse servletResponse = mvcResult.getResponse();
MockClientHttpResponse httpResponse = new MockClientHttpResponse(
servletResponse.getContentAsByteArray(), HttpStatus.valueOf(servletResponse.getStatus()));
OAuth2AccessTokenResponse accessTokenResponse = accessTokenHttpResponseConverter.read(OAuth2AccessTokenResponse.class, httpResponse);
String user1IdToken = (String) accessTokenResponse.getAdditionalParameters().get(OidcParameterNames.ID_TOKEN);
// Login user2
RegisteredClient registeredClient2 = TestRegisteredClients.registeredClient2().scope(OidcScopes.OPENID).build();
this.registeredClientRepository.save(registeredClient2);
authorizationRequestParameters = getAuthorizationRequestParameters(registeredClient2);
mvcResult = this.mvc.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI)
.params(authorizationRequestParameters)
.with(user("user2")))
.andExpect(status().is3xxRedirection())
.andReturn();
MockHttpSession user2Session = (MockHttpSession) mvcResult.getRequest().getSession();
assertThat(user2Session.isNew()).isTrue();
redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
authorizationCode = extractParameterFromRedirectUri(redirectedUrl, "code");
OAuth2Authorization user2Authorization = this.authorizationService.findByToken(authorizationCode, AUTHORIZATION_CODE_TOKEN_TYPE);
mvcResult = this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
.params(getTokenRequestParameters(registeredClient2, user2Authorization))
.header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth(
registeredClient2.getClientId(), registeredClient2.getClientSecret())))
.andExpect(status().isOk())
.andReturn();
servletResponse = mvcResult.getResponse();
httpResponse = new MockClientHttpResponse(
servletResponse.getContentAsByteArray(), HttpStatus.valueOf(servletResponse.getStatus()));
accessTokenResponse = accessTokenHttpResponseConverter.read(OAuth2AccessTokenResponse.class, httpResponse);
String user2IdToken = (String) accessTokenResponse.getAdditionalParameters().get(OidcParameterNames.ID_TOKEN);
// Attempt to log out user1 using user2's ID Token
mvcResult = this.mvc.perform(post(DEFAULT_OIDC_LOGOUT_ENDPOINT_URI)
.param("id_token_hint", user2IdToken)
.session(user1Session))
.andExpect(status().isBadRequest())
.andExpect(status().reason("[invalid_token] OpenID Connect 1.0 Logout Request Parameter: sub"))
.andReturn();
assertThat(user1Session.isInvalid()).isFalse();
}
@Test
public void requestWhenCustomTokenGeneratorThenUsed() throws Exception {
this.spring.register(AuthorizationServerConfigurationWithTokenGenerator.class).autowire();
@@ -403,6 +485,11 @@ public class OidcTests {
return NoOpPasswordEncoder.getInstance();
}
@Bean
SessionRegistry sessionRegistry() {
return sessionRegistry;
}
static class RowMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper {
RowMapper(RegisteredClientRepository registeredClientRepository) {

View File

@@ -126,7 +126,7 @@ public class OidcLogoutAuthenticationProviderTests {
});
verify(this.authorizationService).findByToken(
eq(authentication.getIdToken()), eq(ID_TOKEN_TOKEN_TYPE));
eq(authentication.getIdTokenHint()), eq(ID_TOKEN_TOKEN_TYPE));
}
@Test
@@ -160,7 +160,7 @@ public class OidcLogoutAuthenticationProviderTests {
assertThat(error.getDescription()).contains(IdTokenClaimNames.AUD);
});
verify(this.authorizationService).findByToken(
eq(authentication.getIdToken()), eq(ID_TOKEN_TOKEN_TYPE));
eq(authentication.getIdTokenHint()), eq(ID_TOKEN_TOKEN_TYPE));
verify(this.registeredClientRepository).findById(
eq(authorization.getRegisteredClientId()));
}
@@ -197,7 +197,7 @@ public class OidcLogoutAuthenticationProviderTests {
assertThat(error.getDescription()).contains(IdTokenClaimNames.AUD);
});
verify(this.authorizationService).findByToken(
eq(authentication.getIdToken()), eq(ID_TOKEN_TOKEN_TYPE));
eq(authentication.getIdTokenHint()), eq(ID_TOKEN_TOKEN_TYPE));
verify(this.registeredClientRepository).findById(
eq(authorization.getRegisteredClientId()));
}
@@ -234,7 +234,7 @@ public class OidcLogoutAuthenticationProviderTests {
assertThat(error.getDescription()).contains(OAuth2ParameterNames.CLIENT_ID);
});
verify(this.authorizationService).findByToken(
eq(authentication.getIdToken()), eq(ID_TOKEN_TOKEN_TYPE));
eq(authentication.getIdTokenHint()), eq(ID_TOKEN_TOKEN_TYPE));
verify(this.registeredClientRepository).findById(
eq(authorization.getRegisteredClientId()));
}
@@ -272,7 +272,46 @@ public class OidcLogoutAuthenticationProviderTests {
assertThat(error.getDescription()).contains("post_logout_redirect_uri");
});
verify(this.authorizationService).findByToken(
eq(authentication.getIdToken()), eq(ID_TOKEN_TOKEN_TYPE));
eq(authentication.getIdTokenHint()), eq(ID_TOKEN_TOKEN_TYPE));
verify(this.registeredClientRepository).findById(
eq(authorization.getRegisteredClientId()));
}
@Test
public void authenticateWhenInvalidSubThenThrowOAuth2AuthenticationException() {
TestingAuthenticationToken principal = new TestingAuthenticationToken("principal", "credentials");
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
OidcIdToken idToken = OidcIdToken.withTokenValue("id-token")
.issuer("https://provider.com")
.subject("other-sub")
.audience(Collections.singleton(registeredClient.getClientId()))
.issuedAt(Instant.now().minusSeconds(60).truncatedTo(ChronoUnit.MILLIS))
.expiresAt(Instant.now().plusSeconds(60).truncatedTo(ChronoUnit.MILLIS))
.build();
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient)
.principalName(principal.getName())
.token(idToken,
(metadata) -> metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, idToken.getClaims()))
.build();
when(this.authorizationService.findByToken(eq(idToken.getTokenValue()), eq(ID_TOKEN_TOKEN_TYPE)))
.thenReturn(authorization);
when(this.registeredClientRepository.findById(eq(authorization.getRegisteredClientId())))
.thenReturn(registeredClient);
principal.setAuthenticated(true);
OidcLogoutAuthenticationToken authentication = new OidcLogoutAuthenticationToken(
idToken.getTokenValue(), principal, "session-1", null, null, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_TOKEN);
assertThat(error.getDescription()).contains("sub");
});
verify(this.authorizationService).findByToken(
eq(authentication.getIdTokenHint()), eq(ID_TOKEN_TOKEN_TYPE));
verify(this.registeredClientRepository).findById(
eq(authorization.getRegisteredClientId()));
}
@@ -317,7 +356,7 @@ public class OidcLogoutAuthenticationProviderTests {
assertThat(error.getDescription()).contains("sid");
});
verify(this.authorizationService).findByToken(
eq(authentication.getIdToken()), eq(ID_TOKEN_TOKEN_TYPE));
eq(authentication.getIdTokenHint()), eq(ID_TOKEN_TOKEN_TYPE));
verify(this.registeredClientRepository).findById(
eq(authorization.getRegisteredClientId()));
}
@@ -363,7 +402,7 @@ public class OidcLogoutAuthenticationProviderTests {
assertThat(error.getDescription()).contains("sid");
});
verify(this.authorizationService).findByToken(
eq(authentication.getIdToken()), eq(ID_TOKEN_TOKEN_TYPE));
eq(authentication.getIdTokenHint()), eq(ID_TOKEN_TOKEN_TYPE));
verify(this.registeredClientRepository).findById(
eq(authorization.getRegisteredClientId()));
}
@@ -408,15 +447,14 @@ public class OidcLogoutAuthenticationProviderTests {
(OidcLogoutAuthenticationToken) this.authenticationProvider.authenticate(authentication);
verify(this.authorizationService).findByToken(
eq(authentication.getIdToken()), eq(ID_TOKEN_TOKEN_TYPE));
eq(authentication.getIdTokenHint()), eq(ID_TOKEN_TOKEN_TYPE));
verify(this.registeredClientRepository).findById(
eq(authorization.getRegisteredClientId()));
assertThat(authenticationResult.getPrincipal()).isEqualTo(principal);
assertThat(authenticationResult.getCredentials().toString()).isEmpty();
assertThat(authenticationResult.getIdToken()).isEqualTo(idToken.getTokenValue());
assertThat(authenticationResult.getIdToken()).isEqualTo(idToken);
assertThat(authenticationResult.getSessionId()).isEqualTo(sessionInformation.getSessionId());
assertThat(authenticationResult.getSessionInformation()).isEqualTo(sessionInformation);
assertThat(authenticationResult.getClientId()).isEqualTo(registeredClient.getClientId());
assertThat(authenticationResult.getPostLogoutRedirectUri()).isEqualTo(postLogoutRedirectUri);
assertThat(authenticationResult.getState()).isEqualTo(state);

View File

@@ -15,13 +15,12 @@
*/
package org.springframework.security.oauth2.server.authorization.oidc.authentication;
import java.sql.Date;
import java.time.Instant;
import org.junit.jupiter.api.Test;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@@ -32,59 +31,60 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
* @author Joe Grandja
*/
public class OidcLogoutAuthenticationTokenTests {
private final String idToken = "id-token";
private final String idTokenHint = "id-token";
private final OidcIdToken idToken = OidcIdToken.withTokenValue(this.idTokenHint)
.issuer("https://provider.com")
.subject("principal")
.issuedAt(Instant.now().minusSeconds(60))
.expiresAt(Instant.now().plusSeconds(60))
.build();
private final TestingAuthenticationToken principal = new TestingAuthenticationToken("principal", "credentials");
private final String sessionId = "session-1";
private final SessionInformation sessionInformation = new SessionInformation(this.principal, "session-2", Date.from(Instant.now()));
private final String clientId = "client-1";
private final String postLogoutRedirectUri = "https://example.com/oidc-post-logout";
private final String state = "state-1";
@Test
public void constructorWhenIdTokenNullThenThrowIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new OidcLogoutAuthenticationToken(
null, this.principal, this.sessionId, this.clientId, this.postLogoutRedirectUri, this.state))
.withMessage("idToken cannot be empty");
assertThatIllegalArgumentException()
.isThrownBy(() -> new OidcLogoutAuthenticationToken(
null, this.principal, this.sessionInformation, this.clientId, this.postLogoutRedirectUri, this.state))
.withMessage("idToken cannot be empty");
}
@Test
public void constructorWhenIdTokenEmptyThenThrowIllegalArgumentException() {
public void constructorWhenIdTokenHintEmptyThenThrowIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new OidcLogoutAuthenticationToken(
"", this.principal, this.sessionId, this.clientId, this.postLogoutRedirectUri, this.state))
.withMessage("idToken cannot be empty");
.withMessage("idTokenHint cannot be empty");
assertThatIllegalArgumentException()
.isThrownBy(() -> new OidcLogoutAuthenticationToken(
"", this.principal, this.sessionInformation, this.clientId, this.postLogoutRedirectUri, this.state))
.withMessage("idToken cannot be empty");
(String) null, this.principal, this.sessionId, this.clientId, this.postLogoutRedirectUri, this.state))
.withMessage("idTokenHint cannot be empty");
}
@Test
public void constructorWhenIdTokenNullThenThrowIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new OidcLogoutAuthenticationToken(
(OidcIdToken) null, this.principal, this.sessionId, this.clientId, this.postLogoutRedirectUri, this.state))
.withMessage("idToken cannot be null");
}
@Test
public void constructorWhenPrincipalNullThenThrowIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new OidcLogoutAuthenticationToken(
this.idToken, null, this.sessionId, this.clientId, this.postLogoutRedirectUri, this.state))
this.idTokenHint, null, this.sessionId, this.clientId, this.postLogoutRedirectUri, this.state))
.withMessage("principal cannot be null");
assertThatIllegalArgumentException()
.isThrownBy(() -> new OidcLogoutAuthenticationToken(
this.idToken, null, this.sessionInformation, this.clientId, this.postLogoutRedirectUri, this.state))
this.idToken, null, this.sessionId, this.clientId, this.postLogoutRedirectUri, this.state))
.withMessage("principal cannot be null");
}
@Test
public void constructorWhenSessionIdProvidedThenCreated() {
public void constructorWhenIdTokenHintProvidedThenCreated() {
OidcLogoutAuthenticationToken authentication = new OidcLogoutAuthenticationToken(
this.idToken, this.principal, this.sessionId, this.clientId, this.postLogoutRedirectUri, this.state);
this.idTokenHint, this.principal, this.sessionId, this.clientId, this.postLogoutRedirectUri, this.state);
assertThat(authentication.getPrincipal()).isEqualTo(this.principal);
assertThat(authentication.getCredentials().toString()).isEmpty();
assertThat(authentication.getIdToken()).isEqualTo(this.idToken);
assertThat(authentication.getIdTokenHint()).isEqualTo(this.idTokenHint);
assertThat(authentication.getIdToken()).isNull();
assertThat(authentication.getSessionId()).isEqualTo(this.sessionId);
assertThat(authentication.getSessionInformation()).isNull();
assertThat(authentication.getClientId()).isEqualTo(this.clientId);
assertThat(authentication.getPostLogoutRedirectUri()).isEqualTo(this.postLogoutRedirectUri);
assertThat(authentication.getState()).isEqualTo(this.state);
@@ -92,14 +92,14 @@ public class OidcLogoutAuthenticationTokenTests {
}
@Test
public void constructorWhenSessionInformationProvidedThenCreated() {
public void constructorWhenIdTokenProvidedThenCreated() {
OidcLogoutAuthenticationToken authentication = new OidcLogoutAuthenticationToken(
this.idToken, this.principal, this.sessionInformation, this.clientId, this.postLogoutRedirectUri, this.state);
this.idToken, this.principal, this.sessionId, this.clientId, this.postLogoutRedirectUri, this.state);
assertThat(authentication.getPrincipal()).isEqualTo(this.principal);
assertThat(authentication.getCredentials().toString()).isEmpty();
assertThat(authentication.getIdTokenHint()).isEqualTo(this.idToken.getTokenValue());
assertThat(authentication.getIdToken()).isEqualTo(this.idToken);
assertThat(authentication.getSessionId()).isEqualTo(this.sessionInformation.getSessionId());
assertThat(authentication.getSessionInformation()).isEqualTo(this.sessionInformation);
assertThat(authentication.getSessionId()).isEqualTo(this.sessionId);
assertThat(authentication.getClientId()).isEqualTo(this.clientId);
assertThat(authentication.getPostLogoutRedirectUri()).isEqualTo(this.postLogoutRedirectUri);
assertThat(authentication.getState()).isEqualTo(this.state);

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.security.oauth2.server.authorization.oidc.web;
import java.time.Instant;
import java.util.Date;
import java.util.function.Consumer;
import jakarta.servlet.FilterChain;
@@ -38,7 +36,6 @@ import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
@@ -217,7 +214,7 @@ public class OidcLogoutEndpointFilterTests {
@Test
public void doFilterWhenCustomAuthenticationConverterThenUsed() throws Exception {
OidcLogoutAuthenticationToken authentication = new OidcLogoutAuthenticationToken(
"id-token", this.principal, (SessionInformation) null, null, null, null);
"id-token", this.principal, null, null, null, null);
AuthenticationConverter authenticationConverter = mock(AuthenticationConverter.class);
when(authenticationConverter.convert(any())).thenReturn(authentication);
@@ -240,7 +237,7 @@ public class OidcLogoutEndpointFilterTests {
@Test
public void doFilterWhenCustomAuthenticationSuccessHandlerThenUsed() throws Exception {
OidcLogoutAuthenticationToken authentication = new OidcLogoutAuthenticationToken(
"id-token", this.principal, (SessionInformation) null, null, null, null);
"id-token", this.principal, null, null, null, null);
AuthenticationSuccessHandler authenticationSuccessHandler = mock(AuthenticationSuccessHandler.class);
this.filter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
@@ -292,11 +289,8 @@ public class OidcLogoutEndpointFilterTests {
MockHttpServletRequest request = createLogoutRequest(TestRegisteredClients.registeredClient().build());
MockHttpSession session = (MockHttpSession) request.getSession(true);
SessionInformation sessionInformation = new SessionInformation(
this.principal, session.getId(), Date.from(Instant.now()));
OidcLogoutAuthenticationToken authentication = new OidcLogoutAuthenticationToken(
"id-token", this.principal, sessionInformation, null, null, null);
"id-token", this.principal, session.getId(), null, null, null);
when(this.authenticationManager.authenticate(any()))
.thenReturn(authentication);
@@ -321,14 +315,12 @@ public class OidcLogoutEndpointFilterTests {
MockHttpServletRequest request = createLogoutRequest(registeredClient);
MockHttpSession session = (MockHttpSession) request.getSession(true);
SessionInformation sessionInformation = new SessionInformation(
this.principal, session.getId(), Date.from(Instant.now()));
String postLogoutRedirectUri = registeredClient.getPostLogoutRedirectUris().iterator().next();
String state = "state-1";
OidcLogoutAuthenticationToken authentication = new OidcLogoutAuthenticationToken(
"id-token", this.principal, sessionInformation,
"id-token", this.principal, session.getId(),
registeredClient.getClientId(), postLogoutRedirectUri, state);
authentication.setAuthenticated(true);
when(this.authenticationManager.authenticate(any()))
.thenReturn(authentication);