I am trying to configure a spring boot web application to use basic http security which will be used for web pages, and additionally I need to implement OAuth2 security for an android application to connect.
The problem I have is that OAuth security is overriding basic http security. Searching in google I found that it is due to the execution order of the security filters, so the ResourceServer had to be annotated with @Order(3) and the WebSecurityConfigurerAdapter with @Order(1) so that basic security would be applied first. . However I find that the basic http logs in fine, but when it tries to authenticate the user roles, it doesn't take them. The OAuth Authorization server does work and generates the token, but when it tries to access the protected resources, it either does not take the roles assigned to the user or simply does not protect the resources.
It is as if by mixing both systems, one overwrites the other.
What would be the correct way to integrate both functions (basic http and OAuth) in the same spring boot application? I read something about http.antMatchers but I can't figure it out.
WebSecurityConfig.class
@Configuration
@EnableResourceServer
@Order(1)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private Logger log = LoggerFactory.getLogger(SecurityConfig.class);
@Override
protected void configure(HttpSecurity http) throws Exception {
log.info("Configurando http security web");
http.httpBasic();
// Indica los recursos a proteger
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/home", "/about").permitAll()
.antMatchers("/user/**").authenticated()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/cuenta/**").access("hasAnyRole('USER','ADMIN')");
// Administra la sesion
/*http.sessionManagement()
.invalidSessionUrl("/invalidSession.html")
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);*/
// Configura el login
http.formLogin()
.successHandler(savedRequestAwareAuthenticationSuccessHandler())
.loginPage("/login").permitAll()
.failureUrl("/login?error")
.loginProcessingUrl("/auth/login_check")
.usernameParameter("username")
.passwordParameter("password");
// Configura el logout
/*http.logout()
.permitAll()
.logoutSuccessUrl("/login?logout");*/
// Configura la opcion recuerdame de la sesion
http.rememberMe()
.tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(60); //1209600
//super.configure(http);
}
@Autowired
private DataSource dataSource;
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public static PasswordEncoder passwordEncoder() {
//return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setPasswordEncoder(passwordEncoder());
authProvider.setUserDetailsService(customUserDetailsService);
return authProvider;
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl = new JdbcTokenRepositoryImpl();
jdbcTokenRepositoryImpl.setDataSource(dataSource);
return jdbcTokenRepositoryImpl;
}
@Bean
public SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler () {
SavedRequestAwareAuthenticationSuccessHandler authenticationSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler();
authenticationSuccessHandler.setTargetUrlParameter("targetUrl");
return authenticationSuccessHandler;
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(authProvider());
}
}
ResourceServerConfig.class
@Configuration
@EnableResourceServer
@Order(2)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private Logger log = LoggerFactory.getLogger(ResourceServerConfig.class);
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
.resourceId("recursoUno");
}
@Override
public void configure(HttpSecurity http) throws Exception {
log.info("Configurando http security oauth");
// Indica los recursos a proteger
http.authorizeRequests()
.antMatchers("/api/v1.0/secure").hasRole("ADMIN")
.antMatchers("/api/v1.0/**").authenticated();
// Configurar el estado de la sesion oauth como stateless
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Habilitar csrf para oauth
/*http.csrf()
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize"))
.disable();*/
/*http.authorizeRequests()
.antMatchers("/api/v1.0/secure").hasRole("ADMIN")
.antMatchers("/api/v1.0/**").permitAll();*/
// Configura el logout
/*http.logout()
.logoutUrl("/oauth/logout");*/
}
}
I finally managed to get the basic http security working along with the oauth security that I need for the android app. The use of the @Order annotation was not necessary. Thanks to the help published in this link I was able to get the answer. Here the code.
WebSecurityConfig.class
ResourceServer.class