Inserting Spring-Security filter apparently breaks filter chain

Viewed 889

In my Spring-Boot Application (Resource Server), I want to skip the token-check against the Authorization Server in some cases. To achieve this, I inserted a filter before the SecurityContextPersistenceFilter in the Spring-Security filter chain.

Ideally, I want things not to be changed when the condition is not met (Authorization Server called, Authentication set according to response). I found out that, while the Security Context gets overwritten when the condition is met, problem occurs when the filter does nothing: In that case, the OAuth2AuthenticationProcessingFilter does not appear at all in the chain and I am left with the "anonymousUser".

Here is what my custom filter looks like:

public class SessionFilter extends GenericFilterBean {

    @Override
    public void doFilter(
        ServletRequest servletRequest,
        ServletResponse servletResponse,
        FilterChain filterChain
    ) throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        String authorizationHeader = httpRequest.getHeader(HttpHeaders.AUTHORIZATION);
        
        if (authorizationHeader != null && meetsCondition(authorizationHeader)) {
            SecurityContext sc = SecurityContextHolder.getContext();
            sc.setAuthentication(new CustomAuthentication(authorizationHeader));
            httpRequest.getSession(true)
                    .setAttribute(SPRING_SECURITY_CONTEXT_KEY, sc);
        }

        filterChain.doFilter(servletRequest, servletResponse);
    }
}

It gets thrown in the chain using the WebSecurityConfigurerAdapter:

        http  //...
                .and().csrf().disable()
                .addFilterBefore(
                        new SessionFilter(),
                        SecurityContextPersistenceFilter.class
                 );

Is there a way to achieve what I am looking for using this method? I am using Spring-Boot 1.4.7 with Java 8 and Spring-Security 4.1.4 (upgrading is sadly not possible for reasons external to this question).

Sources which I based my code/understanding on:

2 Answers

I don't see anything particularly unique or strange about your filter, so the problem probably isn't with the filter itself, but rather with the rest of your configuration. I just have a couple of notes

  1. Have you confirmed that the OAuth2 filter was working correctly before you put in this custom class? Did you add it manually or with the @EnableResourceServer annotation?

  2. I noticed that you use a GenericFilterBean and add it manually. I think that Spring Security will automatically scan for GenericFilterBeans and add it to the filter chain so it might end up in your chain twice.

I think the problem lies the way you are injecting the Session Filter in the WebSecurityConfigurerAdapter.

http  //...
                .and().csrf().disable()
                .addFilterBefore(
                        new SessionFilter(), // The session filter here is never set in the application context the way you want it to.
                        SecurityContextPersistenceFilter.class
                 );

Refer to this answer for a better understanding of how to use auto wiring. How does autowiring work in Spring?

You can try this block of code if it helps your cause.

@Autowire 
SessionFilter sessionFilter;

http  //...
                .and().csrf().disable()
                .addFilterBefore(
                        sessionFilter,
                        SecurityContextPersistenceFilter.class
                 );
Related