Authentication
Django REST Framework (DRF) provides a robust and flexible authentication system to secure your API. Here’s an overview of everything you need to know about authentication in DRF:
📘 Authentication in Django REST Framework (DRF)
🔐 Authentication = Who are you?
🔓 Authorization = Are you allowed to do this?
DRF handles authentication via pluggable classes set in REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES']
.
🧱 Built-in Authentication Classes in DRF
Class | Description | Use Case |
---|---|---|
SessionAuthentication |
Uses Django’s session & CSRF cookies | Browser-based apps (Django templates) |
BasicAuthentication |
Base64 username/password in header | Quick testing, not secure for production |
TokenAuthentication |
Token in Authorization: Token <token> |
Mobile apps, SPAs, API clients |
JWTAuthentication (via 3rd-party) |
Token with expiry, stateless | Modern API design |
RemoteUserAuthentication |
Uses REMOTE_USER env var |
Enterprise intranet SSO |
CustomAuthentication |
Your own class | Advanced integrations (mTLS, API keys, etc.) |
🛠 Basic Setup
In settings.py
:
= {
REST_FRAMEWORK 'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
] }
This enables both browser and API clients to authenticate.
✅ Common Auth Workflows
Type | User Experience | Use With |
---|---|---|
SessionAuth | Log in through Django Admin or LoginView | Browsers |
TokenAuth | POST username+password → get token | Postman, scripts, apps |
JWTAuth | POST credentials → get access/refresh tokens | SPAs, mobile apps |
API Keys | Header with a static token | 3rd-party integrations |
OAuth2 / SSO | Login via Google, GitHub, etc. | SaaS, enterprise |
🔑 Token Authentication (Built-in)
- Add
'rest_framework.authtoken'
toINSTALLED_APPS
- Run
python manage.py migrate
- Add login view:
from rest_framework.authtoken.views import obtain_auth_token
= [
urlpatterns 'api/token/', obtain_auth_token),
path( ]
- Use it:
POST /api/token/
{ "username": "user", "password": "pass" }
# Response:
{ "token": "abc123" }
# Then use:
Authorization: Token abc123
🔐 JWT Authentication (Recommended for APIs)
- Install SimpleJWT:
pip install djangorestframework-simplejwt
- Add to
settings.py
:
= {
REST_FRAMEWORK 'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
]
}
from datetime import timedelta
= {
SIMPLE_JWT 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
}
- Add routes:
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
= [
urlpatterns 'api/token/', TokenObtainPairView.as_view()),
path('api/token/refresh/', TokenRefreshView.as_view()),
path( ]
✅ Usage:
POST /api/token/ → get { access, refresh }
Authorization: Bearer <access>
🧠 Custom Authentication
Make a custom class if you want to: - Use X-API-Key
headers - Authenticate based on certificate (mTLS) - Add throttling per user type
Example:
from rest_framework.authentication import BaseAuthentication
class CustomTokenAuth(BaseAuthentication):
def authenticate(self, request):
= request.headers.get('X-Api-Key')
token if token == "expected_token":
return (MyUserObject, None)
return None
🔐 Login via Session + CSRF (For Browsers)
- Requires logging in via Django LoginView or Admin
- Automatically sends
sessionid
cookie - Must include CSRF token in all modifying requests
Good for: - Internal admin views - API browsable interface (/api/
with DRF)
🔒 Permissions (AuthZ, not AuthN)
Once the user is authenticated, permissions check whether they can do something:
Class | Description |
---|---|
AllowAny |
Open to everyone |
IsAuthenticated |
Only logged-in users |
IsAdminUser |
Only superusers |
IsAuthenticatedOrReadOnly |
Anyone can read, only authed can write |
Custom | has_permission(self, request, view) logic |
Used in your views like:
class MyViewSet(viewsets.ModelViewSet):
= [IsAuthenticated] permission_classes
🔁 Session vs Token vs JWT (Comparison)
Feature | SessionAuth | TokenAuth | JWT |
---|---|---|---|
Cookie-based? | ✅ Yes | ❌ No | ❌ No |
Header-based? | ❌ No | ✅ Yes | ✅ Yes |
Expiry Support | Manual | Manual | ✅ Built-in |
Stateless? | ❌ No | ✅ Yes | ✅ Yes |
Best For | Web apps | Simple API clients | Production-grade APIs |
🔐 Example: Login with JWT and Use API
# Login
curl -X POST /api/token/ \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "password": "pass"}'
# Response:
{
"access": "ey...",
"refresh": "ey..."
}
# Use it
curl -H "Authorization: Bearer ey..." /api/clients/
🔄 Refresh Tokens (JWT)
When access token expires, use refresh:
POST /api/token/refresh/
{
"refresh": "ey..."
}
Get a new access token without re-logging in.
🔐 Advanced Use Cases
Feature | Use |
---|---|
API key for 3rd parties | Custom auth class, or use drf-api-key |
Service accounts | Create special users, assign static tokens |
mTLS authentication | Terminate TLS at Nginx/LB, forward identity headers |
OAuth2 | Use django-allauth , django-oauth-toolkit |
🧠 Diagram: DRF Auth Flow (JWT)
[Client]
|
| -- POST /api/token/ --> [DRF Login View]
| <-- {access, refresh}
|
| -- GET /api/data/ (Authorization: Bearer <access>)
| --> DRF checks JWT -> decodes -> authenticates user
✅ Summary Cheat Sheet
Concept | You Should Know |
---|---|
DRF supports multiple auth systems | ✅ Use DEFAULT_AUTHENTICATION_CLASSES |
Token vs JWT | JWT is stateless + has expiry |
SessionAuth | Great for browser use, requires CSRF |
JWTAuth | Best for API use (SPAs, mobile) |
Permissions are separate from auth | Use permission_classes |