Autenticación en DRF
DRF soporta múltiples esquemas de autenticación que se configuran globalmente o por vista:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}

TokenAuthentication
TokenAuthentication usa un token opaco por usuario. Simple pero no soporta expiración sin configuración adicional:
pip install djangorestframework
# settings.py
INSTALLED_APPS += ['rest_framework.authtoken']
# Crear token para un usuario
from rest_framework.authtoken.models import Token
token, created = Token.objects.get_or_create(user=usuario)
# URLs para obtener token
from rest_framework.authtoken.views import obtain_auth_token
urlpatterns += [path('api/token/', obtain_auth_token)]
El cliente envía el token en la cabecera: Authorization: Token abc123...
JWT con djangorestframework-simplejwt
JWT (JSON Web Token) es el estándar recomendado en 2026 para APIs REST. simplejwt proporciona acceso y refresco de tokens:
pip install djangorestframework-simplejwt
# settings.py
from datetime import timedelta
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': True, # Genera nuevo refresh al refrescar
'BLACKLIST_AFTER_ROTATION': True, # Invalida el refresh anterior
'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
}
# urls.py
from rest_framework_simplejwt.views import (
TokenObtainPairView, TokenRefreshView, TokenVerifyView
)
urlpatterns += [
path('api/auth/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/auth/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('api/auth/token/verify/', TokenVerifyView.as_view(), name='token_verify'),
]
El cliente obtiene el token con POST a /api/auth/token/ con username y password. El token se envía en la cabecera: Authorization: Bearer eyJ...
Personalizar el payload del JWT
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
class CustomTokenSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
# Añadir claims personalizados al payload del token
token['username'] = user.username
token['email'] = user.email
token['is_staff'] = user.is_staff
token['roles'] = list(user.groups.values_list('name', flat=True))
return token
class CustomTokenView(TokenObtainPairView):
serializer_class = CustomTokenSerializer
Permisos integrados de DRF
from rest_framework.permissions import (
AllowAny, IsAuthenticated, IsAdminUser,
IsAuthenticatedOrReadOnly, DjangoModelPermissions
)
from rest_framework import viewsets
from .models import Producto
from .serializers import ProductoSerializer
class ProductoPublicoViewSet(viewsets.ReadOnlyModelViewSet):
"""Lectura pública, sin autenticación."""
queryset = Producto.objects.filter(activo=True)
serializer_class = ProductoSerializer
permission_classes = [AllowAny]
class ProductoAdminViewSet(viewsets.ModelViewSet):
"""CRUD completo solo para administradores."""
queryset = Producto.objects.all()
serializer_class = ProductoSerializer
permission_classes = [IsAdminUser]
class ArticuloViewSet(viewsets.ModelViewSet):
"""Lectura pública, escritura solo autenticados."""
queryset = Articulo.objects.all()
serializer_class = ArticuloSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
def get_permissions(self):
"""Permisos diferentes según la acción."""
if self.action in ['list', 'retrieve']:
return [AllowAny()]
elif self.action in ['create']:
return [IsAuthenticated()]
else: # update, partial_update, destroy
return [IsAuthenticated(), EsPropietario()]
return super().get_permissions()
Permisos personalizados
from rest_framework.permissions import BasePermission, SAFE_METHODS
class EsPropietario(BasePermission):
"""Solo el propietario del objeto puede modificarlo."""
message = 'Solo el propietario puede realizar esta acción.'
def has_object_permission(self, request, view, obj):
return obj.autor == request.user
class EsEditorOSuperUser(BasePermission):
"""Editores y superusuarios tienen acceso completo."""
def has_permission(self, request, view):
if not request.user.is_authenticated:
return False
return (
request.user.is_superuser or
request.user.groups.filter(name='Editor').exists()
)
class LecturaPublicaEscrituraAutenticada(BasePermission):
"""Solo lectura sin autenticación, escritura con."""
def has_permission(self, request, view):
if request.method in SAFE_METHODS:
return True
return request.user and request.user.is_authenticated
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Django es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Django
Explora más contenido relacionado con Django y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Configurar TokenAuthentication de DRF para autenticación por token. Implementar autenticación JWT con djangorestframework-simplejwt. Usar los endpoints de obtención y refresco de tokens JWT. Aplicar permisos integrados de DRF como IsAuthenticated y IsAdminUser. Crear permisos personalizados extendiendo BasePermissión.
Cursos que incluyen esta lección
Esta lección forma parte de los siguientes cursos estructurados con rutas de aprendizaje