Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring security with Oauth2 or Http-Basic authentication for the same resource

I'm attempting to implement an API with resources that are protected by either Oauth2 OR Http-Basic authentication.

When I load the WebSecurityConfigurerAdapter which applies http-basic authentication to the resource first, Oauth2 token authentication is not accepted. And vice-versa.

Example configurations: This applies http-basic authentication to all /user/** resources

@Configuration @EnableWebMvcSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {      private LoginApi loginApi;      @Autowired     public void setLoginApi(LoginApi loginApi) {         this.loginApi = loginApi;     }      @Override     protected void configure(AuthenticationManagerBuilder auth) throws Exception {         auth.authenticationProvider(new PortalUserAuthenticationProvider(loginApi));     }      @Override     protected void configure(HttpSecurity http) throws Exception {         http             .authorizeRequests()                 .antMatchers("/users/**").authenticated()                 .and()             .httpBasic();     }      @Override     @Bean     public AuthenticationManager authenticationManagerBean() throws Exception {         return super.authenticationManagerBean();     } } 

This applies oauth token protection to the /user/** resource

@Configuration @EnableResourceServer protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {      @Override     public void configure(HttpSecurity http) throws Exception {         http             .requestMatchers().antMatchers("/users/**")         .and()             .authorizeRequests()                 .antMatchers("/users/**").access("#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.hasScope('read')");     } } 

I'm sure there is some piece of magic code I'm missing which tells spring to attempt both if the first has failed?

Any assistance would be most appreciated.

like image 417
user3613594 Avatar asked May 07 '14 19:05

user3613594


People also ask

Which authentication is best in spring boot?

You can use custom token based implementation, you can create a custom token that you can store in DB but JWT is a good choice.

What is the difference between basic auth and OAuth2?

Unlike Basic Auth, where you have to share your password with people who need to access your user account, OAuth doesn't share password data. Instead, OAuth uses authorization tokens to verify an identity between consumers and service providers.

Does Spring Security use OAuth2?

Spring Security handles the Authentication and Spring Security OAuth2 handles the Authorization. To configure and enable the OAuth 2.0 Authorization Server we have to use @EnableAuthorizationServer annotation.

Is Spring Security OAuth2 deprecated?

End of Life NoticeThe Spring Security OAuth project has reached end of life and is no longer actively maintained by VMware, Inc. This project has been replaced by the OAuth2 support provided by Spring Security and Spring Authorization Server.


1 Answers

I managed to get this work based on the hints by Michael Ressler's answer but with some tweaks.

My goal was to allow both Basic Auth and Oauth on the same resource endpoints, e.g., /leafcase/123. I was trapped for quite some time due to the ordering of the filterChains (can be inspected in FilterChainProxy.filterChains); the default order is as follows:

  • Oauth authentication server (if enabled in the same project)'s filterChains. default order 0 (see AuthorizationServerSecurityConfiguration)
  • Oauth resource server's filterChains. default order 3 (see ResourceServerConfiguration). It has a request matcher logic that matches anything other than the Oauth authentication endpoints (e.g., /oauth/token, /oauth/authorize, etc. See ResourceServerConfiguration$NotOauthRequestMatcher.matches()).
  • The filterChains that corresponds to config(HttpSecurity http) - default order 100, see WebSecurityConfigurerAdapter.

Since resource server's filterChains ranks higher than the one by WebSecurityConfigurerAdapter configured filterchain, and the former matches practically every resource endpoint, then Oauth resource server logic always kick in for any request to resource endpoints (even if the request uses the Authorization:Basic header). The error you would get is:

{     "error": "unauthorized",     "error_description": "Full authentication is required to access this resource" } 

I made 2 changes to get this work:

Firstly, order the WebSecurityConfigurerAdapter higher than the resource server (order 2 is higher than order 3).

@Configuration @Order(2) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

Secondly, let configure(HttpSecurity) use a customer RequestMatcher that only matches "Authorization: Basic".

@Override protected void configure(HttpSecurity http) throws Exception {      http         .anonymous().disable()         .requestMatcher(new BasicRequestMatcher())         .authorizeRequests()             .anyRequest().authenticated()             .and()         .httpBasic()              .authenticationEntryPoint(oAuth2AuthenticationEntryPoint())             .and()         // ... other stuff  }  ...  private static class BasicRequestMatcher implements RequestMatcher {     @Override     public boolean matches(HttpServletRequest request) {         String auth = request.getHeader("Authorization");         return (auth != null && auth.startsWith("Basic"));     }  } 

As a result it matches and handles a Basic Auth resource request before the resource server's filterChain has a chance to match it. It also ONLY handles Authorizaiton:Basic resource request, thus any requests with Authorization:Bearer will fall through, and then handled by resource server's filterChain (i.e., Oauth's filter kicks in). Also, it ranks lower than the AuthenticationServer (in case AuthenticationServer is enabled on the same project), so it doesn't prevent AuthenticaitonServer's filterchain from handling the request to /oauth/token, etc.

like image 127
kca2ply Avatar answered Oct 12 '22 00:10

kca2ply