CSRF & Authentication Debugger
Analyzes and debugs CSRF and authentication issues in this project.
Project Context
- Authentication: JWT tokens in httpOnly cookies + OAuth (Google, GitHub)
- CSRF: Django's CSRF middleware with cookie-based tokens
- OAuth library: django-allauth
- Token service:
services/auth/tokens.py - Frontend API: Axios with credentials and CSRF interceptor
Authentication Architecture
Browser
↓ Request with cookies
│ - access_token (httpOnly, JWT)
│ - refresh_token (httpOnly, JWT)
│ - csrftoken (readable by JS)
Django
↓ CsrfViewMiddleware
↓ JWTAuthenticationMiddleware
↓ View/API endpoint
When to Use
- "CSRF verification failed"
- "403 Forbidden on POST/PUT/DELETE"
- "Login not working"
- "Token expired"
- "OAuth callback failing"
- "Cookies not being set"
- "X-CSRFToken header missing"
CSRF Flow
How CSRF Works in This Project
- GET
/api/v1/auth/csrf/- Setscsrftokencookie - Frontend reads cookie -
getCookie('csrftoken') - POST/PUT/DELETE requests - Include
X-CSRFTokenheader - Django validates - Compares header to cookie
Frontend CSRF Handling
// frontend/src/services/api.ts
api.interceptors.request.use((config) => {
if (['post', 'put', 'patch', 'delete'].includes(method)) {
const csrfToken = getCookie('csrftoken');
if (csrfToken) {
config.headers['X-CSRFToken'] = csrfToken;
}
}
});
Common CSRF Issues
403 "CSRF verification failed":
-
Missing CSRF cookie
# Check if cookie exists in browser DevTools > Application > Cookies # Should see: csrftoken -
Missing X-CSRFToken header
// Check Network tab - request headers should include: // X-CSRFToken: <token value> -
Cookie not sent (CORS)
// Axios must have: withCredentials: true -
Domain mismatch
# settings.py - check these match your domain CSRF_COOKIE_DOMAIN = None # or '.yourdomain.com' CSRF_TRUSTED_ORIGINS = ['http://localhost:3000', ...] -
SameSite cookie issues
# For cross-origin requests: CSRF_COOKIE_SAMESITE = 'Lax' # or 'None' with Secure
Common Auth Issues
JWT token expired:
# Check token expiry in services/auth/tokens.py
ACCESS_TOKEN_LIFETIME = timedelta(minutes=15)
REFRESH_TOKEN_LIFETIME = timedelta(days=7)
Cookies not set after login:
# Check response has Set-Cookie headers
# Verify SameSite and Secure flags match environment
OAuth callback failing:
# Check callback URL matches exactly:
# - In Google/GitHub OAuth app settings
# - In django-allauth config
# - Including trailing slashes!
Debugging Steps
1. Check CSRF Cookie Exists
// Browser console
document.cookie.split(';').find(c => c.includes('csrftoken'))
2. Check Request Headers
Network tab > Request > Headers
Look for: X-CSRFToken: <value>
3. Check Django Logs
docker compose logs web | grep -i csrf
4. Test CSRF Endpoint
curl -c cookies.txt http://localhost:8000/api/v1/auth/csrf/
cat cookies.txt # Should show csrftoken
5. Verify Settings
# Django shell
from django.conf import settings
print(settings.CSRF_COOKIE_NAME)
print(settings.CSRF_TRUSTED_ORIGINS)
print(settings.CORS_ALLOWED_ORIGINS)
Key Files to Check
Backend:
├── config/settings.py # CSRF_*, CORS_*, cookie settings
├── core/auth/views.py # Login, logout, OAuth views
├── core/views/core_views.py # CSRF token endpoint
├── services/auth/tokens.py # JWT token creation
└── services/auth/__init__.py # set_auth_cookies function
Frontend:
├── src/services/api.ts # Axios CSRF interceptor
├── src/contexts/AuthContext.tsx # Auth state management
└── src/pages/AuthPage.tsx # Login/OAuth UI
Django CSRF Settings
# config/settings.py - key settings
CSRF_COOKIE_NAME = 'csrftoken'
CSRF_HEADER_NAME = 'HTTP_X_CSRFTOKEN'
CSRF_COOKIE_HTTPONLY = False # Must be False for JS to read
CSRF_COOKIE_SAMESITE = 'Lax'
CSRF_TRUSTED_ORIGINS = [
'http://localhost:3000',
'http://localhost:8000',
]
Views Exempt from CSRF
Some views use @csrf_exempt (check if issue is with exempt view):
grep -r "csrf_exempt" core/
Testing Authentication
# Login and get tokens
curl -X POST http://localhost:8000/api/v1/auth/login/ \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{"email":"test@example.com","password":"password"}'
# Use tokens for authenticated request
curl http://localhost:8000/api/v1/users/me/ \
-b cookies.txt
Scan to join WeChat group