diff --git a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java index d2a020eee5..3b92be824f 100644 --- a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java @@ -52,6 +52,7 @@ import org.springframework.security.authorization.AuthorizationDecision; import org.springframework.security.authorization.ReactiveAuthorizationManager; import org.springframework.security.config.Customizer; import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.ReactiveUserDetailsService; @@ -102,6 +103,7 @@ import org.springframework.security.web.server.DelegatingServerAuthenticationEnt import org.springframework.security.web.server.MatcherSecurityWebFilterChain; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.ServerAuthenticationEntryPoint; +import org.springframework.security.web.server.WebFilterExchange; import org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter; import org.springframework.security.web.server.authentication.AuthenticationWebFilter; import org.springframework.security.web.server.authentication.HttpBasicServerAuthenticationEntryPoint; @@ -1788,6 +1790,28 @@ public class ServerHttpSecurity { } } + private class BearerTokenAuthenticationWebFilter extends AuthenticationWebFilter { + private ServerAuthenticationFailureHandler authenticationFailureHandler; + + BearerTokenAuthenticationWebFilter(ReactiveAuthenticationManager authenticationManager) { + super(authenticationManager); + } + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + WebFilterExchange webFilterExchange = new WebFilterExchange(exchange, chain); + return super.filter(exchange, chain) + .onErrorResume(AuthenticationException.class, e -> this.authenticationFailureHandler + .onAuthenticationFailure(webFilterExchange, e)); + } + + @Override + public void setAuthenticationFailureHandler(ServerAuthenticationFailureHandler authenticationFailureHandler) { + super.setAuthenticationFailureHandler(authenticationFailureHandler); + this.authenticationFailureHandler = authenticationFailureHandler; + } + } + /** * Configures JWT Resource Server Support */ @@ -1861,7 +1885,7 @@ public class ServerHttpSecurity { protected void configure(ServerHttpSecurity http) { ReactiveAuthenticationManager authenticationManager = getAuthenticationManager(); - AuthenticationWebFilter oauth2 = new AuthenticationWebFilter(authenticationManager); + AuthenticationWebFilter oauth2 = new BearerTokenAuthenticationWebFilter(authenticationManager); oauth2.setServerAuthenticationConverter(bearerTokenConverter); oauth2.setAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(entryPoint)); http @@ -1967,7 +1991,7 @@ public class ServerHttpSecurity { protected void configure(ServerHttpSecurity http) { ReactiveAuthenticationManager authenticationManager = getAuthenticationManager(); - AuthenticationWebFilter oauth2 = new AuthenticationWebFilter(authenticationManager); + AuthenticationWebFilter oauth2 = new BearerTokenAuthenticationWebFilter(authenticationManager); oauth2.setServerAuthenticationConverter(bearerTokenConverter); oauth2.setAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(entryPoint)); http.addFilterAt(oauth2, SecurityWebFiltersOrder.AUTHENTICATION); diff --git a/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java b/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java index 31346199b3..b059c00880 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java @@ -172,6 +172,17 @@ public class OAuth2ResourceServerSpecTests { .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"invalid_token\"")); } + @Test + public void getWhenEmptyBearerTokenThenReturnsInvalidToken() { + this.spring.register(PublicKeyConfig.class).autowire(); + + this.client.get() + .headers(headers -> headers.add("Authorization", "Bearer ")) + .exchange() + .expectStatus().isUnauthorized() + .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"invalid_token\"")); + } + @Test public void getWhenValidTokenAndPublicKeyInLambdaThenReturnsOk() { this.spring.register(PublicKeyInLambdaConfig.class, RootController.class).autowire();