Django REST Framework Authentication
Securing your API with authentication methods
🔐 What is API Authentication?
Authentication identifies who is making API requests. DRF provides multiple authentication methods including tokens, sessions, and JWT. It ensures only authorized users can access protected endpoints and perform specific actions.
# Protect views with authentication
from rest_framework.permissions import IsAuthenticated
class BookViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
queryset = Book.objects.all()
serializer_class = BookSerializer
Unauthorized Response:
{
"detail": "Authentication credentials were not provided."
}
Authentication Methods
Token Auth
Simple token-based auth
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
]
}
Session Auth
Django session-based auth
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
]
}
Basic Auth
Username/password in headers
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
]
}
JWT Auth
JSON Web Token auth
# Using djangorestframework-simplejwt
from rest_framework_simplejwt.authentication import JWTAuthentication
🔹 Token Authentication Setup
Token authentication is simple and secure. Each user gets a unique token for API access. Perfect for mobile apps and single-page applications:
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken', # Add this
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
# Run migrations to create token table
python manage.py migrate
# views.py - Create login endpoint
from rest_framework.authtoken.models import Token
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from django.contrib.auth import authenticate
@api_view(['POST'])
@permission_classes([AllowAny])
def login(request):
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(username=username, password=password)
if user:
token, created = Token.objects.get_or_create(user=user)
return Response({'token': token.key})
return Response({'error': 'Invalid credentials'}, status=400)
Usage Example:
# Login Request
POST /api/login/
{"username": "john", "password": "secret123"}
# Response
{"token": "9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"}
# Use token in subsequent requests
GET /api/books/
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
🔹 Session Authentication
Session authentication uses Django's built-in session framework. Best for web applications where users log in through a browser:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
],
}
# views.py
from django.contrib.auth import login, logout
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from django.contrib.auth import authenticate
@api_view(['POST'])
@permission_classes([AllowAny])
def user_login(request):
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(username=username, password=password)
if user:
login(request, user)
return Response({'message': 'Logged in successfully'})
return Response({'error': 'Invalid credentials'}, status=400)
@api_view(['POST'])
def user_logout(request):
logout(request)
return Response({'message': 'Logged out successfully'})
Session Auth Features:
- Uses cookies for authentication
- Integrates with Django admin
- CSRF protection required for POST/PUT/DELETE
- Best for same-domain web apps
🔹 Permission Classes
Control who can access your API endpoints using permission classes. Combine with authentication for fine-grained access control:
# views.py
from rest_framework import viewsets
from rest_framework.permissions import (
IsAuthenticated,
IsAuthenticatedOrReadOnly,
AllowAny,
IsAdminUser
)
# Only authenticated users can access
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = [IsAuthenticated]
# Anyone can read, only authenticated can write
class PublicBookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
# Only admin users can access
class AdminBookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = [IsAdminUser]
# Anyone can access (no authentication)
class OpenBookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = [AllowAny]
Built-in Permission Classes:
- AllowAny: No restrictions
- IsAuthenticated: Requires login
- IsAdminUser: Only admin users
- IsAuthenticatedOrReadOnly: Read for all, write for authenticated
🔹 Custom Permissions
Create custom permission classes for specific business logic and access control rules:
# permissions.py
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Custom permission: only owners can edit
"""
def has_object_permission(self, request, view, obj):
# Read permissions for any request
if request.method in permissions.SAFE_METHODS:
return True
# Write permissions only for owner
return obj.owner == request.user
class IsAuthorOrAdmin(permissions.BasePermission):
"""
Custom permission: authors and admins only
"""
def has_permission(self, request, view):
return request.user.is_authenticated and (
request.user.is_staff or
request.user.groups.filter(name='Authors').exists()
)
# views.py
from .permissions import IsOwnerOrReadOnly
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
🔹 JWT Authentication
JSON Web Tokens provide stateless authentication with access and refresh tokens. Great for modern APIs and microservices:
# Install JWT package
pip install djangorestframework-simplejwt
# settings.py
from datetime import timedelta
INSTALLED_APPS = [
# ...
'rest_framework',
'rest_framework_simplejwt',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
}
# urls.py
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
JWT Usage:
# Get tokens
POST /api/token/
{"username": "john", "password": "secret123"}
Response:
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}
# Use access token
GET /api/books/
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
# Refresh token when expired
POST /api/token/refresh/
{"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc..."}
🔹 Multiple Authentication Methods
Support multiple authentication methods simultaneously for flexibility across different client types:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
# views.py - Per-view authentication
from rest_framework.authentication import TokenAuthentication, SessionAuthentication
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
authentication_classes = [TokenAuthentication, SessionAuthentication]
permission_classes = [IsAuthenticated]
When to use multiple methods:
- Web app (sessions) + Mobile app (tokens)
- Supporting legacy and new clients
- Admin interface + Public API
- Gradual migration between auth methods