From 01513ab17efc91d6f8795a832680773ad0da0b3a Mon Sep 17 00:00:00 2001 From: Josh Cummings Date: Thu, 16 Jun 2022 15:31:47 -0600 Subject: [PATCH] Add placeholders to reactive post_logout_redirect_uri Now also supports baseScheme, baseHost, basePort, and basePath Issue gh-11229 --- ...ntInitiatedServerLogoutSuccessHandler.java | 23 ++++++++++++-- ...tiatedServerLogoutSuccessHandlerTests.java | 30 ++++++++++++++++++- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandler.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandler.java index 080c70fa64..e4c38b5401 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandler.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandler.java @@ -132,7 +132,19 @@ public class OidcClientInitiatedServerLogoutSuccessHandler implements ServerLogo .build(); Map uriVariables = new HashMap<>(); + String scheme = uriComponents.getScheme(); + uriVariables.put("baseScheme", (scheme != null) ? scheme : ""); uriVariables.put("baseUrl", uriComponents.toUriString()); + + String host = uriComponents.getHost(); + uriVariables.put("baseHost", (host != null) ? host : ""); + + String path = uriComponents.getPath(); + uriVariables.put("basePath", (path != null) ? path : ""); + + int port = uriComponents.getPort(); + uriVariables.put("basePort", (port == -1) ? "" : ":" + port); + uriVariables.put("registrationId", clientRegistration.getRegistrationId()); return UriComponentsBuilder.fromUriString(this.postLogoutRedirectUri) @@ -154,8 +166,15 @@ public class OidcClientInitiatedServerLogoutSuccessHandler implements ServerLogo } /** - * Set the post logout redirect uri template to use. Supports the {@code "{baseUrl}"} - * placeholder, for example: + * Set the post logout redirect uri template. + * + *
+ * The supported uri template variables are: {@code {baseScheme}}, {@code {baseHost}}, + * {@code {basePort}} and {@code {basePath}}. + * + *
+ * NOTE: {@code {baseUrl}} is also supported, which is the same as + * {@code "{baseScheme}://{baseHost}{basePort}{basePath}"} * *
 	 * 	handler.setPostLogoutRedirectUri("{baseUrl}");
diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandlerTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandlerTests.java
index dc868db0e4..211e885ad3 100644
--- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandlerTests.java
+++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandlerTests.java
@@ -136,7 +136,7 @@ public class OidcClientInitiatedServerLogoutSuccessHandlerTests {
 	}
 
 	@Test
-	public void logoutWhenUsingPostLogoutRedirectUriTemplateThenBuildsItForRedirect()
+	public void logoutWhenUsingPostLogoutBaseUrlRedirectUriTemplateThenBuildsItForRedirect()
 			throws IOException, ServletException {
 		OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(),
 				AuthorityUtils.NO_AUTHORITIES, this.registration.getRegistrationId());
@@ -163,6 +163,34 @@ public class OidcClientInitiatedServerLogoutSuccessHandlerTests {
 				+ "post_logout_redirect_uri=https://rp.example.org/context?forwardUrl%3Dsecured%253Fparam%253Dtrue");
 	}
 
+	@Test
+	public void logoutWhenUsingPostLogoutRedirectUriTemplateThenBuildsItForRedirect() {
+		OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(),
+				AuthorityUtils.NO_AUTHORITIES, this.registration.getRegistrationId());
+		given(this.exchange.getPrincipal()).willReturn(Mono.just(token));
+		MockServerHttpRequest request = MockServerHttpRequest.get("https://rp.example.org/").build();
+		given(this.exchange.getRequest()).willReturn(request);
+		WebFilterExchange f = new WebFilterExchange(this.exchange, this.chain);
+		this.handler.setPostLogoutRedirectUri("{baseScheme}://{baseHost}{basePort}{basePath}");
+		this.handler.onLogoutSuccess(f, token).block();
+		assertThat(redirectedUrl(this.exchange)).isEqualTo(
+				"https://endpoint?" + "id_token_hint=id-token&" + "post_logout_redirect_uri=https://rp.example.org");
+	}
+
+	@Test
+	public void logoutWhenUsingPostLogoutRedirectUriTemplateWithOtherPortThenBuildsItForRedirect() {
+		OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(),
+				AuthorityUtils.NO_AUTHORITIES, this.registration.getRegistrationId());
+		given(this.exchange.getPrincipal()).willReturn(Mono.just(token));
+		MockServerHttpRequest request = MockServerHttpRequest.get("https://rp.example.org:400").build();
+		given(this.exchange.getRequest()).willReturn(request);
+		WebFilterExchange f = new WebFilterExchange(this.exchange, this.chain);
+		this.handler.setPostLogoutRedirectUri("{baseScheme}://{baseHost}{basePort}{basePath}");
+		this.handler.onLogoutSuccess(f, token).block();
+		assertThat(redirectedUrl(this.exchange)).isEqualTo("https://endpoint?" + "id_token_hint=id-token&"
+				+ "post_logout_redirect_uri=https://rp.example.org:400");
+	}
+
 	@Test
 	public void logoutWhenUsingPostLogoutRedirectUriTemplateThenBuildsItForRedirectExpanded()
 			throws IOException, ServletException {