From 77d4832296011e9f30854cea294da54496fb0c39 Mon Sep 17 00:00:00 2001 From: Respirayson Date: Sun, 21 Jun 2026 22:36:11 +0800 Subject: [PATCH] fix: avoid invalid -1 port in Cognito logout redirect URL --- .../logout/CognitoLogoutSuccessHandler.java | 7 +- .../CognitoLogoutSuccessHandlerTest.java | 70 +++++++++++++++++++ 2 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 api/src/test/java/io/kafbat/ui/config/auth/logout/CognitoLogoutSuccessHandlerTest.java diff --git a/api/src/main/java/io/kafbat/ui/config/auth/logout/CognitoLogoutSuccessHandler.java b/api/src/main/java/io/kafbat/ui/config/auth/logout/CognitoLogoutSuccessHandler.java index e58f51ab3a..c2da96d1de 100644 --- a/api/src/main/java/io/kafbat/ui/config/auth/logout/CognitoLogoutSuccessHandler.java +++ b/api/src/main/java/io/kafbat/ui/config/auth/logout/CognitoLogoutSuccessHandler.java @@ -10,7 +10,6 @@ import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.security.core.Authentication; import org.springframework.security.web.server.WebFilterExchange; -import org.springframework.security.web.util.UrlUtils; import org.springframework.stereotype.Component; import org.springframework.util.Assert; import org.springframework.web.server.WebSession; @@ -35,12 +34,8 @@ public Mono handle(WebFilterExchange exchange, Authentication authenticati final var requestUri = exchange.getExchange().getRequest().getURI(); - final var fullUrl = UrlUtils.buildFullRequestUrl(requestUri.getScheme(), - requestUri.getHost(), requestUri.getPort(), - requestUri.getPath(), requestUri.getQuery()); - final UriComponents baseUrl = UriComponentsBuilder - .fromUriString(fullUrl) + .fromUri(requestUri) .replacePath("/") .replaceQuery(null) .fragment(null) diff --git a/api/src/test/java/io/kafbat/ui/config/auth/logout/CognitoLogoutSuccessHandlerTest.java b/api/src/test/java/io/kafbat/ui/config/auth/logout/CognitoLogoutSuccessHandlerTest.java new file mode 100644 index 0000000000..cda390b910 --- /dev/null +++ b/api/src/test/java/io/kafbat/ui/config/auth/logout/CognitoLogoutSuccessHandlerTest.java @@ -0,0 +1,70 @@ +package io.kafbat.ui.config.auth.logout; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +import io.kafbat.ui.config.auth.OAuthProperties; +import java.net.URI; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.mock.http.server.reactive.MockServerHttpRequest; +import org.springframework.mock.web.server.MockServerWebExchange; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.server.WebFilterExchange; +import org.springframework.web.server.ServerWebExchange; + +class CognitoLogoutSuccessHandlerTest { + + private CognitoLogoutSuccessHandler handler; + + @BeforeEach + void setUp() { + handler = new CognitoLogoutSuccessHandler(); + } + + @Test + void shouldHandleWithNegativePortBehindProxy() { + MockServerHttpRequest request = MockServerHttpRequest.get("https://proxy.kafbat-ui.com/ui/clusters").build(); + ServerWebExchange serverWebExchange = MockServerWebExchange.from(request); + WebFilterExchange exchange = new WebFilterExchange(serverWebExchange, chain -> reactor.core.publisher.Mono.empty()); + Authentication authentication = mock(Authentication.class); + + OAuthProperties.OAuth2Provider provider = new OAuthProperties.OAuth2Provider(); + provider.setClientId("my-client-id"); + provider.setCustomParams(Map.of("logoutUrl", "https://auth.cognito.com/logout")); + + handler.handle(exchange, authentication, provider).block(); + + assertThat(serverWebExchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.FOUND); + URI location = serverWebExchange.getResponse().getHeaders().getLocation(); + assertThat(location).isNotNull(); + + assertThat(location.toString()).isEqualTo( + "https://auth.cognito.com/logout?client_id=my-client-id&logout_uri=https://proxy.kafbat-ui.com/" + ); + } + + @Test + void shouldHandleWithExplicitPort() { + MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost:8080/ui/clusters").build(); + ServerWebExchange serverWebExchange = MockServerWebExchange.from(request); + WebFilterExchange exchange = new WebFilterExchange(serverWebExchange, chain -> reactor.core.publisher.Mono.empty()); + Authentication authentication = mock(Authentication.class); + + OAuthProperties.OAuth2Provider provider = new OAuthProperties.OAuth2Provider(); + provider.setClientId("test-client"); + provider.setCustomParams(Map.of("logoutUrl", "https://auth.cognito.com/logout")); + + handler.handle(exchange, authentication, provider).block(); + + assertThat(serverWebExchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.FOUND); + URI location = serverWebExchange.getResponse().getHeaders().getLocation(); + assertThat(location).isNotNull(); + + assertThat(location.toString()).isEqualTo( + "https://auth.cognito.com/logout?client_id=test-client&logout_uri=http://localhost:8080/" + ); + } +}