Spring Authorization Server in multi security config

324 views Asked by At

I have a requirement of multiple security configurations in a Spring Boot 3.0 application where postman API calls need to do oauth and application authentication would be through LdapWebSecurityConfigurerAdapter. I have this existing code which has ldap and oauth2 security configuration. I have migrated oauth2 to sping authorization server. My changes for spring authorization server & ldap work fine individually by commenting the other class. However, spring authorization server login gives 401 when /oauth2/authorize endpoint is hit. Following are my configurations.

Spring Authorization server config having InMemoryRegisteredClientRepository:

@Bean
    @Order(1)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
      logger.info("Inside authorizationServerSecurityFilterChain");
      OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);

      http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
          .oidc(Customizer.withDefaults());
      http.exceptionHandling(e -> e
          .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")))
          .oauth2ResourceServer((oauth2) -> oauth2.jwt(customizer -> customizer.jwtAuthenticationConverter(jwtAuthenticationConverter())));

      return http.build();
    }

Spring DefaultSecurityFilterChain :

    @Bean
    @Order(2)
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
      logger.info("Inside defaultSecurityFilterChain");
      http
          .authorizeHttpRequests(authorizeRequests ->
              authorizeRequests
                  .requestMatchers("/oauth2/**").permitAll()
                  .requestMatchers("/login").permitAll()
                  .requestMatchers("/api/**").authenticated()
          ).oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults()))
          .formLogin(Customizer.withDefaults());
      return http.build();

LDAP configuration :

public static class LdapWebSecurityConfigurerAdapter{

// DEPENDENCY INJECTIONS HERE

@Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
  // LdapAuthenticationProviderConfigurer CONFIGURATION HERE
}

@Bean
@Order(3)
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
log.info("Inside filterChain");

    http.authorizeHttpRequests((authorizeHttpRequests) ->
            authorizeHttpRequests
                .requestMatchers("/app/**")
        )
        .exceptionHandling((exceptionHandling) ->
        exceptionHandling.authenticationEntryPoint(authenticationEntryPoint))
        .formLogin(formLogin -> formLogin.loginProcessingUrl("/app/authentication")
        .successHandler(ajaxAuthenticationSuccessHandler)
        .failureHandler(ajaxAuthenticationFailureHandler)
        .usernameParameter("j_username")
        .passwordParameter("j_password")
        .permitAll())
        .logout((logout) -> logout.logoutUrl("/app/logout")
        .logoutSuccessHandler(ajaxLogoutSuccessHandler)
        .deleteCookies("JSESSIONID")
        .permitAll())
        .csrf((csrf) -> csrf.disable())
        .headers((headers) -> headers.frameOptions(Customizer.withDefaults()).disable());


    http.authorizeHttpRequests((authorizeHttpRequests) ->
        authorizeHttpRequests
            .requestMatchers("/app/rest/register").permitAll()
            .requestMatchers("/app/rest/activate").permitAll()
            .requestMatchers("/app/rest/authenticate").permitAll()
            .requestMatchers("/app/rest/logs/**").hasAuthority(AuthoritiesConstants.ADMIN)
            .requestMatchers("/app/**").permitAll()
            .requestMatchers("/app/**").authenticated());         
return http.build();
}


}

So, for this setup if I comment the LdapWebSecurityConfigurerAdapter, the authorization server works fine, however, It does not work when un-commented. The /oauth2/authorize/ endpoint call is redirected to /login for authorization server login, but the page does not render due to 401 error. I tried explicitly permitting the /oauth2/** and /login calls, but it does not work. Do I need to do anymore settings for login page to render and proceed the authentication with oauth2? Any help would be much appreciated.

So, for this setup if I comment the LdapWebSecurityConfigurerAdapter, the authorization server works fine, however, It does not work when un-commented. The /oauth2/authorize/ endpoint call is redirected to /login for authorization server login, but the page does not render due to 401 error.

  • I tried explicitly permitting the /oauth2/** and /login calls, but it does not work.
  • I tried combining defaultSecurityFilterChain with configure() method of LdapWebSecurityConfigurerAdapter but it does not work.

Do I need to do anymore settings for login page to render and proceed the authentication with oauth2? Or how can I segregate the two authentication flows. Any help would be much appreciated!

1

There are 1 answers

0
Steve Riesenberg On

At a glance, it looks like your @Order(3) filterChain will never be hit, because the earlier defaultSecurityFilterChain has an implicit anyRequest().denyAll() rule.

A lot of the rest of your configuration seems experimental so I can't tell what you're intended working configuration would be. However, it seems you should just need two filter chains, and the 2nd filter chain should be configured to use LDAP. In other words, you should go back to the filter chains defined in the Getting Started example and add the minimum required config to support LDAP, which would be defining a custom AuthenticationManager as a @Bean and that should be it.

If you also need to support API calls via postman, see this answer for how to correctly add another filter chain for those API calls. Note that in that case, you can wire a custom AuthenticationManager into the filter chain using formLogin() (which would end up being the 3rd filter chain) via http.authenticationManager(...). You don't need publish it as a @Bean when using the authenticationManager() DSL method.