Documentation Index
Fetch the complete documentation index at: https://mintlify.com/pennersr/django-allauth/llms.txt
Use this file to discover all available pages before exploring further.
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.
The recommended way to handle CORS in Django is with the django-cors-headers package:
pip install django-cors-headers
Basic Configuration
Add the package to your Django settings:
INSTALLED_APPS = [
# ...
'corsheaders',
'allauth',
'allauth.account',
'allauth.headless',
# ...
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware', # Must be before CommonMiddleware
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'allauth.account.middleware.AccountMiddleware',
]
Note: CorsMiddleware must be placed before CommonMiddleware.
Production Configuration
For production, explicitly whitelist your frontend domain:
# Allow specific origins
CORS_ALLOWED_ORIGINS = [
"https://app.example.com",
"https://www.example.com",
]
# Allow credentials (cookies, authorization headers)
CORS_ALLOW_CREDENTIALS = True
# Custom headers used by allauth headless
from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = [
*default_headers,
'x-session-token',
'x-email-verification-key',
'x-password-reset-key',
]
Development Configuration
For local development, you can allow localhost:
# settings.py or local_settings.py
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
"http://localhost:5173", # Vite default
"http://127.0.0.1:3000",
]
CORS_ALLOW_CREDENTIALS = True
from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = [
*default_headers,
'x-session-token',
'x-email-verification-key',
'x-password-reset-key',
]
Allow All Origins (Development Only)
For quick development setup (NOT for production):
# WARNING: Only for development!
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True
django-allauth headless uses these custom HTTP headers:
X-Session-Token
Used by app clients to maintain session state:
fetch('http://localhost:8000/_allauth/app/v1/auth/session', {
headers: {
'X-Session-Token': sessionToken,
},
});
X-Email-Verification-Key
Used to verify email addresses:
fetch('http://localhost:8000/_allauth/app/v1/auth/email/verify', {
headers: {
'X-Email-Verification-Key': verificationKey,
},
});
X-Password-Reset-Key
Used to verify password reset requests:
fetch('http://localhost:8000/_allauth/app/v1/auth/password/reset', {
headers: {
'X-Password-Reset-Key': resetKey,
},
});
All these headers must be allowed in your CORS configuration.
Complete Example Configuration
Production Settings
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders',
'allauth',
'allauth.account',
'allauth.headless',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'allauth.account.middleware.AccountMiddleware',
]
# CORS Configuration
CORS_ALLOWED_ORIGINS = [
"https://app.example.com",
"https://www.example.com",
]
CORS_ALLOW_CREDENTIALS = True
from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = [
*default_headers,
'x-session-token',
'x-email-verification-key',
'x-password-reset-key',
]
# Headless configuration
HEADLESS_ONLY = True
HEADLESS_FRONTEND_URLS = {
"account_confirm_email": "https://app.example.com/account/verify-email/{key}",
"account_reset_password_from_key": "https://app.example.com/account/password/reset/key/{key}",
"account_reset_password": "https://app.example.com/account/password/reset",
"account_signup": "https://app.example.com/account/signup",
}
Development Settings
Create a local_settings.py that overrides production settings:
# local_settings.py (gitignored)
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
"http://localhost:5173",
"http://127.0.0.1:3000",
]
HEADLESS_FRONTEND_URLS = {
"account_confirm_email": "http://localhost:3000/account/verify-email/{key}",
"account_reset_password_from_key": "http://localhost:3000/account/password/reset/key/{key}",
"account_reset_password": "http://localhost:3000/account/password/reset",
"account_signup": "http://localhost:3000/account/signup",
}
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
Import it at the end of settings.py:
# settings.py
try:
from .local_settings import *
except ImportError:
pass
Client-Side Configuration
Browser Client (Same-Origin)
For SPAs on the same domain, no CORS is needed, but you must handle CSRF:
// Get CSRF token from cookie
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}
const csrfToken = getCookie('csrftoken');
fetch('/_allauth/browser/v1/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
credentials: 'include', // Include cookies
body: JSON.stringify({
email: 'user@example.com',
password: 'password123',
}),
});
App Client (Cross-Origin)
For cross-origin SPAs or mobile apps:
let sessionToken = null;
async function login(email, password) {
const response = await fetch('http://localhost:8000/_allauth/app/v1/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// No CSRF token needed for app clients
...(sessionToken && { 'X-Session-Token': sessionToken }),
},
body: JSON.stringify({ email, password }),
});
const data = await response.json();
// Store session token from response
if (data.meta?.session_token) {
sessionToken = data.meta.session_token;
localStorage.setItem('sessionToken', sessionToken);
}
// Or store JWT tokens
if (data.meta?.access_token) {
localStorage.setItem('accessToken', data.meta.access_token);
localStorage.setItem('refreshToken', data.meta.refresh_token);
}
return data;
}
async function apiRequest(url) {
const response = await fetch(url, {
headers: {
'X-Session-Token': sessionToken,
// Or for JWT:
// 'Authorization': `Bearer ${accessToken}`,
},
});
return response.json();
}
React Example
Here’s a complete example with React:
// api/allauth.js
const API_BASE = process.env.REACT_APP_API_URL || 'http://localhost:8000';
const CLIENT_TYPE = 'app'; // or 'browser'
let sessionToken = localStorage.getItem('sessionToken');
async function request(method, path, data = null) {
const headers = {
'Accept': 'application/json',
};
// Add session token for app clients
if (sessionToken) {
headers['X-Session-Token'] = sessionToken;
}
const options = {
method,
headers,
};
if (data) {
options.headers['Content-Type'] = 'application/json';
options.body = JSON.stringify(data);
}
const response = await fetch(
`${API_BASE}/_allauth/${CLIENT_TYPE}/v1${path}`,
options
);
const result = await response.json();
// Update session token if provided
if (result.meta?.session_token) {
sessionToken = result.meta.session_token;
localStorage.setItem('sessionToken', sessionToken);
}
// Clear token on logout
if ([401, 410].includes(result.status)) {
sessionToken = null;
localStorage.removeItem('sessionToken');
}
return result;
}
export const login = (email, password) =>
request('POST', '/auth/login', { email, password });
export const signup = (email, password) =>
request('POST', '/auth/signup', { email, password });
export const logout = () =>
request('DELETE', '/auth/session');
export const getSession = () =>
request('GET', '/auth/session');
export const getConfig = () =>
request('GET', '/config');
Troubleshooting
”CORS policy” Error
If you see:
Access to fetch at 'http://localhost:8000/_allauth/...' from origin 'http://localhost:3000'
has been blocked by CORS policy
Solutions:
- Verify
corsheaders is in INSTALLED_APPS
- Verify
CorsMiddleware is in MIDDLEWARE before CommonMiddleware
- Check that your frontend origin is in
CORS_ALLOWED_ORIGINS
- Restart the Django server after changing settings
”X-Session-Token” Not Allowed
If custom headers are blocked:
Request header field x-session-token is not allowed by Access-Control-Allow-Headers
Solution: Add the header to CORS_ALLOW_HEADERS:
from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = [
*default_headers,
'x-session-token',
'x-email-verification-key',
'x-password-reset-key',
]
Credentials Not Included
If session cookies aren’t being sent:
Backend:
CORS_ALLOW_CREDENTIALS = True
Frontend:
fetch(url, {
credentials: 'include', // Required for cookies
});
Preflight Request Fails
Browsers send an OPTIONS request before POST/PUT/DELETE. Ensure:
- Your server handles OPTIONS requests (django-cors-headers does this automatically)
- All custom headers are whitelisted
- 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:
# DANGEROUS: Do not use in production!
CORS_ALLOW_ALL_ORIGINS = True
Always explicitly whitelist trusted origins.
Use HTTPS in Production
Always use HTTPS for both frontend and backend in production:
CORS_ALLOWED_ORIGINS = [
"https://app.example.com", # HTTPS only
]
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
Only expose necessary custom headers:
CORS_ALLOW_HEADERS = [
*default_headers,
'x-session-token',
'x-email-verification-key',
'x-password-reset-key',
# Don't add unnecessary headers
]
Next Steps