78 lines
2.6 KiB
Markdown
78 lines
2.6 KiB
Markdown
# 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)*
|