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.