Skip to main content
When building a single-page application that runs on a different origin than your Django backend, you need to configure Cross-Origin Resource Sharing (CORS) to allow your frontend to communicate with the API.

Why CORS is Needed

Browsers enforce the Same-Origin Policy, which prevents JavaScript from making requests to a different domain, protocol, or port. If your:
  • Frontend runs on http://localhost:3000 (development)
  • Backend runs on http://localhost:8000 (development)
  • Or frontend is on https://app.example.com and backend on https://api.example.com
You need CORS configuration to allow cross-origin requests.

Install django-cors-headers

The recommended way to handle CORS in Django is with the django-cors-headers package:

Basic Configuration

Add the package to your Django settings:
Note: CorsMiddleware must be placed before CommonMiddleware.

Production Configuration

For production, explicitly whitelist your frontend domain:

Development Configuration

For local development, you can allow localhost:

Allow All Origins (Development Only)

For quick development setup (NOT for production):

Required Custom Headers

django-allauth headless uses these custom HTTP headers:

X-Session-Token

Used by app clients to maintain session state:

X-Email-Verification-Key

Used to verify email addresses:

X-Password-Reset-Key

Used to verify password reset requests:
All these headers must be allowed in your CORS configuration.

Complete Example Configuration

Production Settings

Development Settings

Create a local_settings.py that overrides production settings:
Import it at the end of settings.py:

Client-Side Configuration

Browser Client (Same-Origin)

For SPAs on the same domain, no CORS is needed, but you must handle CSRF:

App Client (Cross-Origin)

For cross-origin SPAs or mobile apps:

React Example

Here’s a complete example with React:

Troubleshooting

”CORS policy” Error

If you see:
Solutions:
  1. Verify corsheaders is in INSTALLED_APPS
  2. Verify CorsMiddleware is in MIDDLEWARE before CommonMiddleware
  3. Check that your frontend origin is in CORS_ALLOWED_ORIGINS
  4. Restart the Django server after changing settings

”X-Session-Token” Not Allowed

If custom headers are blocked:
Solution: Add the header to CORS_ALLOW_HEADERS:

Credentials Not Included

If session cookies aren’t being sent: Backend:
Frontend:

Preflight Request Fails

Browsers send an OPTIONS request before POST/PUT/DELETE. Ensure:
  1. Your server handles OPTIONS requests (django-cors-headers does this automatically)
  2. All custom headers are whitelisted
  3. The middleware is configured correctly

Security Considerations

Never Use CORS_ALLOW_ALL_ORIGINS in Production

This allows any website to make requests to your API:
Always explicitly whitelist trusted origins.

Use HTTPS in Production

Always use HTTPS for both frontend and backend in production:

Limit Exposed Headers

Only expose necessary custom headers:

Next Steps