Issue
In the new Spring Boot 3.0.1 I'm adding support for CSRF protection by adding this simple configuration as per Spring documentation:
http.csrf().csrfTokenRepository(tokenRepository);
and
@Bean
public CsrfTokenRepository tokenRepository() {
var tokenRepo = CookieCsrfTokenRepository.withHttpOnlyFalse();
tokenRepo.setCookiePath("/");
return tokenRepo;
}
On the front-end side, there is an Angular app with import of the standard library
import {HTTP_INTERCEPTORS, HttpClientModule, HttpClientXsrfModule} from '@angular/common/http';
However I cannot make it work with the standard workflow, like
- Execute request to get XCSRF-TOKEN cookie from the server.
- Extract the token value from the cookie.
- Add X-XSRF-TOKEN header with the extract value from the cookie.
The front-end sends both cookie and header with the same token value and it fails in check:
public final class XorCsrfTokenRequestAttributeHandler ...
private static String getTokenValue(String actualToken, String token) {
byte[] actualBytes;
try {
actualBytes = Base64.getUrlDecoder().decode(actualToken);
}
catch (Exception ex) {
return null;
}
byte[] tokenBytes = Utf8.encode(token);
int tokenSize = tokenBytes.length;
if (actualBytes.length < tokenSize) {
return null;
}
The methods always returns null for
if (actualBytes.length < tokenSize) {
return null;
}
The only way to make it work is to return encoded string to be pasted in the header directly by adding endpoint, like this:
DeferredCsrfToken deferredCsrfToken = repository.loadDeferredToken(request, response);
requestHandler.handle(request, response, deferredCsrfToken::get);
CsrfToken csrfToken = (CsrfToken) request.getAttribute("_csrf");
return csrfToken.getToken();
So the returned value to be used in header looks like:
ab5tfqabXomGPuLjDQk96mVMZHNOh_JnpPVM4F_hQU1sOMyWW9sLSsCtb72rWNPabyQJ01EpSUsvtctKwcQphWeAJX9ZDPmg
instead of
5adaf830-40e6-43c9-b42a-e36fd713c1a6
Any advice on what I'm missing here?
Solution
Several things changed with spring security 6.
The migration guide also mentioned changes to be aware of when using angular with HttpClientXsrfModule or similar on client side.
https://docs.spring.io/spring-security/reference/migration/servlet/exploits.html
According to spring security migration guides following configurtation should work and is the recommended way.
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
CookieCsrfTokenRepository tokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler();
// (optional) set null to opt out of deferred tokens
requestHandler.setCsrfRequestAttributeName(null);
http
// ...
.csrf((csrf) -> csrf
.csrfTokenRepository(tokenRepository)
.csrfTokenRequestHandler(requestHandler)
);
return http.build();
}
For further details please read migration guides, so you can adapt to your needs.
Answered By - Matthias K.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.