When building web APIs with Django REST Framework (DRF), see post controlling access to sensitive data and endpoints is a foundational requirement. While standard Django relies on middleware, sessions, and backend classes to handle web page authentication, DRF introduces a modular, flexible system known as authentication classes.
Authentication is the mechanism that links an incoming HTTP request to a specific user identity, determining who is making the request. Once identity is established, DRF’s permission classes determine whether that user is allowed to perform specific actions.
This comprehensive guide explores how DRF authentication classes work, examines built-in options, demonstrates global and view-level configuration, and walks through writing a custom authentication scheme.
1. How DRF Authentication Classes Work
Unlike standard Django, which processes authentication globally during request middleware, Django REST Framework evaluates authentication on a per-request basis inside its APIView lifecycle.
When an incoming request reaches a DRF view, the framework iterates through a defined list of authentication classes. It attempts to authenticate the request using the first class in the list.
- If credentials are valid, it halts execution of subsequent authentication classes and populates two critical properties on the request object:
request.user: An instance of the DjangoUsermodel (or a custom user model).request.auth: Any additional token or credential metadata (e.g., a token string or object).
- If credentials are invalid or missing, it passes control to the next authentication class in the sequence.
- If all authentication classes fail to identify the user, the request defaults to an unauthenticated state, setting
request.userto an instance ofAnonymousUserandrequest.authtoNone.
Crucially, authentication classes alone do not reject unauthorized requests. They only identify the user. Rejecting unauthenticated requests is the responsibility of DRF permission classes (such as IsAuthenticated).
2. Built-in Authentication Classes in DRF
Django REST Framework ships with several production-ready authentication classes out of the box, each tailored to different client architectures:
1. SessionAuthentication
This class utilizes Django’s default session backend and cookie storage. It is ideal when your API is consumed by a frontend application running on the same domain (such as a Django-rendered template, React, or Vue app served via the same origin). Because it relies on cookies, it automatically benefits from Django’s built-in CSRF protection.
2. BasicAuthentication
Basic Authentication verifies users using standard HTTP Basic authentication credentials (encoding the username and password in base64 within the Authorization header). While simple to test using tools like curl or Postman, it should never be used in production without HTTPS, as transmitting plain-text credentials on every request exposes them to interception.
3. TokenAuthentication
Token Authentication provides a simpler, stateless mechanism suitable for client-side applications (like mobile apps or desktop clients). It relies on a simple key-value database table (rest_framework.authtoken). Clients include the token in the request header:
HTTP
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
4. JSON Web Token (JWT) Authentication
While not built directly into core DRF, JWT authentication is the industry standard for modern Single-Page Applications (SPAs) and microservices. Popular third-party packages like djangorestframework-simplejwt allow stateless verification of cryptographically signed tokens containing user claims.
3. Global vs. Per-View Configuration
You can configure authentication classes globally across your entire Django project or override them on a per-view basis.
Global Configuration (settings.py)
To apply default authentication schemes across all API endpoints, define DEFAULT_AUTHENTICATION_CLASSES in your project settings:
Python
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
Per-View Configuration
If a specific view requires a different visit this site authentication strategy—such as allowing public access to a registration endpoint while keeping user profiles secure—you can override authentication classes directly inside class-based views (APIView or ViewSets):
Python
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import AllowAny
class PublicDataView(APIView):
# Override global settings for this specific view
authentication_classes = []
permission_classes = [AllowAny]
def get(self, request):
return Response({"message": "This endpoint is public and unauthenticated."})
4. Building a Custom Authentication Class
Sometimes built-in authentication mechanisms do not match your project architecture—for instance, if you need to authenticate requests via a custom API key header, an HMAC signature, or an external microservice.
DRF makes creating custom authentication schemes straightforward by subclassing BaseAuthentication and implementing the authenticate(self, request) method.
Consider a custom authentication class that looks for a specialized X-API-Key header:
Python
from rest_framework import authentication
from rest_framework import exceptions
from django.contrib.auth.models import User
class APIKeyAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
# Extract the custom API key from request headers
api_key = request.META.get('HTTP_X_API_KEY')
if not api_key:
# Return None if the header is missing, allowing other
# authentication classes in the stack a chance to run
return None
try:
# Look up a user associated with this custom API key
# (Assuming a profile or key mapping exists in your database)
user = User.objects.get(profile__api_key=api_key)
except User.DoesNotExist:
raise exceptions.AuthenticationFailed('Invalid or inactive API key.')
# Return a tuple of (user, auth) upon successful validation
return (user, api_key)
To use your custom class, simply include its module path in your global settings or view attributes:
Python
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'myapp.authentication.APIKeyAuthentication',
'rest_framework.authentication.SessionAuthentication',
]
}
5. Best Practices for DRF Authentication
- Always Enforce HTTPS: Session, Basic, and Token authentication transmit sensitive credentials or tokens over network requests. Always deploy behind TLS/SSL to prevent man-in-the-middle attacks.
- Combine Authentication with Permissions: Remember that authentication only identifies the user. Always pair your authentication classes with restrictive permission classes (like
IsAuthenticatedor custom object-level permissions) to lock down endpoints. - Handle Token Expiration: If using token or JWT authentication, implement token expiration and rotation policies to mitigate risks if a client credential is leaked.
- Order Matters: When defining multiple authentication classes in a list, DRF evaluates them sequentially. Place faster or more restrictive schemes first, keeping broader fallbacks (like session authentication) toward the end.
Conclusion
Django REST Framework authentication classes provide a powerful, extensible architecture for identifying API consumers. By understanding how DRF evaluates authentication sequences, leveraging built-in mechanisms like Token and Session authentication, and crafting custom schemes when unique requirements arise, Full Report you can design secure, flexible, and robust web APIs.