Describe the bug Keycloak for spring-boot adds two filters successively which results in a NPE:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                ...
                .addFilterAfter(keycloakSecurityContextRequestFilter(), SecurityContextHolderAwareRequestFilter.class)
                .addFilterAfter(keycloakAuthenticatedActionsRequestFilter(), KeycloakSecurityContextRequestFilter.class)
                ...
    }

which causes:

Caused by: java.lang.NullPointerException: null
    at org.springframework.security.config.annotation.web.builders.HttpSecurity.addFilterAtOffsetOf(HttpSecurity.java:2654) ~[spring-security-config-5.5.0.jar:5.5.0]
    at org.springframework.security.config.annotation.web.builders.HttpSecurity.addFilterAfter(HttpSecurity.java:2645) ~[spring-security-config-5.5.0.jar:5.5.0]
    at org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter.configure(KeycloakWebSecurityConfigurerAdapter.java:123) ~[keycloak-spring-security-adapter-13.0.0.jar:13.0.0]

To Reproduce Add a filter just after one you manually added.

Expected behavior Second filter should be added successfully after the first one.

Sample KeycloakSpringBootSampleApp from this repo: https://github.com/ch4mpy/spring-addons

Run tests or the KeycloakSpringBootSampleApp from an IDE

Possible Cause Maybe should an entry be added to this.filterOrders after the filter is added to this.filters there: https://github.com/spring-projects/spring-security/blob/488683f5a5658003b96ee7d01c9e5c952a3f1f64/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java#L2655

Comment From: theexiile1305

This error concerns me and my context can be found under the following stackoverflow thread: https://stackoverflow.com/questions/67683336/spring-boot-upgrade-2-4-5-to-2-5-issue-npe-springsecurityfilterchain

Comment From: ThomasVitale

The same bug is also reported here: https://github.com/spring-projects/spring-security/issues/9787

Comment From: robert-bor

ch4mpy's suggestion looks legit, the filterOrders are not appended with key filter class and the new order. Putting the class with the applied order looks like it will do the trick.

In HttpSecurity.addFilterAtOffsetOf:

private HttpSecurity addFilterAtOffsetOf(Filter filter, int offset, Class<? extends Filter> registeredFilter) {
        int order = this.filterOrders.getOrder(registeredFilter) + offset;
        this.filters.add(new OrderedFilter(filter, order));
        return this;
    }

Add this line:

        this.filterOrders.put(filter.getClass(), order);

Note that the order assigning process is rather coarse, just +1/-1. If you add two filters before the same filter, they appear to get the same order number with no certain way of knowing how the sorting will work out. Therefore the above solution may result in new issues.

Note also that FilterOrderRegistration.put() is private.

Comment From: sjohnr

@ch4mpy - Thanks for the bug report, your research and willingness to help are greatly appreciated!

I'm going to close this issue in favor of #9787. Please feel free to continue the conversation there.