6.8 KiB
Changelog - Corrección de Errores de Autenticación
Fecha: 2025-10-12 Versión: 1.0.1
Problemas Resueltos
1. Error 403 CSRF en Login desde Navegador
Síntoma: Al intentar hacer login desde el navegador web, el backend retornaba error 403 (Forbidden) con mensaje "Acceso denegado (permisos insuficientes)".
Causa Raíz: Django estaba aplicando validación CSRF a todas las rutas, incluyendo las rutas de API REST que usan JWT para autenticación. El middleware CsrfViewMiddleware rechazaba requests sin token CSRF.
Solución Implementada:
-
Creado nuevo middleware
DisableCSRFOnAPIMiddlewareenbackend/mac_attendance/middleware.py- Desactiva validación CSRF para todas las rutas que coincidan con
^api/.*$ - Colocado antes de
CsrfViewMiddlewareen la cadena de middleware
- Desactiva validación CSRF para todas las rutas que coincidan con
-
Actualizado
settings.py:- Agregado
CSRF_EXEMPT_URLS = [r'^api/.*$'] - Actualizado
CORS_ALLOWED_ORIGINSpara incluirhttp://localhost - Agregado
CSRF_TRUSTED_ORIGINSpara desarrollo local - Agregado middleware en posición correcta (línea 45)
- Agregado
-
Configuración final de middleware:
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'mac_attendance.middleware.DisableCSRFOnAPIMiddleware', # ← NUEVO
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'mac_attendance.middleware.AuditMiddleware',
]
Resultado: ✅ Login desde navegador funciona correctamente sin error 403
2. Endpoint /api/ Expuesto Públicamente
Síntoma: Cualquier usuario no autenticado podía acceder a /api/ y /api/docs/ para ver información sobre todos los endpoints del sistema.
Riesgo de Seguridad: Exposición de información sensible sobre la estructura de la API.
Solución Implementada:
-
Actualizado
backend/mac_attendance/urls.py:- Agregado decorador
@permission_classes([IsAuthenticated])a funciónapi_root() - Agregado decorador
@permission_classes([IsAuthenticated])a funciónapi_docs() - Ambos endpoints ahora requieren token JWT válido
- Agregado decorador
-
Código modificado:
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def api_root(request):
"""API root endpoint - Returns comprehensive API information (Protected)"""
# ...
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def api_docs(request):
"""API documentation endpoint (Protected)"""
# ...
Resultado:
- ✅
/api/sin autenticación → Error 401 "Las credenciales de autenticación no se proveyeron" - ✅
/api/con token válido → Muestra información de la API - ✅
/api/docs/ahora también protegido
Archivos Modificados
1. backend/mac_attendance/middleware.py
- Agregado: Clase
DisableCSRFOnAPIMiddleware - Líneas: 103-126
2. backend/mac_attendance/settings.py
- Modificado: Lista
MIDDLEWARE(línea 40-51) - Agregado:
CSRF_EXEMPT_URLS(línea 154) - Modificado:
CORS_ALLOWED_ORIGINS(línea 140-143) - Agregado:
CSRF_TRUSTED_ORIGINS(línea 148-151)
3. backend/mac_attendance/urls.py
- Modificado: Función
api_root()- agregado autenticación (línea 23-26) - Modificado: Función
api_docs()- agregado autenticación (línea 138-140)
4. API_DOCUMENTATION.md
- Actualizado: Sección "Acceder a la Documentación" con advertencia de autenticación
Testing Realizado
Test 1: Login desde cURL (simulando navegador)
curl -X POST http://localhost/api/auth/login/ \
-H "Content-Type: application/json" \
-H "Origin: http://localhost" \
-d '{"account_number":"3123123"}'
Resultado: ✅ Status 200, retorna tokens JWT
Test 2: API Root sin autenticación
curl -X GET http://localhost/api/
Resultado: ✅ Status 401, mensaje de error apropiado
Test 3: API Root con autenticación
curl -X GET http://localhost/api/ \
-H "Authorization: Bearer <token>"
Resultado: ✅ Status 200, retorna información de API
Seguridad Mejorada
Antes de la Corrección:
- ❌ Login fallaba con 403 desde navegador
- ❌
/api/accesible sin autenticación - ❌
/api/docs/accesible sin autenticación - ⚠️ Información de endpoints expuesta públicamente
Después de la Corrección:
- ✅ Login funciona correctamente desde navegador
- ✅
/api/requiere autenticación JWT - ✅
/api/docs/requiere autenticación JWT - ✅ Información de API protegida
- ✅ CSRF deshabilitado solo en rutas API (usamos JWT)
- ✅ CSRF sigue activo en panel admin (usa sesiones)
Notas Técnicas
¿Por qué deshabilitar CSRF en API?
Django REST Framework con JWT no necesita protección CSRF porque:
- No usa cookies de sesión: JWT se envía en header
Authorization - Tokens stateless: No hay estado de sesión en servidor
- CORS protege: CORS ya previene requests desde orígenes no autorizados
- JWT expira: Tokens tienen tiempo de vida limitado (1 hora)
Alternativa No Recomendada
Usar @csrf_exempt en cada vista → ❌ Requiere modificar múltiples archivos
Nuestra solución: Middleware centralizado → ✅ Un solo punto de configuración
Cómo Probar
1. Desde el navegador (http://localhost)
- Abrir la aplicación
- Ingresar número de cuenta:
3123123 - Click en "Iniciar Sesión"
- ✅ Debe iniciar sesión exitosamente
2. Verificar protección de /api/
- Abrir navegador e ir a http://localhost/api/
- ✅ Debe mostrar:
{"detail": "Las credenciales de autenticación no se proveyeron."}
3. Acceder a /api/ autenticado
- Hacer login primero
- Copiar el access_token
- Usar extensión de navegador o Postman:
- URL: http://localhost/api/
- Header:
Authorization: Bearer <access_token>
- ✅ Debe mostrar información completa de la API
Próximos Pasos (Opcional)
- Implementar rate limiting específico para login (ya existe global)
- Agregar logs de accesos exitosos/fallidos a
/api/ - Considerar implementar API key para documentación pública
- Agregar tests automatizados para validación CSRF
Contacto
Si encuentras algún problema con estas correcciones, revisa:
- Logs del backend:
docker-compose logs backend - Logs de nginx:
docker-compose logs nginx - Consola del navegador (F12) para ver errores de JavaScript
Revisado y probado: ✅ Contenedores actualizados: ✅ Documentación actualizada: ✅