Let me shortly describe what problem i am facing right now.
I have configured spring security for webflux application, and i am getting login form prompted, when i try to access the route that doesn't require authentication. The route is /swagger-ui/ and it should get opened without any login forms or whatever.
Below is the code i have within the SecurityWebFilterChain
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
//@formatter:off
return http
.formLogin().disable()
.httpBasic().disable()
.authenticationManager(authenticationManager)
.securityContextRepository(securityContextRepository)
.authorizeExchange()
.pathMatchers(HttpMethod.OPTIONS).permitAll()
.pathMatchers("/v2/api-docs", "/v3/api-docs", "/configuration/ui", "/swagger-resources",
"/configuration/security", "/swagger-ui/", "/swagger-ui",
"/webjars/**", "/swagger-resources/configuration/ui",
"/swagger-resources/configuration/security").permitAll() // Allowed routes for swagger
.pathMatchers("/api/auth", "/api/auth/**").permitAll() // Allowed routes for auth
.and()
.authorizeExchange()
.anyExchange()
.authenticated() // All other routes require authentication
.and()
.csrf().disable()
.headers()
.hsts()
.includeSubdomains(true)
.maxAge(Duration.ofSeconds(31536000))
.and()
.frameOptions().mode(XFrameOptionsServerHttpHeadersWriter.Mode.SAMEORIGIN)
.and()
.build();
//@formatter:on
}
}
If anyone has any suggestions, please let me know, i will appreciate it. Here is the picture what i got in the browser.

I was really annoyed by this issue too. The problem is that by putting .httpBasic().disable() in your code you would expect spring to skip basic authentication (that browser window) but it doesn't.
Instead, try providing a ServerAuthenticationEntryPoint to the .httpBasic().
The most simple one is the HttpStatusServerEntryPoint.
For example in your code change to:
***
return http
.formLogin().disable()
.httpBasic().authenticationEntryPoint(new HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED))
.authenticationManager(authenticationManager)
***
By changing that your server will return a 401 UNAUTHORIZED HttpStatus instead of that browser window!
Cheers!
For those who would like to keep .httpBasic().disable() in their code while making the basic login go away I have the following setup that works.
The issue lies in that a default HttpBasicServerAuthenticationEntryPoint is configured as the fallback if there isn't another ServerAuthenticationEntryPoint. This entry point returns WWW-Authenticate header with value Basic realm="realm" which prompt the browser to pop the login prompt.
To this disable the entrypoint we cannot just disable httpBasic, but we must configure a custom ServerEntryPoint. I did it through a authentication filter but .exceptionHandling().authenticationEntryPoint(new HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED)).and() should also work.
My setup (which use authentication filter):
http.
.httpBasic().disable() // Disable Basic Login
.formLogin().disable() // Disables Form Login
.logout().disable() // Disables default Logout endpoint
.authenticationManager(authManager)
.addFilterAt(createCustomJwtFilter(), SecurityWebFiltersOrder.AUTHENTICATION)
.authorizeExchange()
.pathMatchers(HttpMethod.OPTIONS).permitAll()
.pathMatchers("/", "/healthcheck").permitAll()
.anyExchange().authenticated();
return http.build();
createCustomJwtFilter() method
private static AuthenticationWebFilter createCustomJwtFilter(ReactiveAuthenticationManager authManager)
{
AuthenticationWebFilter filter = new AuthenticationWebFilter(authManager);
// This line configures the custom entryPoint
filter.setAuthenticationFailureHandler(
new ServerAuthenticationEntryPointFailureHandler(HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED)));
return filter;
}
This should also return a 401, while keeping the httpBasic() disabled for better code readability.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With