parent
4c44de7db2
commit
663946806c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
|
@ -23,6 +23,7 @@ import java.util.Map;
|
|||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
|
@ -35,6 +36,7 @@ import org.springframework.security.web.server.WebFilterExchange;
|
|||
import org.springframework.security.web.server.authentication.logout.RedirectServerLogoutSuccessHandler;
|
||||
import org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
|
@ -57,6 +59,8 @@ public class OidcClientInitiatedServerLogoutSuccessHandler implements ServerLogo
|
|||
|
||||
private String postLogoutRedirectUri;
|
||||
|
||||
private Converter<RedirectUriParameters, Mono<String>> redirectUriResolver = new DefaultRedirectUriResolver();
|
||||
|
||||
/**
|
||||
* Constructs an {@link OidcClientInitiatedServerLogoutSuccessHandler} with the
|
||||
* provided parameters
|
||||
|
@ -79,15 +83,10 @@ public class OidcClientInitiatedServerLogoutSuccessHandler implements ServerLogo
|
|||
.map(OAuth2AuthenticationToken.class::cast)
|
||||
.map(OAuth2AuthenticationToken::getAuthorizedClientRegistrationId)
|
||||
.flatMap(this.clientRegistrationRepository::findByRegistrationId)
|
||||
.flatMap((clientRegistration) -> {
|
||||
URI endSessionEndpoint = endSessionEndpoint(clientRegistration);
|
||||
if (endSessionEndpoint == null) {
|
||||
return Mono.empty();
|
||||
}
|
||||
String idToken = idToken(authentication);
|
||||
String postLogoutRedirectUri = postLogoutRedirectUri(exchange.getExchange().getRequest(), clientRegistration);
|
||||
return Mono.just(endpointUri(endSessionEndpoint, idToken, postLogoutRedirectUri));
|
||||
})
|
||||
.flatMap((clientRegistration) ->
|
||||
this.redirectUriResolver.convert(
|
||||
new RedirectUriParameters(exchange.getExchange(), authentication, clientRegistration))
|
||||
)
|
||||
.switchIfEmpty(
|
||||
this.serverLogoutSuccessHandler.onLogoutSuccess(exchange, authentication).then(Mono.empty())
|
||||
)
|
||||
|
@ -189,4 +188,79 @@ public class OidcClientInitiatedServerLogoutSuccessHandler implements ServerLogo
|
|||
this.serverLogoutSuccessHandler.setLogoutSuccessUrl(logoutSuccessUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link Converter} that converts {@link RedirectUriParameters} to redirect
|
||||
* URI
|
||||
* @param redirectUriResolver {@link Converter}
|
||||
* @since 6.4
|
||||
*/
|
||||
public void setRedirectUriResolver(Converter<RedirectUriParameters, Mono<String>> redirectUriResolver) {
|
||||
Assert.notNull(redirectUriResolver, "redirectUriResolver cannot be null");
|
||||
this.redirectUriResolver = redirectUriResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters, required for redirect URI resolving.
|
||||
*
|
||||
* @author Max Batischev
|
||||
* @since 6.4
|
||||
*/
|
||||
public static final class RedirectUriParameters {
|
||||
|
||||
private final ServerWebExchange serverWebExchange;
|
||||
|
||||
private final Authentication authentication;
|
||||
|
||||
private final ClientRegistration clientRegistration;
|
||||
|
||||
public RedirectUriParameters(ServerWebExchange serverWebExchange, Authentication authentication,
|
||||
ClientRegistration clientRegistration) {
|
||||
Assert.notNull(clientRegistration, "clientRegistration cannot be null");
|
||||
Assert.notNull(serverWebExchange, "serverWebExchange cannot be null");
|
||||
Assert.notNull(authentication, "authentication cannot be null");
|
||||
this.serverWebExchange = serverWebExchange;
|
||||
this.authentication = authentication;
|
||||
this.clientRegistration = clientRegistration;
|
||||
}
|
||||
|
||||
public ServerWebExchange getServerWebExchange() {
|
||||
return this.serverWebExchange;
|
||||
}
|
||||
|
||||
public Authentication getAuthentication() {
|
||||
return this.authentication;
|
||||
}
|
||||
|
||||
public ClientRegistration getClientRegistration() {
|
||||
return this.clientRegistration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Default {@link Converter} for redirect uri resolving.
|
||||
*
|
||||
* @since 6.4
|
||||
*/
|
||||
private final class DefaultRedirectUriResolver implements Converter<RedirectUriParameters, Mono<String>> {
|
||||
|
||||
@Override
|
||||
public Mono<String> convert(RedirectUriParameters redirectUriParameters) {
|
||||
// @formatter:off
|
||||
return Mono.just(redirectUriParameters.authentication)
|
||||
.flatMap((authentication) -> {
|
||||
URI endSessionEndpoint = endSessionEndpoint(redirectUriParameters.clientRegistration);
|
||||
if (endSessionEndpoint == null) {
|
||||
return Mono.empty();
|
||||
}
|
||||
String idToken = idToken(authentication);
|
||||
String postLogoutRedirectUri = postLogoutRedirectUri(
|
||||
redirectUriParameters.serverWebExchange.getRequest(), redirectUriParameters.clientRegistration);
|
||||
return Mono.just(endpointUri(endSessionEndpoint, idToken, postLogoutRedirectUri));
|
||||
});
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
|
@ -19,6 +19,7 @@ package org.springframework.security.oauth2.client.oidc.web.server.logout;
|
|||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
@ -199,6 +200,25 @@ public class OidcClientInitiatedServerLogoutSuccessHandlerTests {
|
|||
assertThatIllegalArgumentException().isThrownBy(() -> this.handler.setPostLogoutRedirectUri((String) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenCustomRedirectUriResolverSetThenRedirects() {
|
||||
OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(),
|
||||
AuthorityUtils.NO_AUTHORITIES, this.registration.getRegistrationId());
|
||||
WebFilterExchange filterExchange = new WebFilterExchange(this.exchange, this.chain);
|
||||
given(this.exchange.getRequest())
|
||||
.willReturn(MockServerHttpRequest.get("/").queryParam("location", "https://test.com").build());
|
||||
// @formatter:off
|
||||
this.handler.setRedirectUriResolver((params) -> Mono.just(
|
||||
Objects.requireNonNull(params.getServerWebExchange()
|
||||
.getRequest()
|
||||
.getQueryParams()
|
||||
.getFirst("location"))));
|
||||
// @formatter:on
|
||||
this.handler.onLogoutSuccess(filterExchange, token).block();
|
||||
|
||||
assertThat(redirectedUrl(this.exchange)).isEqualTo("https://test.com");
|
||||
}
|
||||
|
||||
private String redirectedUrl(ServerWebExchange exchange) {
|
||||
return exchange.getResponse().getHeaders().getFirst("Location");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue