Volcano DocumentationAuthenticationConfiguration

CORS Configuration

Restrict which domains can call your auth endpoints.

Restrict which domains can call your auth endpoints.

What is CORS?

Cross-Origin Resource Sharing controls which websites can make requests to your API.

Without CORS:

Any website can use your anon key to call signup/signin
(Even with valid anon key, attackers can embed forms on their sites)

With CORS:

Only YOUR websites can use your anon key
Attackers blocked even with valid anon key

Enable CORS

Setting: cors_enabled
Default: false

{
  "cors_enabled": true,
  "cors_allowed_origins": ["https://myapp.com", "http://localhost:3000"]
}

Allowed Origins

Setting: cors_allowed_origins
Type: Array of strings

List of origins that can call your auth endpoints.

Examples:

{
  "cors_allowed_origins": [
    "https://myapp.com",
    "https://app.mycompany.com",
    "http://localhost:3000",
    "http://localhost:5000"
  ]
}

Wildcard subdomains:

{
  "cors_allow_credentials": false,
  "cors_allowed_origins": ["https://*.myapp.com"]
}

This pattern matches one leftmost label, such as app.myapp.com or api.myapp.com.

Use "*" with cors_allow_credentials: false to allow every valid browser origin. Prefer explicit origins or a one-label wildcard in production.

Wildcard origins cannot be combined with cors_allow_credentials: true. Credentialed requests require exact origins so the browser can safely send cookies and other credentials. If an existing project has both settings configured, replace the wildcard with exact origins or disable credentials in the same update before changing other auth settings.

Frontend previews

Setting: cors_allow_frontend_previews
Default: false

Each frontend preview is served at its own origin, such as https://<preview-id>.frontends.volcano.run. Turn this on to let the project's own live previews call its auth, storage, database, function, realtime and log endpoints from those origins, without listing them:

{
  "cors_enabled": true,
  "cors_allow_frontend_previews": true
}
  • Only previews of this project's frontends are allowed. Other projects' previews and every other *.frontends host are refused.
  • Each preview origin is an exact origin, so it works with cors_allow_credentials: true.
  • A preview's origin is allowed once it is ready. It stops being allowed within a few seconds of the preview being deleted or reaching its --ttl, with no configuration change. A promoted preview stays allowed while it is served. An open realtime connection is not closed when its origin stops being allowed.
  • GET /projects/{id}/auth/config lists the origins currently allowed this way in frontend_preview_origins.
  • At most 500 live previews per project are allowed this way. Past that, the 500 most recently created are allowed, and older ones are refused until some are deleted or expire.
  • Previews sign in with tokens. Cookie sessions are not offered to preview origins.

How It Works

Request from allowed origin:

POST /auth/signup
Origin: https://myapp.com
Authorization: Bearer ANON_KEY

Response: 201 Created
Access-Control-Allow-Origin: https://myapp.com

Request from blocked origin:

POST /auth/signup
Origin: https://evil.com
Authorization: Bearer ANON_KEY

Response: 403 Forbidden
{"error": "origin not allowed by CORS policy"}

Important Notes

Protocol matters:

Allowed: https://myapp.com
Blocked: http://myapp.com  (different protocol)

Hostnames are case-insensitive:

Allowed: https://myapp.com
Allowed: https://MyApp.com

Exact match:

Allowed: https://myapp.com
Blocked: https://www.myapp.com  (different subdomain)

Development Setup

Allow both production and local development:

{
  "cors_enabled": true,
  "cors_allowed_origins": [
    "https://myapp.com", // Production
    "https://staging.myapp.com", // Staging
    "http://localhost:3000", // Local dev
    "http://localhost:5173" // Vite dev server
  ]
}

Configuration

curl -X PUT https://api.volcano.dev/projects/PROJECT_ID/auth/config \
  -H "Authorization: Bearer TOKEN" \
  -d '{
    "cors_enabled": true,
    "cors_allowed_origins": ["https://myapp.com", "http://localhost:3000"]
  }'

Troubleshooting

Error: "origin not allowed by CORS policy"

  • Add your domain to cors_allowed_origins
  • For a frontend preview, set cors_allow_frontend_previews and check that the preview is listed in frontend_preview_origins
  • Check protocol (HTTP vs HTTPS)
  • Check for typos
  • Configure an origin only; paths, query strings, and fragments are rejected

Preflight requests failing:

  • Browser sends OPTIONS request first
  • Make sure CORS is configured
  • Check browser console for details

See Also

On this page