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.