Safeguard
Developer Tools•

Why does Spring Security 6 return 403 for my SPA's POST requests?

After upgrading to Spring Security 6, single page apps often get 403 on POST. Deferred tokens and BREACH protection changed, and a cookie repository needs care.

Safeguard Security Team
3 min read

After moving to Spring Security 6, a single page app can start getting 403 responses on POST because CSRF token loading is now deferred and the token value includes randomness on every request. Spring documents extra configuration for single page apps. Do not respond by disabling CSRF without reading why it fails.

What changed in version 6

The Spring Security reference lists two changes that affect CSRF handling when you migrate from version 5 to 6:

  • Loading of the token is deferred by default, so the session no longer has to load on every request.
  • The token now includes randomness on every request, to protect it from a BREACH attack.

The reference adds that these changes require additional configuration for single page applications and points to a dedicated Single Page Applications section. A front end that read the cookie once and replayed the raw value used to work. With a randomised token it can fail.

A cookie repository, in brief

For JavaScript frameworks, Spring offers CookieCsrfTokenRepository. The reference shows this configuration, with HttpOnly set to false so the framework can read the cookie:

http.csrf((csrf) -> csrf
    .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
);

The docs say the default cookie and header names, XSRF-TOKEN and X-XSRF-TOKEN, come from Angular and AngularJS. They also say that if you do not need JavaScript to read the cookie, you should omit the HttpOnly false setting. Readable cookies are a trade, so only do it when a front end needs it.

Diagnose before you change anything

  1. Open the browser network tab and look at the failing request. Is a token header present at all?
  2. Compare the header name with what the repository expects. A mismatch gives a 403 just like a bad value.
  3. Check whether the token is fetched fresh after login and after logout. Tokens tied to a session change when the session does.
  4. Read the Single Page Applications section of the Spring Security reference and apply the request handler it describes.
  5. Add a test that sends a state changing request with and without a token.

Why not just disable CSRF

If your app authenticates with a session cookie, a browser attaches it automatically to cross site requests, which is the situation CSRF protection exists for. Turning protection off removes the defence rather than fixing the cause. Our post on when it is safe to disable CSRF in Spring Security covers the cases where it is reasonable.

Safeguard scans dependencies, produces SBOMs and uses reachability analysis to show which findings your code can actually reach. You can run a free scan at gold.safeguard.sh/scan.

Quick check

Is the 403 a bug in Spring Security 6?

Usually not. It is the documented result of deferred and randomised tokens meeting a front end written for the earlier behaviour.

Should the CSRF cookie be HttpOnly?

Only if no JavaScript needs to read it. The reference recommends omitting the HttpOnly false setting when you do not need that.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.