I'm experimenting with the possibility of serving an Angular application through Spring Cloud Gateway.
Everything works fine for GET requests but as soon as I try to send a POST request to the resource service through the gateway, the request fails because of "Invalid CSRF token".
This is probably because of some misconfiguration but I'm not being able to find it. Also, online documentation for both Spring Gateway and Angular are not being very useful for this specific scenario.
Here is the repository with the current configuration if you want to replicate this behavior: github repo.
Current behavior: POST request from Angular fails because of "Invalid CSRF token":
error: "Invalid CSRF Token"
message: "Http failure response for http://gateway:8000/api/post: 403 Forbidden"
name: "HttpErrorResponse"
ok: false
status: 403
statusText: "Forbidden"
url: "http://gateway:8000/api/post"
Desired behavior: POST requests executing successfully without disabling csrf in spring security.
This is my Spring Security configuration for the gateway:
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
@Bean
SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http) throws Exception {
return http
.authorizeExchange(exchange -> exchange
.pathMatchers("/**").permitAll()
.anyExchange().authenticated())
.csrf(csrf -> csrf.csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse()))
.build();
}
}
Gateway also contains the following WebFilter:
@Component
@Configuration
public class CsrfCookieWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
String key = CsrfToken.class.getName();
Mono<CsrfToken> csrfToken = null != exchange.getAttribute(key) ? exchange.getAttribute(key) : Mono.empty();
return csrfToken.doOnSuccess(token -> {
ResponseCookie cookie = ResponseCookie.from("XSRF-TOKEN", token.getToken())
.maxAge(Duration.ofHours(1))
.httpOnly(false)
.path("/")
.sameSite(Cookie.SameSite.LAX.attributeValue())
.build();
exchange.getResponse().getCookies().add("XSRF-TOKEN", cookie);
}).then(chain.filter(exchange));
}
}
The angular application AppModule contains the import of HttpClientXsrfModule.