Skip to content

Commit 7782e29

Browse files
ttddyyrwinch
authored andcommitted
Allow custom ReactiveAuthenticationManager for basic and form auth
Prior to this change, "HttpBasicSpec#authenticationManager" and "FormLoginSpec#authenticationManager" were always overridden by "ServerHttpSecurity#authenticationManager". This commit makes sure override only happens when custom authentication manager was not specified. Fixes: gh-5660
1 parent 400e0c8 commit 7782e29

File tree

3 files changed

+70
-4
lines changed

3 files changed

+70
-4
lines changed

config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -1667,11 +1667,15 @@ public SecurityWebFilterChain build() {
16671667
this.cors.configure(this);
16681668
}
16691669
if (this.httpBasic != null) {
1670-
this.httpBasic.authenticationManager(this.authenticationManager);
1670+
if (this.httpBasic.authenticationManager == null) {
1671+
this.httpBasic.authenticationManager(this.authenticationManager);
1672+
}
16711673
this.httpBasic.configure(this);
16721674
}
16731675
if (this.formLogin != null) {
1674-
this.formLogin.authenticationManager(this.authenticationManager);
1676+
if (this.formLogin.authenticationManager == null) {
1677+
this.formLogin.authenticationManager(this.authenticationManager);
1678+
}
16751679
if (this.securityContextRepository != null) {
16761680
this.formLogin.securityContextRepository(this.securityContextRepository);
16771681
}

config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java

+43-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@
2323
import org.openqa.selenium.WebElement;
2424
import org.openqa.selenium.support.FindBy;
2525
import org.openqa.selenium.support.PageFactory;
26+
import org.springframework.security.authentication.ReactiveAuthenticationManager;
27+
import org.springframework.security.authentication.TestingAuthenticationToken;
2628
import org.springframework.security.config.annotation.web.reactive.ServerHttpSecurityConfigurationBuilder;
2729
import org.springframework.security.htmlunit.server.WebTestClientHtmlUnitDriverBuilder;
2830
import org.springframework.security.test.web.reactive.server.WebTestClientBuilder;
@@ -40,6 +42,10 @@
4042
import static org.assertj.core.api.Assertions.assertThat;
4143
import static org.assertj.core.api.Assertions.assertThatCode;
4244
import static org.assertj.core.api.Assertions.assertThatThrownBy;
45+
import static org.mockito.ArgumentMatchers.any;
46+
import static org.mockito.BDDMockito.given;
47+
import static org.mockito.Mockito.mock;
48+
import static org.mockito.Mockito.verifyZeroInteractions;
4349

4450
/**
4551
* @author Rob Winch
@@ -152,6 +158,42 @@ public void authenticationSuccess() {
152158
assertThat(driver.getCurrentUrl()).endsWith("/custom");
153159
}
154160

161+
@Test
162+
public void customAuthenticationManager() {
163+
ReactiveAuthenticationManager defaultAuthenticationManager = mock(ReactiveAuthenticationManager.class);
164+
ReactiveAuthenticationManager customAuthenticationManager = mock(ReactiveAuthenticationManager.class);
165+
166+
given(defaultAuthenticationManager.authenticate(any())).willThrow(new RuntimeException("should not interact with default auth manager"));
167+
given(customAuthenticationManager.authenticate(any())).willReturn(Mono.just(new TestingAuthenticationToken("user", "password", "ROLE_USER", "ROLE_ADMIN")));
168+
169+
SecurityWebFilterChain securityWebFilter = this.http
170+
.authenticationManager(defaultAuthenticationManager)
171+
.formLogin()
172+
.authenticationManager(customAuthenticationManager)
173+
.and()
174+
.build();
175+
176+
WebTestClient webTestClient = WebTestClientBuilder
177+
.bindToWebFilters(securityWebFilter)
178+
.build();
179+
180+
WebDriver driver = WebTestClientHtmlUnitDriverBuilder
181+
.webTestClientSetup(webTestClient)
182+
.build();
183+
184+
DefaultLoginPage loginPage = DefaultLoginPage.to(driver)
185+
.assertAt();
186+
187+
HomePage homePage = loginPage.loginForm()
188+
.username("user")
189+
.password("password")
190+
.submit(HomePage.class);
191+
192+
homePage.assertAt();
193+
194+
verifyZeroInteractions(defaultAuthenticationManager);
195+
}
196+
155197
public static class CustomLoginPage {
156198

157199
private WebDriver driver;

config/src/test/java/org/springframework/security/config/web/server/ServerHttpSecurityTests.java

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
2020
import static org.mockito.BDDMockito.given;
2121
import static org.mockito.Matchers.any;
2222
import static org.mockito.Mockito.mock;
23+
import static org.mockito.Mockito.verifyZeroInteractions;
2324
import static org.mockito.Mockito.when;
2425

2526
import java.util.Arrays;
@@ -282,6 +283,25 @@ public void basicWithCustomRealmName() {
282283
assertThat(result.getResponseCookies().getFirst("SESSION")).isNull();
283284
}
284285

286+
@Test
287+
public void basicWithCustomAuthenticationManager() {
288+
ReactiveAuthenticationManager customAuthenticationManager = mock(ReactiveAuthenticationManager.class);
289+
given(customAuthenticationManager.authenticate(any())).willReturn(Mono.just(new TestingAuthenticationToken("rob", "rob", "ROLE_USER", "ROLE_ADMIN")));
290+
291+
SecurityWebFilterChain securityFilterChain = this.http.httpBasic().authenticationManager(customAuthenticationManager).and().build();
292+
WebFilterChainProxy springSecurityFilterChain = new WebFilterChainProxy(securityFilterChain);
293+
WebTestClient client = WebTestClientBuilder.bindToWebFilters(springSecurityFilterChain).build();
294+
295+
client.get()
296+
.uri("/")
297+
.headers(headers -> headers.setBasicAuth("rob", "rob"))
298+
.exchange()
299+
.expectStatus().isOk()
300+
.expectBody(String.class).consumeWith(b -> assertThat(b.getResponseBody()).isEqualTo("ok"));
301+
302+
verifyZeroInteractions(this.authenticationManager);
303+
}
304+
285305
@Test
286306
@SuppressWarnings("unchecked")
287307
public void addsX509FilterWhenX509AuthenticationIsConfigured() {

0 commit comments

Comments
 (0)