I have a few different APIs in my spring webflux application that need to respond differently to failed authentication. I am trying to set different ServerAuthenticationEntryPoints for each API to handle these cases.
I found this example configuration that shows how to configure different AuthenticationWebFilter for different resources, which enables you to set ServerAuthenticationSuccessHandler and ServerAuthenticationFailureHandler individually, however I am not sure how to configure different ServerAuthenticationEntryPoints without having completely separate SecurityWebFilterChains.
If I have to configure separate SecurityWebFilterChains, how would I do that?
My SecurityWebFilterChain is currently configured like this - unfortunately you can't set the exceptionHandling individually and the second call to authenticationEntryPoint takes precedent:
@Bean
fun securityWebFilterChain(
http: ServerHttpSecurity,
userServerAuthenticationEntryPoint: ServerAuthenticationEntryPoint,
userAuthenticationWebFilter: AuthenticationWebFilter,
deviceServerAuthenticationEntryPoint: ServerAuthenticationEntryPoint,
deviceAuthenticationWebFilter: AuthenticationWebFilter,
serverSecurityContextRepository: ServerSecurityContextRepository,
authenticationManager: ReactiveAuthenticationManager,
serverAccessDeniedHandler: ServerAccessDeniedHandler
): SecurityWebFilterChain {
http
.addFilterAt(userAuthenticationWebFilter, SecurityWebFiltersOrder.AUTHENTICATION)
.exceptionHandling()
.authenticationEntryPoint(userServerAuthenticationEntryPoint)
.and()
.authorizeExchange()
.pathMatchers(GET, "/sign-in").permitAll()
.pathMatchers("/authentication/**").permitAll()
.pathMatchers(GET, "/landing").hasAnyAuthority("USER", "ADMIN")
.pathMatchers("/user-api/**").hasAnyAuthority("USER", "ADMIN")
http
.addFilterAt(deviceAuthenticationWebFilter, SecurityWebFiltersOrder.AUTHENTICATION)
.exceptionHandling()
.authenticationEntryPoint(deviceServerAuthenticationEntryPoint)
.and()
.authorizeExchange()
.pathMatchers("/device-api/**").hasAuthority("DEVICE")
// GLOBAL
http
.httpBasic().disable()
.formLogin().disable()
.csrf().disable()
.cors().disable()
.securityContextRepository(serverSecurityContextRepository)
.authenticationManager(authenticationManager)
.exceptionHandling()
.accessDeniedHandler(serverAccessDeniedHandler)
.and()
.authorizeExchange()
.pathMatchers(GET, "/webjars/**").permitAll()
.pathMatchers(GET, "/assets/**").permitAll()
.anyExchange().authenticated()
return http.build()
}