I’m trying to use the @EnableOAuth2Sso feature in Spring Cloud Security. Specifically, I’m attempting to protect some resources with OAuth2 while leaving others publicly accessible. I've managed to get this working, but I'm looking at the resulting code and wondering if there is a cleaner way.
I’m following the documentation here: https://github.com/spring-cloud/spring-cloud-security/blob/master/src/main/asciidoc/spring-cloud-security.adoc AND similar guidance from the Spring Boot reference. I have a tiny code example that illustrates my dilemma: https://github.com/kennyk65/oAuthSsoExample.
In a nutshell, I want the localhost:8080/unprotected resource to be publicly available, and I want the localhost:8080/protected resource to require OAuth2 (via github, as configured). I’m able to get the basic OAuth2 behavior to work just fine, but causing /unprotected to be publicly available is problematic.
First, The docs indicate that you can just use the OAuth2SsoConfigurer’s match() method to specify the resources to protect. I've found this doesn't work; when I try I get an IllegalStateException saying that at least one mapping is required. This appears to be referring to the unimplemented configure(HttpSecurity) method.
Next, I’ve tried to specify a mapping in configure(HttpSecurity) that states that the ‘unprotected’ resources should be unprotected. However, this results in Http basic security being applied to that resource. Curiously, this results in the ‘protected’ resource being completely public!
// This results in “unprotected” being protected by HTTP Basic
// and “protected” being completely open!
@Configuration
protected static class OauthConfig extends OAuth2SsoConfigurerAdapter {
@Override
public void match(RequestMatchers matchers) {
matchers.antMatchers("/protected/**");
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/unprotected/**").permitAll();
}
}
On a whim I tried deliberately adding that the protected resource should be authenticated. This resulted in the protected resource getting OAuth2 protection (hurrah!) but the unprotected resource got http basic security applied (huh?).
// This results in “protected” being protected by OAuth 2
// and “unprotected” being protected by HTTP Basic, even though we say permitAll():
@Configuration
protected static class OauthConfig extends OAuth2SsoConfigurerAdapter {
@Override
public void match(RequestMatchers matchers) {
matchers.antMatchers("/protected/**");
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/protected/**”).authenticated();
.antMatchers("/unprotected/**").permitAll();
}
}
At wit’s end to try to find the magic combination, I tried simply switching HTTP basic authentication off using security.basic.enabled: false. This worked (hurrah!), though I’m still a bit puzzled what the issue is with the mappings.
So I guess my question is, is this correct? What is the best way to protect some resources with OAuth 2 and leave others alone?
If you match on /protected/**
then it makes no sense to then add an access rule to /unprotected/**
(the path doesn't match so the rule will never be applied). You either need another filter chain for your "unprotected" resources, or a wider match for the SSO one. In the former case, the default one that you get from Spring Security will do if you don't mind switching off the security it is providing. E.g.
@Configuration
protected static class OauthConfig extends OAuth2SsoConfigurerAdapter {
@Override
public void match(RequestMatchers matchers) {
matchers.antMatchers("/protected/**");
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**”).authenticated();
}
}
and set security.basic.enabled=false
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With