spring-projects / spring-projects/spring-security
Customizing AccessDeniedHandler for MissingCsrfTokenException when an InvalidSessionStrategy exists
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 9.6k
- Forks
- 6.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 52
Description
Use case
Signaling a CSRF problem to client app via 403 or some other status-code, while invalid sessions result in 401. For example in a SPA 401 might trigger re-authentication, while missing CSRF token might be an issue for a single request (which wouldn't need / want re-authentication).
Problem
I didn't find a "proper" way to handle / customize handling for missing CSRF token (MissingCsrfTokenException). I was expecting to get the error into AccessDeniedHandler specified in the ExceptionHandlingConfigurer.
I tracked the possible cause to CsrfConfigurer.createAccessDeniedHandler (code below) where a defined InvalidSessionStrategy results in instantiating a DelegatingAccessDeniedHandler with MissingCsrfTokenException mapped to an instantiated InvalidSessionAccessDeniedHandler, which in turn calls invalidSessionStrategy.onInvalidSessionDetected and drops the info on cause / exception. So a defined InvalidSessionStrategy takes precedence over an AccessDeniedHandler.
It surprised me a bit that a missing CSRF token leads to "invalid session detected".
private AccessDeniedHandler createAccessDeniedHandler(H http) {
InvalidSessionStrategy invalidSessionStrategy = getInvalidSessionStrategy(http);
AccessDeniedHandler defaultAccessDeniedHandler = getDefaultAccessDeniedHandler(http);
if (invalidSessionStrategy == null) {
return defaultAccessDeniedHandler;
}
InvalidSessionAccessDeniedHandler invalidSessionDeniedHandler = new InvalidSessionAccessDeniedHandler(
invalidSessionStrategy);
LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler> handlers = new LinkedHashMap<>();
handlers.put(MissingCsrfTokenException.class, invalidSessionDeniedHandler);
return new DelegatingAccessDeniedHandler(handlers, defaultAccessDeniedHandler);
}
Possible solution
It would be nice to just handle the MissingCsrfTokenException directly via AccessDeniedHandler defined in ExceptionHandlingConfigurer (just like InvalidCsrfTokenException can be handled) or specify a custom AccessDeniedHandler for the CsrfConfigurer, which would take precedence over InvalidSessionStrategy.
Workarounds
Easy workaround is to have a custom CsrfTokenRequestAttributeHandler with resolveCsrfTokenValue returning String "null" instead of null-value CSRF token is missing, leading to InvalidCsrfTokenException instead of MissingCsrfTokenExeption.
It's also possible to handle the issue in the InvalidSessionStrategy.onInvalidSessionDetected by checking if the request should've had CSFR-token and whether it did, but this would start duplicating CSRF-logic there.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.