# 8. Debugging recipes *Prev: [7. SameSite](07-samesite.md)* ## Turn on the two log categories first ```yaml logging: level: org.springframework.web.cors: DEBUG # DefaultCorsProcessor's Skip:/Reject: lines org.springframework.security.web.csrf: DEBUG # "Invalid CSRF token found for ..." ``` Almost every question in this subject is answered by one line from one of those two. ## Reproduce the preflight without a browser ```bash curl -s -i -X OPTIONS http://localhost:8080/api/data \ -H 'Origin: https://spa.example.com' \ -H 'Access-Control-Request-Method: POST' \ -H 'Access-Control-Request-Headers: content-type,x-xsrf-token' ``` That is the whole preflight. `scripts/preflight.sh` wraps it. Note the absence of `-u` and `-b`: the browser sends no credentials on a preflight, and reproducing it *with* credentials hides the bug. ## Is `CorsFilter` even in the chain? ```bash curl -s localhost:8080/diag/chain | python3 -m json.tool ``` If `CorsFilter` is absent, no amount of MVC configuration will help — chapter 1. The production equivalent, without a diagnostic endpoint, is the startup log: ``` Will secure any request with filters: DisableEncodeUrlFilter, ..., CorsFilter, ... ``` Grep for `with filters:`. ## Which `CorsConfigurationSource` beans exist, and what are they called? ```bash curl -s localhost:8080/diag/cors-sources ``` `hasBeanNamedCorsConfigurationSource: false` with a `UrlBasedCorsConfigurationSource` in the list is the chapter 2 failure exactly. ## Read the status code as a diagnosis | Symptom | Look at | |---|---| | Preflight `401`/`403`, no CORS headers | Chapter 1 — no `CorsFilter` | | Preflight `200`, no CORS headers | Chapter 2 — bean name | | Preflight `403`, `Invalid CORS request` | Chapter 3 — read the DEBUG line | | `401` on a request with valid credentials | Chapter 5 — the `/error` dispatch | | `403` on a POST, `GET` is fine | Chapter 6 — CSRF | | Cookie visible in DevTools' response, absent from the jar | Chapter 7 — `SameSite=None` with no `Secure` | | Every request preflights, latency doubled | Chapter 1 — no `Access-Control-Max-Age` | ## Check the cookie jar, not the response DevTools shows the `Set-Cookie` header in the Network tab whether or not the browser stored the cookie. Application → Cookies is the jar. A header present in one and absent from the other is chapter 7, every time. ## Delete the diagnostic endpoints `DiagController` and `CookieSpecReport` publish your filter chain and bean names. They exist to make this repository legible. Do not ship them. --- *Prev: [7. SameSite](07-samesite.md)*