Selaa lähdekoodia

Fix NPE with DPoP tokenAuthenticationManager

Closes gh-17172
Joe Grandja 2 kuukautta sitten
vanhempi
commit
dab989d7c3

+ 22 - 1
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/DPoPAuthenticationConfigurer.java

@@ -29,6 +29,7 @@ import jakarta.servlet.http.HttpServletResponse;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.AuthenticationManagerResolver;
 import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
 import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
 import org.springframework.security.core.Authentication;
@@ -51,6 +52,9 @@ import org.springframework.security.web.context.RequestAttributeSecurityContextR
 import org.springframework.security.web.util.matcher.RequestMatcher;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
 
 /**
  * An {@link AbstractHttpConfigurer} for OAuth 2.0 Demonstrating Proof of Possession
@@ -76,7 +80,7 @@ final class DPoPAuthenticationConfigurer<B extends HttpSecurityBuilder<B>>
 	@Override
 	public void configure(B http) {
 		AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
-		http.authenticationProvider(new DPoPAuthenticationProvider(authenticationManager));
+		http.authenticationProvider(new DPoPAuthenticationProvider(getTokenAuthenticationManager(http)));
 		AuthenticationFilter authenticationFilter = new AuthenticationFilter(authenticationManager,
 				getAuthenticationConverter());
 		authenticationFilter.setRequestMatcher(getRequestMatcher());
@@ -87,6 +91,23 @@ final class DPoPAuthenticationConfigurer<B extends HttpSecurityBuilder<B>>
 		http.addFilter(authenticationFilter);
 	}
 
+	private AuthenticationManager getTokenAuthenticationManager(B http) {
+		OAuth2ResourceServerConfigurer<B> resourceServerConfigurer = http
+			.getConfigurer(OAuth2ResourceServerConfigurer.class);
+		final AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver = resourceServerConfigurer
+			.getAuthenticationManagerResolver();
+		if (authenticationManagerResolver == null) {
+			return resourceServerConfigurer.getAuthenticationManager(http);
+		}
+		return (authentication) -> {
+			RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
+			ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
+			AuthenticationManager authenticationManager = authenticationManagerResolver
+				.resolve(servletRequestAttributes.getRequest());
+			return authenticationManager.authenticate(authentication);
+		};
+	}
+
 	private RequestMatcher getRequestMatcher() {
 		if (this.requestMatcher == null) {
 			this.requestMatcher = new DPoPRequestMatcher();

+ 4 - 0
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java

@@ -363,6 +363,10 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
 		return http.getSharedObject(AuthenticationManager.class);
 	}
 
+	AuthenticationManagerResolver<HttpServletRequest> getAuthenticationManagerResolver() {
+		return this.authenticationManagerResolver;
+	}
+
 	BearerTokenResolver getBearerTokenResolver() {
 		if (this.bearerTokenResolver == null) {
 			if (this.context.getBeanNamesForType(BearerTokenResolver.class).length > 0) {

+ 4 - 1
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java

@@ -88,6 +88,7 @@ import org.springframework.security.config.annotation.method.configuration.Enabl
 import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
 import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.config.test.SpringTestContext;
 import org.springframework.security.config.test.SpringTestContextExtension;
@@ -2532,7 +2533,9 @@ public class OAuth2ResourceServerConfigurerTests {
 			// @formatter:off
 			http
 				.oauth2ResourceServer()
-					.authenticationManagerResolver(authenticationManagerResolver);
+					.authenticationManagerResolver(authenticationManagerResolver)
+					.and()
+				.anonymous(AbstractHttpConfigurer::disable);
 			return http.build();
 			// @formatter:on
 		}