Our SPA kept mysteriously failing on production. CORS errors in the console, CSP violations in the Network tab. Different errors on different endpoints. Turned out we were cargo-culting CSP headers without understanding how they interact with CORS.
The issue: we had Content-Security-Policy: default-src 'self' which was fine, but added script-src 'self' later and forgot to include our API domain. CORS preflight succeeded, but the actual request got blocked by CSP before it even hit the CORS check.
What actually works:
Access-Control-Allow-Origin: app.example.com
Access-Control-Allow-Credentials: true
Content-Security-Policy: default-src 'self'; script-src 'self' api.example.com; connect-src 'self' api.example.com
The key thing I missed: CSP connect-src controls what fetch/xhr can hit. If you're doing credentials, you need both CORS headers AND the CSP header aligned, not just one.
Also killed us on staging because we were using * for CORS (with Credentials: false) but then toggled credentials in our client code during a refactor. Headers matched, browser said no.
Lesson learned: CORS and CSP aren't separate concerns. Test them together. Document what each domain needs in CSP or you'll waste a day like I did.
No responses yet.