Spring Security does not let me login using one of my 2 authentication providers.
My application should be able to authenticate two types of users - User
and Organization
by checking information stored on the database. For that, I created two separate WebSecurityConfiguration
classes, with different SecurityFilterChain
, defining different form logins and using the 2 different authentication providers - which use two different UserDetailsService
implementations (pointing to different repositories).
My endpoints for Organization
work - both register and login, and the session is successfully created, but for User
, my POST
method on the login endpoint (/auth/login/user
) is blocked - returning Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' is not supported]
on IntelliJ as a warning, but the backend returns status 200
on Postman. The application does not crash, but the POST method is not completed - on debug, it completes as 405
and redirects the request to /auth/login/org
.
This is OrgWebSecurityConfiguration
's SecurityFilterChain
:
@Bean
@CrossOrigin
public SecurityFilterChain orgSecurityFilterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.securityMatchers((matcher) -> matcher
.requestMatchers("/auth/*/org").anyRequest())
.authorizeHttpRequests()
.requestMatchers("/auth/register/**")
.permitAll()
.requestMatchers("/auth/login/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/auth/login/org")
.loginProcessingUrl("/auth/login/org")
.defaultSuccessUrl("/auth/org-login-success", true)
.permitAll()
.and()
.authenticationManager(orgAuthenticationManager(http))
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/auth/login?logout")
.permitAll();
return http.build();
}
UserWebSecurityConfiguration
's SecurityFilterChain
:
@Bean
@CrossOrigin
public SecurityFilterChain userSecurityFilterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.securityMatchers((matcher) -> matcher
.requestMatchers("/auth/*/user").anyRequest())
.authorizeHttpRequests()
.requestMatchers("/auth/register/**")
.permitAll()
.requestMatchers("/auth/login/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/auth/login/user")
.loginProcessingUrl("/auth/login/user")
.defaultSuccessUrl("/auth/login-success", true)
.permitAll()
.and()
.authenticationManager(userAuthenticationManager(http))
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/auth/login?logout")
.permitAll();
return http.build();
}
userAuthProvider
:
@Bean
public DaoAuthenticationProvider userAuthProvider() {
DaoAuthenticationProvider userAuthenticationProvider = new DaoAuthenticationProvider();
userAuthenticationProvider.setUserDetailsService(userDetailsService);
userAuthenticationProvider.setPasswordEncoder(passwordEncoder());
return userAuthenticationProvider;
}
orgAuthProvider
:
@Bean
public DaoAuthenticationProvider orgAuthProvider() {
DaoAuthenticationProvider orgAuthenticationProvider = new DaoAuthenticationProvider();
orgAuthenticationProvider.setUserDetailsService(organizationDetailsService);
orgAuthenticationProvider.setPasswordEncoder(passwordEncoder);
return orgAuthenticationProvider;
}
Both orgAuthenticationManager
and userAuthenticationManager
were created by defining an authentication provider of type DaoAuthenticationProvider
and setting the proper UserDetailsService
for each, implementing the created auth providers on AuthenticationManagerBuilder
. In this case, User
's authentication manager is set to be the primary one, by using @Primary
annotation.
I've tried using @Order(0)
annotation on UserWebSecurityConfiguration
as per this question, but the problem persisted. I also disabled csrf.