reiley
reiley

Reputation: 3761

Spring boot / Java - Add basic auth with session

My application has 2 existing access levels:

  1. For urls present in String[] ALLOWED_WITHOUT_AUTHENTICATION, it's permitAll().
  2. For everything else it is authenticated by oauth2Login().

Application is also using a securityContext - CookieSecurityContextRepository of type SecurityContextRepository, which is storing user of type CustomOidcUser.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and().authorizeRequests().antMatchers(Constants.ALLOWED_WITHOUT_AUTHENTICATION).permitAll()
        .and().securityContext().securityContextRepository(new CookieSecurityContextRepository(authCookieHelper))
        .and().authorizeRequests().antMatchers("/**").authenticated()
        .and().oauth2Login().userInfoEndpoint().oidcUserService(oidcUserService).customUserType(CustomOidcUser.class, "customUser")
        .and().defaultSuccessUrl(authSuccessURL, true).failureUrl(userNotAuthenticatedURL)
        .and().exceptionHandling().authenticationEntryPoint(getAuthenticationEntryPoint());
}

I want to add basicAuth to some of the urls String[] AUTHENTICATED_WITH_BASIC_AUTH. So I've added below code:

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and().authorizeRequests().antMatchers(Constants.ALLOWED_WITHOUT_AUTHENTICATION).permitAll()
        .and().securityContext().securityContextRepository(new CookieSecurityContextRepository(authCookieHelper))

        .and().authorizeRequests().antMatchers(Constants.AUTHENTICATED_WITH_BASIC_AUTH).authenticated() // Line added #1 
        .and().httpBasic() // Line added #2

        .and().authorizeRequests().antMatchers("/**").authenticated()
        .and().oauth2Login().userInfoEndpoint().oidcUserService(oidcUserService).customUserType(CustomOidcUser.class, "customUser")
        .and().defaultSuccessUrl(authSuccessURL, true).failureUrl(userNotAuthenticatedURL)
        .and().exceptionHandling().authenticationEntryPoint(getAuthenticationEntryPoint());
}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
            .withUser("myUser")
            .password("{noop}1234")
            .roles("USER");
}

But whenever I'm trying to access a basic auth protected url, I'm getting error:

java.lang.ClassCastException: org.springframework.security.core.userdetails.User cannot be cast to com.myapp.user.CustomOidcUser

I think it is because session is trying to find user of type CustomOidcUser.

How can I separate out http basicAuth from my existing configurations, in such a way that both of them works?

Upvotes: 1

Views: 807

Answers (1)

Pilpo
Pilpo

Reputation: 1276

One solution is to use two distinct security configuration in your SecurityConfiguration class

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Configuration
    @Order(1)
    public class BasicAuthSecurity extends WebSecurityConfigurerAdapter {
       @Override 
       public void configure(HttpSecurity http) throws Exception {
          [basic HTTP auth configuration here]
       }
       [...]
    }


    @Configuration
    @Order(2)
    public class OAuthSecurity extends WebSecurityConfigurerAdapter {
       @Override 
       public void configure(HttpSecurity http) throws Exception {
          [OAuth configuration here]
       }
       [...]
    }
}

This way Spring will work with two different authentication system.

An other solution is to use two roles as shown here https://stackoverflow.com/a/50062043/10691359.

Upvotes: 1

Related Questions