Multiple Spring's SecurityConfigs not working - spring

I'm trying to configure two SecurityConfigs simultaneously. The SecurityConfig requires an Oauth authorization at Keycloak Auth Server (embedded in a separate Spring app). The OauthSecurityConfig requires an Oauth authorization at GoogleApi. Both configs DO work, when implemented separately (when I define just one config at a time).
Right now, only one of them works (the one annotated with #Order(1)). I'm trying to implementing them both in the following way:
#EnableWebSecurity
public class MultiSecurityConfig {
#Configuration
#Order(1)
public static class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/auth/**")
.hasAnyAuthority("SCOPE_read", "SCOPE_write")
.anyRequest()
.permitAll()
.and()
.oauth2ResourceServer()
.jwt();
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
#Configuration
public static class OauthSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/oauth/**")
.authenticated()
.anyRequest()
.permitAll()
.and()
.oauth2Login();
}
}
}
What am I doing wrong?

It turns out that for multiple SecurityConfigs to work you have to define '.antMatcher()` at each config, like so:
http.antMatcher("/auth/**").cors()
.and()
...

Related

Hww to bind two SecurityFilterChain respectively? [duplicate]

I am trying to use Spring Security and I have a use case where I want different login pages and different set of URLs to be secured.
Here is my configuration:
#Configuration
#Order(1)
public static class ProviderSecurity extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.antMatchers("/admin/login").permitAll()
.antMatchers("/admin/**").access("hasRole('BASE_USER')")
.and()
.formLogin()
.loginPage("/admin/login").permitAll()
.defaultSuccessUrl("/admin/home")
.failureUrl("/admin/login?error=true").permitAll()
.usernameParameter("username")
.passwordParameter("password")
.and()
.csrf()
.and()
.exceptionHandling().accessDeniedPage("/Access_Denied");
}
}
#Configuration
#Order(2)
public static class ConsumerSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/consumer/login").permitAll()
.antMatchers("/consumer/**").access("hasRole('BASE_USER')")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/consumer/login").permitAll()
.defaultSuccessUrl("/consumer/home")
.failureUrl("/consumer/login?error=true").permitAll()
.usernameParameter("username")
.passwordParameter("password")
.and().csrf()
.and()
.exceptionHandling().accessDeniedPage("/Access_Denied");
}
}
These classes are inner classes of another class MultipleHttpSecurityConfig that has annotation #EnableWebSecurity.
The security for admin/** is working fine, but none of the consumer/** pages are secured, no redirection is happening for login page. I've searched for other answers but none worked.
Look at the Spring Security Reference:
#EnableWebSecurity
public class MultiHttpSecurityConfig {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) { 1
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
#Configuration
#Order(1) 2
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**") 3
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}
#Configuration 4
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin();
}
}
}
1 Configure Authentication as normal
2 Create an instance of WebSecurityConfigurerAdapter that contains #Order to specify which WebSecurityConfigurerAdapter should be considered first.
3 The http.antMatcher states that this HttpSecurity will only be applicable to URLs that start with /api/
4 Create another instance of WebSecurityConfigurerAdapter. If the URL does not start with /api/ this configuration will be used. This configuration is considered after ApiWebSecurityConfigurationAdapter since it has an #Order value after 1 (no #Order defaults to last).
Your second configuration is not used, because your first configuration matches /** (no antMatcher configured). And your first configuration restricts only /admin/**, all other URLs are permitted by default.
Your first WebSecurityConfigurerAdapter's
http
.authorizeRequests()
matches all the URLs, limit it to only URLs start with /admin by using antMatcher:
#Configuration
#Order(1)
public static class ProviderSecurity extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/admin/**")
.authorizeRequests()
.antMatchers("/admin/login").permitAll()
.antMatchers("/admin/**").access("hasRole('BASE_USER')")
.and()
...

Spring Resource Server Multi-tenancy with BasicAuth

So I tried Resource Server Multi-tenancy using Spring docs and
everything works fine, I can pass two different token to access my resource. My question is how do I add BasicAuth functionality to this. I want my resource to be accessible by either of the oauth2 tokens or BasicAuth. I have individual solutions but I am not able to combine both for some reason.
Working solution -> Resource server Multi-tenancy
#EnableWebSecurity
#Order(1)
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.httpBasic()
.disable()
.authorizeRequests(auth -> auth
.anyRequest().authenticated()
).oauth2ResourceServer(oauth2ResourceServer -> {
oauth2ResourceServer.authenticationManagerResolver(this.authenticationManagerResolver);
});
}
//...
Working Solution -> Oauth and BasicAuth both to access same resource
I came across this solution which does this
https://stackoverflow.com/a/36243650/2188126
#EnableWebSecurity
#Order(1)
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.requestMatcher(new BasicRequestMatcher())
.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(new OAuth2AuthenticationEntryPoint())
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
//...
Here's what I have tried(and few other variations) but doesn't work. -> Multi-tenancy + Basic Auth
#EnableWebSecurity
#Order(1)
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.requestMatcher(new BasicRequestMatcher())
.authorizeRequests().anyRequest().authenticated()
.and()
.oauth2ResourceServer(oauth2ResourceServer -> {
oauth2ResourceServer.authenticationManagerResolver(this.authenticationManagerResolver);
})
.httpBasic()
.authenticationEntryPoint(new OAuth2AuthenticationEntryPoint())
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
//...
Here's my resource server config file
#Configuration
#EnableResourceServer
public class Oauth2SecurityConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(AUTH_WHITELIST).permitAll()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.anyRequest().authenticated();
}
}

Multiple authentication methods for one endpoint? [duplicate]

I am trying to use Spring Security and I have a use case where I want different login pages and different set of URLs to be secured.
Here is my configuration:
#Configuration
#Order(1)
public static class ProviderSecurity extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.antMatchers("/admin/login").permitAll()
.antMatchers("/admin/**").access("hasRole('BASE_USER')")
.and()
.formLogin()
.loginPage("/admin/login").permitAll()
.defaultSuccessUrl("/admin/home")
.failureUrl("/admin/login?error=true").permitAll()
.usernameParameter("username")
.passwordParameter("password")
.and()
.csrf()
.and()
.exceptionHandling().accessDeniedPage("/Access_Denied");
}
}
#Configuration
#Order(2)
public static class ConsumerSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/consumer/login").permitAll()
.antMatchers("/consumer/**").access("hasRole('BASE_USER')")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/consumer/login").permitAll()
.defaultSuccessUrl("/consumer/home")
.failureUrl("/consumer/login?error=true").permitAll()
.usernameParameter("username")
.passwordParameter("password")
.and().csrf()
.and()
.exceptionHandling().accessDeniedPage("/Access_Denied");
}
}
These classes are inner classes of another class MultipleHttpSecurityConfig that has annotation #EnableWebSecurity.
The security for admin/** is working fine, but none of the consumer/** pages are secured, no redirection is happening for login page. I've searched for other answers but none worked.
Look at the Spring Security Reference:
#EnableWebSecurity
public class MultiHttpSecurityConfig {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) { 1
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
#Configuration
#Order(1) 2
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**") 3
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}
#Configuration 4
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin();
}
}
}
1 Configure Authentication as normal
2 Create an instance of WebSecurityConfigurerAdapter that contains #Order to specify which WebSecurityConfigurerAdapter should be considered first.
3 The http.antMatcher states that this HttpSecurity will only be applicable to URLs that start with /api/
4 Create another instance of WebSecurityConfigurerAdapter. If the URL does not start with /api/ this configuration will be used. This configuration is considered after ApiWebSecurityConfigurationAdapter since it has an #Order value after 1 (no #Order defaults to last).
Your second configuration is not used, because your first configuration matches /** (no antMatcher configured). And your first configuration restricts only /admin/**, all other URLs are permitted by default.
Your first WebSecurityConfigurerAdapter's
http
.authorizeRequests()
matches all the URLs, limit it to only URLs start with /admin by using antMatcher:
#Configuration
#Order(1)
public static class ProviderSecurity extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/admin/**")
.authorizeRequests()
.antMatchers("/admin/login").permitAll()
.antMatchers("/admin/**").access("hasRole('BASE_USER')")
.and()
...

multiple entry points in spring security

I have a spring boot application that should allow form based authentication against database and SSO CAS based authentication.
I have followed the example from here (https://www.baeldung.com/spring-security-multiple-entry-points) and seems to me that Order is not working as expected. it is always using the one that is annotated as Order(1) as entry point.
here is my code,
#Configuration
#EnableWebSecurity
public class SecurityConfig {
#Configuration
#Order(2)
public static class WebSecurityCASConfig extends WebSecurityConfigurerAdapter {
public WebSecurityCASConfig() {
super();
}
#Autowired
private AuthenticationEntryPoint authenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(
"/js/**",
"/css/**",
"/images/**").permitAll()
.regexMatchers("/login1")
.authenticated()
.and()
.authorizeRequests()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint);
}
}
//second
#Configuration
#Order(1)
public static class WebSecurityDatabaseConfig extends WebSecurityConfigurerAdapter {
public WebSecurityDatabaseConfig() {
super();
}
#Autowired
UserDetailServiceImpl userDetailsService;
#Autowired
BCryptPasswordEncoder passwordEncoder;
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(
"/js/**",
"/css/**",
"/images/**").permitAll()
//.antMatchers("/catalog").access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')")
////.antMatchers("/login1").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/catalog", true)
.permitAll()
.usernameParameter("username")
.passwordParameter("password")
.and()
.logout()
.permitAll()
.logoutUrl("/logout").logoutSuccessUrl("/logout")
.and().exceptionHandling().accessDeniedPage("/403");
}
}
}
I want both configurations work based on url pattern. Any solutions/help/suggestions would be highly appreciated. Thanks.
I found a solution for this. I just simply followed what the spring document says in 5.9 (https://docs.spring.io/spring-security/site/docs/5.0.0.RELEASE/reference/htmlsingle/) and also another question on stackoverflow, Spring Security : Multiple HTTP Config not working

Configuring Spring Security for Form Login AND RESTful API [duplicate]

I am trying to use Spring Security and I have a use case where I want different login pages and different set of URLs to be secured.
Here is my configuration:
#Configuration
#Order(1)
public static class ProviderSecurity extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.antMatchers("/admin/login").permitAll()
.antMatchers("/admin/**").access("hasRole('BASE_USER')")
.and()
.formLogin()
.loginPage("/admin/login").permitAll()
.defaultSuccessUrl("/admin/home")
.failureUrl("/admin/login?error=true").permitAll()
.usernameParameter("username")
.passwordParameter("password")
.and()
.csrf()
.and()
.exceptionHandling().accessDeniedPage("/Access_Denied");
}
}
#Configuration
#Order(2)
public static class ConsumerSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/consumer/login").permitAll()
.antMatchers("/consumer/**").access("hasRole('BASE_USER')")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/consumer/login").permitAll()
.defaultSuccessUrl("/consumer/home")
.failureUrl("/consumer/login?error=true").permitAll()
.usernameParameter("username")
.passwordParameter("password")
.and().csrf()
.and()
.exceptionHandling().accessDeniedPage("/Access_Denied");
}
}
These classes are inner classes of another class MultipleHttpSecurityConfig that has annotation #EnableWebSecurity.
The security for admin/** is working fine, but none of the consumer/** pages are secured, no redirection is happening for login page. I've searched for other answers but none worked.
Look at the Spring Security Reference:
#EnableWebSecurity
public class MultiHttpSecurityConfig {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) { 1
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
#Configuration
#Order(1) 2
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**") 3
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}
#Configuration 4
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin();
}
}
}
1 Configure Authentication as normal
2 Create an instance of WebSecurityConfigurerAdapter that contains #Order to specify which WebSecurityConfigurerAdapter should be considered first.
3 The http.antMatcher states that this HttpSecurity will only be applicable to URLs that start with /api/
4 Create another instance of WebSecurityConfigurerAdapter. If the URL does not start with /api/ this configuration will be used. This configuration is considered after ApiWebSecurityConfigurationAdapter since it has an #Order value after 1 (no #Order defaults to last).
Your second configuration is not used, because your first configuration matches /** (no antMatcher configured). And your first configuration restricts only /admin/**, all other URLs are permitted by default.
Your first WebSecurityConfigurerAdapter's
http
.authorizeRequests()
matches all the URLs, limit it to only URLs start with /admin by using antMatcher:
#Configuration
#Order(1)
public static class ProviderSecurity extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/admin/**")
.authorizeRequests()
.antMatchers("/admin/login").permitAll()
.antMatchers("/admin/**").access("hasRole('BASE_USER')")
.and()
...

Resources