CORS (Cross-Origin Resource Sharing)

Bulwark handles CORS automatically for SDK users. If you use a publishable key, CORS works out of the box — no domains to configure.


How it works

CORS headers are included on responses that match one of these conditions:

  1. Publishable key header — requests with X-Bulwark-Publishable-Key (the SDK sends this automatically)
  2. Public auth endpoints/api/v1/auth/*, /oauth2/*, /hosted/*, /.well-known/*
  3. Tenant header — requests with a valid X-Bulwark-Tenant UUID
  4. Global origin allowlist — origins listed in BULWARK_CORS_ORIGINS
  5. OPTIONS preflight — always allowed

This means:

  • SDK users — CORS works automatically via the publishable key
  • Auth endpoints — login, register, identify, SSO all work cross-origin
  • localhost — works during development
  • No "add this domain" configuration when using the SDK

Requests without any of the above identifiers do not receive CORS headers. This prevents credential theft via malicious cross-origin requests.

Preflight requests

Bulwark handles OPTIONS preflight requests automatically with a 204 No Content response, full CORS headers, and a 24-hour cache (Access-Control-Max-Age: 86400), minimizing preflight overhead.

Response headers

Matching responses include:

| Header | Value | |--------|-------| | Access-Control-Allow-Origin | The requesting origin (echoed back) | | Access-Control-Allow-Credentials | true | | Access-Control-Allow-Headers | Content-Type, Authorization, X-Bulwark-Tenant, X-Bulwark-App-Id, X-Bulwark-Publishable-Key | | Access-Control-Allow-Methods | GET, POST, PATCH, PUT, DELETE, OPTIONS | | Access-Control-Max-Age | 86400 (24 hours) | | Vary | Origin (for correct caching) |

SDK integration

All Bulwark SDKs work automatically. Just initialize the provider:

<BulwarkProvider publishableKey="pk_live_...">
  <App />
</BulwarkProvider>

No CORS configuration needed. The SDK sends the publishable key as a header on every request.

Server-side requests

Server-side requests (Node.js, Go, Python) are not subject to CORS — browsers enforce CORS, servers don't. Your backend API calls to Bulwark work without any configuration.

Self-hosted deployments

For self-hosted Bulwark instances, you can restrict CORS to specific origins by setting the BULWARK_CORS_ORIGINS environment variable:

BULWARK_CORS_ORIGINS=https://app.example.com,https://admin.example.com

When set, only these origins (plus publishable key and auth endpoints) receive CORS headers. Set to * to allow all origins without credentials.