Files
adastra_api/docs/decisions/0010-cors-origin-restriction.md
T

2.6 KiB

Restrict CORS to explicit allowed origins

  • Status: accepted
  • Date: 2026-04-26

Context and Problem Statement

The API serves an Angular frontend from a different origin. Cross-Origin Resource Sharing (CORS) must be configured to allow the frontend to call the API. The initial configuration used cors() with no options, which sets Access-Control-Allow-Origin: * and allows any website to make cross-origin requests to the API — including requests carrying a victim's JWT token.

Decision Drivers

  • Any malicious website could make authenticated requests to the API on behalf of a logged-in user (CSRF-like attack via CORS misconfiguration).
  • The list of legitimate frontend origins is finite and known at deployment time.
  • The Authorization: Token <jwt> header is a non-simple header that always triggers a CORS preflight — the server controls which origins receive a valid preflight response.

Considered Options

  • Wildcard CORS (Access-Control-Allow-Origin: *)
  • Explicit origin allowlist via environment variable

Decision Outcome

Chosen option: "Explicit origin allowlist", because it limits cross-origin access to known, trusted frontends. Unknown origins receive no CORS headers and are blocked by the browser.

Allowed origins are read from the ALLOWED_ORIGINS environment variable as a comma-separated list. If the variable is not set, all cross-origin requests are rejected (origin: false). credentials: true is set to allow the Authorization header to be sent cross-origin.

Positive Consequences

  • Malicious third-party sites cannot make authenticated cross-origin requests on behalf of users.
  • Adding a new frontend origin (e.g. a mobile web app) requires only an env var change, no code deployment.

Negative Consequences

  • ALLOWED_ORIGINS must be set correctly in every environment (dev, staging, prod) or the frontend will fail with CORS errors. Incorrect configuration is a common operational mistake.

Pros and Cons of the Options

Wildcard CORS

  • Good, because no configuration required.
  • Bad, because allows any origin — malicious sites can make authenticated requests on behalf of logged-in users.
  • Bad, because incompatible with credentials: true per the CORS spec when Access-Control-Allow-Origin is *.

Explicit origin allowlist

  • Good, because only known frontends can make cross-origin requests.
  • Good, because configurable per environment without code changes.
  • Bad, because requires correct ALLOWED_ORIGINS configuration in each environment.
  • Related to ADR 0004 — all API routes are under /api/*, making CORS the only cross-origin entry point.