Skip to content

Commit 925d531

Browse files
karltinawiSteve Riesenberg
authored andcommitted
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)