Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have separate authentication sources? (one for Oauth2 and one for form-based login)

I'm writing a small application that has an authentication linked to a database, this authentication will be managed by the Oauth2 aspect (Classes annotated by @EnableAuthorizationServer and @EnableResourceServer). There's another authentication in the same application for an administration page that will be linked to another different database and will use the normal form-based authentication.

I've written the following Web Security configuration class for this specific purpose:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig{

    @Configuration
    @Order(5)
    public static class AdminSecurityConfig extends WebSecurityConfigurerAdapter {

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

            http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/admin_logout"))
                    .invalidateHttpSession(true).logoutSuccessUrl("/admin/login.html");

            http.authorizeRequests()
                    .antMatchers("/admin/login.html").permitAll().antMatchers("/admin/protected.html")
                    .hasRole("ADMIN")
                    .and().formLogin().loginPage("/admin/login.html")
                    .loginProcessingUrl("/admin_login").defaultSuccessUrl("/admin/protected.html");

        }

        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            //Data source for form based auth
            auth.inMemoryAuthentication().withUser("adminuser").password("adminpassword").roles("ADMIN");
        }
    }
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        //Data source for Oauth
        auth.inMemoryAuthentication().withUser("myuser").password("mypassword").roles("USER").and().withUser("test")
                .password("testpassword").roles("USER");
    }
}

Other relevant components are:

Authorization Server configuration:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter{

    @Autowired
    AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager).tokenEnhancer(tokenEnhancer())
        .tokenStore(tokenStore());
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
            .inMemory()
                .withClient("client")
                .secret("secret")
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("read", "write")
                .resourceIds("resource").accessTokenValiditySeconds(60);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception
    {
       oauthServer.checkTokenAccess("isAuthenticated()");    
    }

    @Bean
    public TokenEnhancer tokenEnhancer() {
        return new CustomTokenEnhancer();
    }

    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }

}

Resource server configuration:

@Configuration
@EnableResourceServer
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER-1)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter{

    @Autowired
    TokenStore tokenStore;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId("resource").tokenStore(tokenStore);
    }
    @Override
    public void configure(final HttpSecurity http) throws Exception {
     http.authorizeRequests().antMatchers("/api/**").authenticated();
 }
}

You can also checkout the code here: https://github.com/cenobyte321/spring-oauth2-tokenenhancer-test/tree/webspeciallogin (Branch: webspeciallogin)

The problem is that everything in the AdminSecurityConfig class is ignored, I can go into the protected.html page without logging myself in and the login and logout processing urls specified aren't created.

The Oauth2 based login on the other hand works without a problem. I haven't also figured out how to specify in Oauth2 an AuthenticationManagerBuilder, most of online resources suggest to use the configureGlobal injected method which is read by Oauth appropriately, that's why it's setup like that in the code above.

How can I configure two authentication sources independent of one another in a single Oauth2-enabled application?

Regards.

like image 654
Cenobyte321 Avatar asked Dec 08 '15 16:12

Cenobyte321


1 Answers

You need two things:

  1. Make sure your AdminSecurityConfig has a higher priority than your ResourceServerConfiguration. While the @EnableResourceServer annotation's documentation says it will register a WebSecurityConfigurerAdapter with a hard-coded Order 3, it's actually overridden in ResourceServerOrderProcessor with an order of -10. So make sure your AdminSecurityConfig has an order lower than -10.
  2. Make sure you limit your configuration of HttpSecurity in AdminSecurityConfig with request matchers to the URLs associated with your admin server, like this:

    http.requestMatchers().antMatchers("/admin/**", "/admin_login", "/admin_logout")
        .and()
            .authorizeRequests()
            .antMatchers("/admin/protected.html").hasRole("ADMIN")
            .antMatchers("/admin/login.html").permitAll()
        .and()
            .formLogin().loginPage("/admin/login.html")
            .loginProcessingUrl("/admin_login")
            .defaultSuccessUrl("/admin/protected.html")
        .and()
            .logout().logoutRequestMatcher(new AntPathRequestMatcher("/admin_logout"))
            .invalidateHttpSession(true).logoutSuccessUrl("/admin/login.html")
            ;
    

    Note the first line of the embedded code with http.requestMatchers().antMatchers("/admin/**", "/admin_login", "/admin_logout").

See Dave Syer's (one of Spring Security authors) answer on a similar question for reference.

I made a pull request with the above fixes for your example project on github.

like image 119
Nándor Előd Fekete Avatar answered Sep 23 '22 15:09

Nándor Előd Fekete