diff --git a/web/src/main/java/org/springframework/security/web/server/authentication/logout/DelegatingServerLogoutHandler.java b/web/src/main/java/org/springframework/security/web/server/authentication/logout/DelegatingServerLogoutHandler.java index 3a6a6fc400..9b6567227d 100644 --- a/web/src/main/java/org/springframework/security/web/server/authentication/logout/DelegatingServerLogoutHandler.java +++ b/web/src/main/java/org/springframework/security/web/server/authentication/logout/DelegatingServerLogoutHandler.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.security.core.Authentication; @@ -48,12 +49,8 @@ public class DelegatingServerLogoutHandler implements ServerLogoutHandler { @Override public Mono logout(WebFilterExchange exchange, Authentication authentication) { - List> results = new ArrayList<>(); - for (ServerLogoutHandler delegate : delegates) { - if (delegate != null) { - results.add(delegate.logout(exchange, authentication)); - } - } - return Mono.when(results); + return Flux.fromIterable(this.delegates) + .concatMap(delegate -> delegate.logout(exchange, authentication)) + .then(); } } diff --git a/web/src/test/java/org/springframework/security/web/server/authentication/logout/DelegatingServerLogoutHandlerTests.java b/web/src/test/java/org/springframework/security/web/server/authentication/logout/DelegatingServerLogoutHandlerTests.java index 76c790c42f..01a304c0fe 100644 --- a/web/src/test/java/org/springframework/security/web/server/authentication/logout/DelegatingServerLogoutHandlerTests.java +++ b/web/src/test/java/org/springframework/security/web/server/authentication/logout/DelegatingServerLogoutHandlerTests.java @@ -16,6 +16,7 @@ package org.springframework.security.web.server.authentication.logout; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.*; @@ -28,9 +29,14 @@ import org.mockito.junit.MockitoJUnitRunner; import org.springframework.security.core.Authentication; import org.springframework.security.web.server.WebFilterExchange; +import reactor.core.publisher.Mono; import reactor.test.publisher.PublisherProbe; +import java.time.Duration; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; /** * @author Eric Deandrea @@ -98,4 +104,26 @@ public class DelegatingServerLogoutHandlerTests { this.delegate1Result.assertWasSubscribed(); this.delegate2Result.assertWasSubscribed(); } + + @Test + public void logoutSequential() throws Exception { + AtomicBoolean slowDone = new AtomicBoolean(); + CountDownLatch latch = new CountDownLatch(1); + ServerLogoutHandler slow = (exchange, authentication) -> + Mono.delay(Duration.ofMillis(100)) + .doOnSuccess(__ -> slowDone.set(true)) + .then(); + ServerLogoutHandler second = (exchange, authentication) -> + Mono.fromRunnable(() -> { + latch.countDown(); + assertThat(slowDone.get()) + .describedAs("ServerLogoutHandler should be executed sequentially") + .isTrue(); + }); + DelegatingServerLogoutHandler handler = new DelegatingServerLogoutHandler(slow, second); + + handler.logout(this.exchange, this.authentication).block(); + + assertThat(latch.await(3, TimeUnit.SECONDS)).isTrue(); + } }