2

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:

AdrienW
  • 3,092
  • 6
  • 29
  • 59
  • If I have understood correctly you are trying to avoid the authentication for some endpoints and does not want to apply the filter for that endpoints is it? – Romil Patel Jun 29 '20 at 15:02
  • In a way, yes. Actually, I want to manipulate the `SecurityContext` in some cases, so that no `/oauth/user` request gets sent and instead of this my `CustomAuthentication` is used. But when `meetsCondition()` evaluates to false, all should work as normal. – AdrienW Jun 29 '20 at 15:05
  • For `/oauth/user` you want to invoke your `CustomAuthentication` that will manipulate the security context and for the rest of endpoint it should work normally. you may use `http.antMatcher` for the same If this is the case let me know I can add more details on it – Romil Patel Jun 29 '20 at 15:09
  • As much as I see, spring security filter chain has changed unexpectedly with and without custom SessionFilter. In past, what helped me was to print the spring security filters chain in logs (https://www.baeldung.com/spring-security-registered-filters). Can you please update the question with registered filter chain with and without custom SessionFilter in spring context? – Avnish Jul 04 '20 at 17:20

2 Answers2

0

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.

Anonymous Beaver
  • 370
  • 2
  • 10
  • What do you suggest to prevent #2? I actually think (from the Logs) that it's in there only once – AdrienW Jul 06 '20 at 05:05
  • 1
    Ah, if your logs are already indicating that it's only being called once, then there probably isn't an issue. I wonder if it points to some configuration issue that is leading to the OAuth2 filter not being called. In my case, I used the OncePerRequestFilter which works in basically the same way as the Generic Filter Bean, but guarantees that it is only called once – Anonymous Beaver Jul 06 '20 at 13:15
-1

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
                 );
  • Already tried this, it did not seem to change anything :/ the `SessionFilter` is being used at the right place in the filter chain, but the rest of the chain seems broken. I can edit the question if the problem is unclear. – AdrienW Jun 29 '20 at 10:42