Skip to content

Commit 8e53c3f

Browse files
committed
DelegatingServerAuthenticationSuccessHandler Executes Sequentially
Fixes gh-7728
1 parent c71e84b commit 8e53c3f

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

web/src/main/java/org/springframework/security/web/server/authentication/DelegatingServerAuthenticationSuccessHandler.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
import org.springframework.security.core.Authentication;
2020
import org.springframework.security.web.server.WebFilterExchange;
2121
import org.springframework.util.Assert;
22+
import reactor.core.publisher.Flux;
2223
import reactor.core.publisher.Mono;
2324

2425
import java.util.Arrays;
2526
import java.util.List;
26-
import java.util.ArrayList;
2727

2828
/**
2929
* Delegates to a collection of {@link ServerAuthenticationSuccessHandler} implementations.
@@ -42,10 +42,8 @@ public DelegatingServerAuthenticationSuccessHandler(ServerAuthenticationSuccessH
4242
@Override
4343
public Mono<Void> onAuthenticationSuccess(WebFilterExchange exchange,
4444
Authentication authentication) {
45-
List<Mono<Void>> results = new ArrayList<>();
46-
for (ServerAuthenticationSuccessHandler delegate : delegates) {
47-
results.add(delegate.onAuthenticationSuccess(exchange, authentication));
48-
}
49-
return Mono.when(results);
45+
return Flux.fromIterable(this.delegates)
46+
.concatMap(delegate -> delegate.onAuthenticationSuccess(exchange, authentication))
47+
.then();
5048
}
5149
}

web/src/test/java/org/springframework/security/web/server/authentication/DelegatingServerAuthenticationSuccessHandlerTests.java

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,26 @@
1616

1717
package org.springframework.security.web.server.authentication;
1818

19-
import static org.assertj.core.api.Assertions.assertThatThrownBy;
20-
import static org.mockito.ArgumentMatchers.any;
21-
import static org.mockito.Mockito.when;
22-
2319
import org.junit.Before;
2420
import org.junit.Test;
2521
import org.junit.runner.RunWith;
2622
import org.mockito.Mock;
2723
import org.mockito.junit.MockitoJUnitRunner;
2824
import org.springframework.security.core.Authentication;
2925
import org.springframework.security.web.server.WebFilterExchange;
30-
26+
import reactor.core.publisher.Mono;
3127
import reactor.test.publisher.PublisherProbe;
3228

29+
import java.time.Duration;
30+
import java.util.concurrent.CountDownLatch;
31+
import java.util.concurrent.TimeUnit;
32+
import java.util.concurrent.atomic.AtomicBoolean;
33+
34+
import static org.assertj.core.api.Assertions.assertThat;
35+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
36+
import static org.mockito.ArgumentMatchers.any;
37+
import static org.mockito.Mockito.when;
38+
3339
/**
3440
* @author Rob Winch
3541
* @since 5.1
@@ -88,4 +94,26 @@ public void onAuthenticationSuccessWhenMultipleThenExecuted() {
8894
this.delegate1Result.assertWasSubscribed();
8995
this.delegate2Result.assertWasSubscribed();
9096
}
97+
98+
@Test
99+
public void onAuthenticationSuccessSequential() throws Exception {
100+
AtomicBoolean slowDone = new AtomicBoolean();
101+
CountDownLatch latch = new CountDownLatch(1);
102+
ServerAuthenticationSuccessHandler slow = (exchange, authentication) ->
103+
Mono.delay(Duration.ofMillis(100))
104+
.doOnSuccess(__ -> slowDone.set(true))
105+
.then();
106+
ServerAuthenticationSuccessHandler second = (exchange, authentication) ->
107+
Mono.fromRunnable(() -> {
108+
latch.countDown();
109+
assertThat(slowDone.get())
110+
.describedAs("ServerAuthenticationSuccessHandler should be executed sequentially")
111+
.isTrue();
112+
});
113+
DelegatingServerAuthenticationSuccessHandler handler = new DelegatingServerAuthenticationSuccessHandler(slow, second);
114+
115+
handler.onAuthenticationSuccess(this.exchange, this.authentication).block();
116+
117+
assertThat(latch.await(3, TimeUnit.SECONDS)).isTrue();
118+
}
91119
}

0 commit comments

Comments
 (0)