-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SecurityMockMvcRequestPostProcessors.csrf()
doesn't work with XorCsrfTokenRequestAttributeHandler
#14125
Comments
Hey, @ch4mpy, thank you for the reproducer, it was very helpful. I talked briefly with @sjohnr about this and this is the current recommendation for working with SPAs and BREACH CSRF support. When I update your sample to use that recommendation, the tests pass fine. The migration guide should be updated to reflect this which I'm happy to keep this ticket open for. And seeing this ticket, as well as your comment on #5766, I wonder if you might have an opinion on #14149, which is an effort to simplify the SPA-centric CSRF configuration. |
@jzheaux I had missed this updated documentation. Thank you for pointing it. I couldn't find an equivalent for reactive applications. Here is what I plan to use, is it correct? http.csrf(csrf -> csrf
.csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
.csrfTokenRequestHandler(new SpaServerCsrfTokenRequestHandler())); with: /**
* Adapted from https://docs.spring.io/spring-security/reference/servlet/exploits/csrf.html#csrf-integration-javascript-spa
*/
static final class SpaServerCsrfTokenRequestHandler extends ServerCsrfTokenRequestAttributeHandler {
private final ServerCsrfTokenRequestAttributeHandler delegate = new XorServerCsrfTokenRequestAttributeHandler();
@Override
public void handle(ServerWebExchange exchange, Mono<CsrfToken> csrfToken) {
/*
* Always use XorCsrfTokenRequestAttributeHandler to provide BREACH protection of the CsrfToken when it is rendered in the response body.
*/
this.delegate.handle(exchange, csrfToken);
}
@Override
public Mono<String> resolveCsrfTokenValue(ServerWebExchange exchange, CsrfToken csrfToken) {
final var hasHeader = exchange.getRequest().getHeaders().get(csrfToken.getHeaderName()).stream().filter(StringUtils::hasText).count() > 0;
return hasHeader ? super.resolveCsrfTokenValue(exchange, csrfToken) : this.delegate.resolveCsrfTokenValue(exchange, csrfToken);
}
}
@Bean
WebFilter csrfCookieWebFilter() {
return (exchange, chain) -> {
exchange.getAttributeOrDefault(CsrfToken.class.getName(), Mono.empty()).subscribe();
return chain.filter(exchange);
};
} Maybe could this Regarding #14149, yep, that would be great to have this done in one step. I currently offer this feature in my Boot starter with an enum in properties. But having it as a predefined customizer in |
hello ch4mpy
|
@LHai-dev correct me if my wrong, but your comment has nothing to do with this issue (if I'm right, you should probably delete it). It looks like an issue at runtime (not during JUnit tests like this ticket is about), and it also seems that this issue is due to the fact that you copied some code from my tutorials before I updated it with the latest recommandations linked above by @jzheaux |
Thank you @jzheaux . I think that we can close this issue as the other one gives a follow up on good CSRF practices for SPAs (and this practices solve the bug I reported here) |
Describe the bug
Using
SecurityMockMvcRequestPostProcessors.csrf()
gives invalid CSRF token when configuration containscsrf.csrfTokenRequestHandler(new XorCsrfTokenRequestAttributeHandler()::handle)
To Reproduce
Configure a servlet application with
oauth2Login
and CSRF security for a SPAExpected behavior
Test security framework should provide with the tooling to mimic a request from a SPA with valid CSRF token.
Sample
https://github.com/ch4mpy/reproducer_spring-security_gh-14125
This repo contains a minimal reproducer (
reproducer-bff-servlet
module) with a failing test (ReproducerBffServletApplicationTests::givenCsrfTokenIsPresent_whenLogout_thenOk
).It also contains an equivalent reactive app (which is not affected by the bug) and an Angular SPA working with both Spring backends.
The text was updated successfully, but these errors were encountered: