Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security OAuth2 - @EnableOauth2Sso but accept tokens as authentication, too

I have an application which has @EnableOAuth2Sso on the WebSecurityConfigurerAdapter

After adding @EnableOAuth2Ssothe application redirects me to the authorization server and allows access after login at this authorization server. I want to offer API access as well, so i want applications be able to access my resources by passing an accesstoken via the Authorization-Header

Authorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... 

I debuged through the authentication filter which is used with @EnableOAuth2Sso noticed, that Authorization-Header value is not checked.

After that i tried to create a custom filter and added this filter to the security configuration

@Override
public void configure(HttpSecurity http) throws Exception {
  http.addFilter(myCustomFilter)
    ...;
}

But now i get the following Exception:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
    ... 26 more
Caused by: org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:44)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain(WebSecurityConfiguration.java:105)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$f0788cea.CGLIB$springSecurityFilterChain$5(<generated>)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$f0788cea$$FastClassBySpringCGLIB$$7e95689d.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:318)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$f0788cea.springSecurityFilterChain(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)

At first i thought i've done something wrong inside my filter but i ended up with a plain filter class doing nothing else than proceed the filterchain and still having the same error.

So i have two questions:

  1. Why do i get this exception?
  2. Is there a way to allow token authentication for endpoints in an application which uses @EnableOAuth2Sso ?
like image 830
Yannic Klem Avatar asked Jan 11 '16 09:01

Yannic Klem


2 Answers

The reason for the exception was the ordering of the filters like @jah said.

What i did to achieve the authentication of requests, containing an access token in the Authorization-Header, is to create a class ApiTokenAccessFilter which extends OAuth2AuthenticationProcessingFilter. This filter takes a ResourceServerTokenServices constructor parameter and sets the stateless flag to false.

public class ApiTokenAccessFilter extends OAuth2AuthenticationProcessingFilter {

  public ApiTokenAccessFilter(ResourceServerTokenServices resourceServerTokenServices) {

    super();
    setStateless(false);
    setAuthenticationManager(oauthAuthenticationManager(resourceServerTokenServices));
  }

  private AuthenticationManager oauthAuthenticationManager(ResourceServerTokenServices tokenServices) {

    OAuth2AuthenticationManager oauthAuthenticationManager = new OAuth2AuthenticationManager();

    oauthAuthenticationManager.setResourceId("oauth2-resource");
    oauthAuthenticationManager.setTokenServices(tokenServices);
    oauthAuthenticationManager.setClientDetailsService(null);

    return oauthAuthenticationManager;
  }
}

In my security config i used this Filter as follows:

@Configuration
@EnableOAuth2Sso
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Autowired
  private ResourceServerTokenServices tokenServices;

  @Override
  public void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
        .anyRequest()
        .authenticated()
        .and()
        .addFilterBefore(new ApiTokenAccessFilter(tokenServices), AbstractPreAuthenticatedProcessingFilter.class);
  }
}

I think this could be easier so i opened an issue on the spring-security-oauth Github repo. I'm not sure whether this solution is the way to go, but i didn't find another alternative.

like image 80
Yannic Klem Avatar answered Nov 01 '22 08:11

Yannic Klem


This is an answer for your first question. You getting this exception because you are trying to add a filter to a filer chain without specifying an order. The filter chain consist of several filters in a fixed order. The exception is thrown in the check for the existenceof the filter to add. The org.springframework.security.config.annotation.AlreadyBuiltException in the AbstractSecurityBuilder when an exception happens inside it. So a wide range of exceptions happening inside the AbstractSecurityBuilder are causing this unrelated exception.

A possible way to add your filter would be to use the addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter) or the addFilterAfter(Filter filter, Class<? extends Filter> afterFilter) methods of HttpSecurity.

Regarding your 2nd question, you should provide more information.

like image 25
Hendrik Jander Avatar answered Nov 01 '22 08:11

Hendrik Jander