Skip to content

Commit 925d531

Browse files
karltinawiSteve Riesenberg
authored and
Steve Riesenberg
committed
Set details on authentication token created by HttpServlet3RequestFactory
Currently the login mechanism when triggered by executing HttpServlet3RequestFactory#login does not set any details on the underlying authentication token that is authenticated. This change adds an AuthenticationDetailsSource on the HttpServlet3RequestFactory, which defaults to a WebAuthenticationDetailsSource. Closes gh-9579
1 parent 074e38d commit 925d531

File tree

4 files changed

+71
-1
lines changed

4 files changed

+71
-1
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import javax.servlet.http.HttpServletRequest;
2222

2323
import org.springframework.context.ApplicationContext;
24+
import org.springframework.security.authentication.AuthenticationDetailsSource;
2425
import org.springframework.security.authentication.AuthenticationManager;
2526
import org.springframework.security.authentication.AuthenticationTrustResolver;
2627
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
@@ -90,6 +91,11 @@ public void configure(H http) {
9091
if (trustResolver != null) {
9192
this.securityContextRequestFilter.setTrustResolver(trustResolver);
9293
}
94+
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = http
95+
.getSharedObject(AuthenticationDetailsSource.class);
96+
if (authenticationDetailsSource != null) {
97+
this.securityContextRequestFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
98+
}
9399
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
94100
if (context != null) {
95101
String[] grantedAuthorityDefaultsBeanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class);

config/src/test/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.springframework.context.annotation.Bean;
3131
import org.springframework.context.annotation.Configuration;
3232
import org.springframework.security.access.AccessDeniedException;
33+
import org.springframework.security.authentication.AuthenticationDetailsSource;
3334
import org.springframework.security.authentication.AuthenticationManager;
3435
import org.springframework.security.authentication.AuthenticationTrustResolver;
3536
import org.springframework.security.authentication.TestingAuthenticationToken;
@@ -149,6 +150,15 @@ public void configureWhenSharedObjectTrustResolverThenTrustResolverUsed() throws
149150
verify(SharedTrustResolverConfig.TR, atLeastOnce()).isAnonymous(any());
150151
}
151152

