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 a
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:
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.