153+
@Test
154+
public void configureWhenSharedObjectAuthenticationDetailsSourceThenAuthenticationDetailsSourceUsed() {
155+
this.spring.register(SharedAuthenticationDetailsSourceConfig.class).autowire();
156+
SecurityContextHolderAwareRequestFilter scaFilter = getFilter(SecurityContextHolderAwareRequestFilter.class);
157+
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = getFieldValue(scaFilter,
158+
"authenticationDetailsSource");
159+
assertThat(authenticationDetailsSource).isEqualTo(SharedAuthenticationDetailsSourceConfig.ADS);
160+
}
161+
152162
@Test
153163
public void requestWhenServletApiWithDefaultsInLambdaThenUsesDefaultRolePrefix() throws Exception {
154164
this.spring.register(ServletApiWithDefaultsInLambdaConfig.class, AdminController.class).autowire();
@@ -321,6 +331,22 @@ protected void configure(HttpSecurity http) {
321331

322332
}
323333

334+
@EnableWebSecurity
335+
static class SharedAuthenticationDetailsSourceConfig extends WebSecurityConfigurerAdapter {
336+
337+
@SuppressWarnings("unchecked")
338+
static AuthenticationDetailsSource<HttpServletRequest, ?> ADS = spy(AuthenticationDetailsSource.class);
339+
340+
@Override
341+
protected void configure(HttpSecurity http) {
342+
// @formatter:off
343+
http
344+
.setSharedObject(AuthenticationDetailsSource.class, ADS);
345+
// @formatter:on
346+
}
347+
348+
}
349+
324350
@EnableWebSecurity
325351
static class ServletApiWithDefaultsInLambdaConfig extends WebSecurityConfigurerAdapter {
326352

web/src/main/java/org/springframework/security/web/servletapi/HttpServlet3RequestFactory.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.apache.commons.logging.LogFactory;
3333

3434
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
35+
import org.springframework.security.authentication.AuthenticationDetailsSource;
3536
import org.springframework.security.authentication.AuthenticationManager;
3637
import org.springframework.security.authentication.AuthenticationTrustResolver;
3738
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
@@ -42,6 +43,7 @@
4243
import org.springframework.security.core.context.SecurityContext;
4344
import org.springframework.security.core.context.SecurityContextHolder;
4445
import org.springframework.security.web.AuthenticationEntryPoint;
46+
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
4547
import org.springframework.security.web.authentication.logout.LogoutHandler;
4648
import org.springframework.util.Assert;
4749
import org.springframework.util.CollectionUtils;
@@ -79,6 +81,8 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
7981

8082
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
8183

84+
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
85+
8286
private AuthenticationEntryPoint authenticationEntryPoint;
8387

8488
private AuthenticationManager authenticationManager;
@@ -158,6 +162,18 @@ void setTrustResolver(AuthenticationTrustResolver trustResolver) {
158162
this.trustResolver = trustResolver;
159163
}
160164

165+
/**
166+
* Sets the {@link AuthenticationDetailsSource} to be used. The default is
167+
* {@link WebAuthenticationDetailsSource}.
168+
* @param authenticationDetailsSource the {@link AuthenticationDetailsSource} to use.
169+
* Cannot be null.
170+
*/
171+
void setAuthenticationDetailsSource(
172+
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
173+
Assert.notNull(authenticationDetailsSource, "authenticationDetailsSource cannot be null");
174+
this.authenticationDetailsSource = authenticationDetailsSource;
175+
}
176+
161177
@Override
162178
public HttpServletRequest create(HttpServletRequest request, HttpServletResponse response) {
163179
return new Servlet3SecurityContextHolderAwareRequestWrapper(request, this.rolePrefix, response);
@@ -233,7 +249,11 @@ public void login(String username, String password) throws ServletException {
233249
private Authentication getAuthentication(AuthenticationManager authManager, String username, String password)
234250
throws ServletException {
235251
try {
236-
return authManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
252+
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username,
253+
password);
254+
Object details = HttpServlet3RequestFactory.this.authenticationDetailsSource.buildDetails(this);
255+
authentication.setDetails(details);
256+
return authManager.authenticate(authentication);
237257
}
238258
catch (AuthenticationException ex) {
239259
SecurityContextHolder.clearContext();

web/src/main/java/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestFilter.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,14 @@
2727
import javax.servlet.http.HttpServletRequest;
2828
import javax.servlet.http.HttpServletResponse;
2929

30+
import org.springframework.security.authentication.AuthenticationDetailsSource;
3031
import org.springframework.security.authentication.AuthenticationManager;
3132
import org.springframework.security.authentication.AuthenticationTrustResolver;
3233
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
3334
import org.springframework.security.core.context.SecurityContext;
3435
import org.springframework.security.core.context.SecurityContextHolder;
3536
import org.springframework.security.web.AuthenticationEntryPoint;
37+
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
3638
import org.springframework.security.web.authentication.logout.LogoutHandler;
3739
import org.springframework.util.Assert;
3840
import org.springframework.web.filter.GenericFilterBean;
@@ -80,6 +82,8 @@ public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
8082

8183
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
8284

85+
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
86+
8387
public void setRolePrefix(String rolePrefix) {
8488
Assert.notNull(rolePrefix, "Role prefix must not be null");
8589
this.rolePrefix = rolePrefix;
@@ -172,9 +176,23 @@ public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
172176
updateFactory();
173177
}
174178

179+
/**
180+
* Sets the {@link AuthenticationDetailsSource} to be used. The default is
181+
* {@link WebAuthenticationDetailsSource}.
182+
* @param authenticationDetailsSource the {@link AuthenticationDetailsSource} to use.
183+
* Cannot be null.
184+
*/
185+
public void setAuthenticationDetailsSource(
186+
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
187+
Assert.notNull(authenticationDetailsSource, "authenticationDetailsSource cannot be null");
188+
this.authenticationDetailsSource = authenticationDetailsSource;
189+
updateFactory();
190+
}
191+
175192
private HttpServletRequestFactory createServlet3Factory(String rolePrefix) {
176193
HttpServlet3RequestFactory factory = new HttpServlet3RequestFactory(rolePrefix);
177194
factory.setTrustResolver(this.trustResolver);
195+
factory.setAuthenticationDetailsSource(this.authenticationDetailsSource);
178196
factory.setAuthenticationEntryPoint(this.authenticationEntryPoint);
179197
factory.setAuthenticationManager(this.authenticationManager);
180198
factory.setLogoutHandlers(this.logoutHandlers);

0 commit comments

Comments
 (0)