⚠️ SOBRE ESTA GUÍA
Esta guía documenta errores REALES encontrados por estudiantes al seguir la guía principal paso a paso.
Beneficio: Si encuentras estos errores, aquí está la solución comprobada que ya funcionó.
- 4 errores documentados con soluciones detalladas
- Capturas de pantalla de los errores exactos
- Explicación técnica del por qué ocurren
- Código corregido listo para copiar y pegar
📋 ÍNDICE DE ERRORES
| Error | Descripción | Sección |
|---|---|---|
| 1 | ValueError: Invalid model reference 'oauth2_provider.Models.AccessToken' | 3.2 → Configuración OAuth Provider |
| 2 | Unknown command: 'show_urls' | 3.3.1 → Configurar URLs OAuth |
| 3 | Redirect URI mismatch / Loop infinito de login | 3.4 → oauth_views.py |
| 4 | Token OAuth retorna 401 en test_oauth.py | 2.2 → Configurar JWT + OAuth |
1ERROR EN OAUTH2_PROVIDER SETTINGS
📍 UBICACIÓN EN LA GUÍA
Sección 3.2: Instalar y configurar Django Allauth
Subsección 2.5: Agregar Configuración de OAuth 2.0 Provider
ERROR ValueError en settings.py
ValueError: Invalid model reference 'oauth2_provider.Models.AccessToken'.
String model references must be of the form 'app_label.ModelName'.
Ocurre al ejecutar: python manage.py check
🔍 ¿POR QUÉ OCURRE?
Django espera que las referencias a modelos sigan el formato 'app_label.ModelName'
El código en la guía incluye erróneamente .Models. en la ruta, causando que Django no reconozca el formato.
Formato incorrecto: 'oauth2_provider.Models.AccessToken'
Formato correcto: 'oauth2_provider.AccessToken'
✅ SOLUCIÓN
1Ubicar el archivo
Abre biblioteca_project/settings.py
2Buscar la sección OAUTH2_PROVIDER
Busca estas líneas (aproximadamente línea 200-220):
# ❌ CÓDIGO INCORRECTO (de la guía original)
OAUTH2_PROVIDER = {
'SCOPES': {
'read': 'Read scope',
'write': 'Write scope',
},
'ACCESS_TOKEN_EXPIRE_SECONDS': 36000,
'REFRESH_TOKEN_EXPIRE_SECONDS': 86400,
'ACCESS_TOKEN_MODEL': 'oauth2_provider.Models.AccessToken', # ❌ ERROR
'REFRESH_TOKEN_MODEL': 'oauth2_provider.Models.RefreshToken', # ❌ ERROR
}
3Corregir eliminando ".Models"
Cambia las dos últimas líneas a:
# ✅ CÓDIGO CORRECTO
OAUTH2_PROVIDER = {
'SCOPES': {
'read': 'Read scope',
'write': 'Write scope',
},
'ACCESS_TOKEN_EXPIRE_SECONDS': 36000,
'REFRESH_TOKEN_EXPIRE_SECONDS': 86400,
'ACCESS_TOKEN_MODEL': 'oauth2_provider.AccessToken', # ✅ CORRECTO
'REFRESH_TOKEN_MODEL': 'oauth2_provider.RefreshToken', # ✅ CORRECTO
}
4Verificar que funciona
python manage.py check
✅ Salida esperada
System check identified no issues (0 silenced).
💡 EXPLICACIÓN TÉCNICA
¿Qué significan estos modelos?
ACCESS_TOKEN_MODEL: Define qué modelo usar para almacenar tokens de acceso OAuthREFRESH_TOKEN_MODEL: Define qué modelo usar para almacenar tokens de refresco
Formato de referencia Django:
'nombre_app.NombreModelo'
NO incluir subcarpetas o módulos como .Models.
2COMANDO show_urls NO ENCONTRADO
📍 UBICACIÓN EN LA GUÍA
Sección 3.3.1: Configurar URLs de OAuth 2.0
Al ejecutar: python manage.py show_urls
ERROR Unknown command
Unknown command: 'show_urls'
Type 'manage.py help' for usage.
🔍 ¿POR QUÉ OCURRE?
El comando show_urls NO es nativo de Django.
Pertenece al paquete django-extensions que NO está instalado por defecto.
La guía asume que esta librería ya está instalada, pero hay que hacerlo manualmente.
✅ SOLUCIÓN
1Instalar django-extensions
# En tu terminal con el entorno virtual activado:
pip install django-extensions
2Agregar a INSTALLED_APPS
Abre biblioteca_project/settings.py y agrega:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Third party apps
'rest_framework',
'rest_framework_simplejwt',
'corsheaders',
'oauth2_provider',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.google',
'django_extensions', # ⬅️ AGREGAR ESTA LÍNEA
# Local apps
'libros',
]
⚠️ IMPORTANTE: Guion bajo
Nota que en pip instalamos django-extensions (con guion)
Pero en INSTALLED_APPS ponemos 'django_extensions' (con guion bajo)
3Probar el comando
python manage.py show_urls
✅ Salida esperada (parcial)
/admin/ admin:index
/api/libros/ libros-list
/api/auth/login/ token_obtain_pair
/api/auth/google/redirect/ google_oauth_redirect
/api/auth/google/callback/ google_oauth_callback
/o/authorize/ oauth2_provider:authorize
/o/token/ oauth2_provider:token
...
(mostrará todas tus rutas)
📦 ¿Qué es django-extensions?
django-extensions es un paquete que agrega comandos útiles para desarrollo:
show_urls- Muestra todas las rutas de tu proyectoshell_plus- Shell mejorado con imports automáticosgraph_models- Genera diagramas de tus modelosrunserver_plus- Servidor de desarrollo mejorado- Y muchos más...
Recomendación: Úsalo solo en desarrollo, no en producción.
💾 Actualizar requirements.txt
Para que no olvides instalarlo en el futuro:
# Agregar a requirements.txt:
django-extensions==3.2.3
3PROBLEMAS CON REDIRECT_URI EN OAUTH
📍 UBICACIÓN EN LA GUÍA
Sección 3.4: Crear Vista de OAuth y Generar JWT
Archivo: libros/oauth_views.py
ERROR 1 redirect_uri_mismatch
Al intentar loguearse con Google, aparece error de redirección.
🖼️ [Captura: Ventana de error de Google OAuth]
"Error 400: redirect_uri_mismatch"
ERROR 2 Loop infinito de login
Después de autenticarse, regresa a la pantalla de Django REST una y otra vez.
No muestra la información del usuario logueado.
🖼️ [Captura: Terminal mostrando GET en verde pero sin procesar login]
🔍 ¿POR QUÉ OCURRE?
CAUSA DEL ERROR 1: Inconsistencia en redirect_uri
Las dos funciones en oauth_views.py usan URLs diferentes:
google_oauth_callbackusa:http://localhost:8000/...google_oauth_redirectusa:http://127.0.0.1:8000/...
Problema: Google OAuth requiere que la URL de callback sea EXACTAMENTE la misma que se registró y la que se envía en la solicitud.
CAUSA DEL ERROR 2: Flujo OAuth incompleto
Posibles causas:
- El token no se está guardando correctamente
- El frontend no está recibiendo el token
- Falta el procesamiento en
oauth_login.html
✅ SOLUCIÓN PARA ERROR 1: Consistencia en URLs
1Decidir qué URL usar
Recomendación: Usa 127.0.0.1 en lugar de localhost
Razón: Es más confiable y evita problemas de resolución DNS en algunos sistemas.
2Abrir oauth_views.py
Ubicación: libros/oauth_views.py
3Corregir AMBAS funciones
Función 1: google_oauth_callback
@api_view(['GET', 'POST'])
@permission_classes([AllowAny])
def google_oauth_callback(request):
"""Callback de Google OAuth"""
code = request.GET.get('code')
if not code:
return Response({'error': 'No code provided'}, status=400)
token_url = 'https://oauth2.googleapis.com/token'
token_data = {
'code': code,
'client_id': settings.SOCIALACCOUNT_PROVIDERS['google']['APP']['client_id'],
'client_secret': settings.SOCIALACCOUNT_PROVIDERS['google']['APP']['secret'],
'redirect_uri': 'http://127.0.0.1:8000/api/auth/google/callback/', # ✅ USAR 127.0.0.1
'grant_type': 'authorization_code',
}
# ... resto del código
Función 2: google_oauth_redirect
@api_view(['GET'])
@permission_classes([AllowAny])
def google_oauth_redirect(request):
"""Genera URL de autorización de Google"""
google_auth_url = 'https://accounts.google.com/o/oauth2/v2/auth'
params = {
'client_id': settings.SOCIALACCOUNT_PROVIDERS['google']['APP']['client_id'],
'redirect_uri': 'http://127.0.0.1:8000/api/auth/google/callback/', # ✅ USAR 127.0.0.1
'response_type': 'code',
'scope': 'openid email profile',
'access_type': 'offline',
}
# ... resto del código
4Verificar en Google Cloud Console
Asegúrate de que en Google Cloud Console tengas AMBAS URIs:
http://127.0.0.1:8000/api/auth/google/callback/
http://localhost:8000/api/auth/google/callback/
Tener ambas asegura compatibilidad en cualquier caso
✅ SOLUCIÓN PARA ERROR 2: Loop infinito
⚠️ PROBLEMA COMPLEJO
Este error requiere revisión detallada del flujo OAuth completo.
Según el reporte: "Probé con la primera versión que tenía la guía, más los cambios que le había hecho, y en esa sí me deja logguearme"
Conclusión: Hay una discrepancia entre versiones de oauth_views.py
🔧 Pasos de diagnóstico:
1Verificar que el token se está generando
Agrega prints de debug en google_oauth_callback:
def google_oauth_callback(request):
code = request.GET.get('code')
print(f"📥 Code recibido: {code}") # Debug
# ... solicitar token ...
print(f"✅ Access token: {google_token_response.get('access_token')}") # Debug
print(f"✅ JWT generado: {jwt_token}") # Debug
# ... resto del código
2Verificar el script de oauth_login.html
Usa la versión corregida del Error #3 de la Guía v3.0
3Revisar el return en la función callback
Asegúrate de que la función retorna correctamente:
# Al final de google_oauth_callback:
return redirect(
f'/oauth/login/?access={jwt_token}&refresh={refresh_token}'
f'&email={user_info.get("email")}&username={user.username}'
)
📧 ARCHIVO ADJUNTO MENCIONADO
El estudiante menciona: "Ese archivo se lo adjuntaré en el correo"
Acción: Si tienes acceso a ese archivo oauth_views.py que funciona, úsalo como referencia.
Alternativa: Usa la versión de la Guía v3.0 que ya tiene correcciones aplicadas.
4TOKEN OAUTH RETORNA 401 EN TESTS
📍 UBICACIÓN EN LA GUÍA
Sección 2.2: Configurar JWT en Settings
Al ejecutar: python test_oauth.py
ERROR Token OAuth no es válido
=== Obteniendo Token OAuth 2.0 ===
✅ Token obtenido: gCMkTVM8G1fLnegrmhkqTzdrnNbCk3...
Status Code: 401
Data: {
'detail': 'El token dado no es valido para ningun tipo de token',
'code': 'token_not_valid',
'messages': [{
'token_class': 'AccessToken',
'token_type': 'access',
'message': 'Token is invalid'
}]
}
🔍 ¿POR QUÉ OCURRE?
CAUSA: Orden de autenticación en REST_FRAMEWORK
Django REST Framework procesa los métodos de autenticación EN ORDEN
Si JWTAuthentication está PRIMERO, intentará validar el token OAuth como si fuera JWT, fallando con error 401.
Orden INCORRECTO:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication', # ⬅️ Primero
'oauth2_provider.contrib.rest_framework.OAuth2Authentication', # ⬅️ Segundo
],
}
Problema: Cuando llega un token OAuth, JWTAuthentication lo intenta validar primero y falla.
✅ SOLUCIÓN: Cambiar el orden
1Abrir settings.py
Ubicación: biblioteca_project/settings.py
2Buscar REST_FRAMEWORK
Busca la configuración de REST_FRAMEWORK (aproximadamente línea 150-170)
3Cambiar el orden
Pon OAuth2Authentication PRIMERO:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'oauth2_provider.contrib.rest_framework.OAuth2Authentication', # ✅ PRIMERO
'rest_framework_simplejwt.authentication.JWTAuthentication', # Segundo
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
}
4Probar test_oauth.py nuevamente
python test_oauth.py
✅ Salida esperada
=== Obteniendo Token OAuth 2.0 ===
✅ Token obtenido: gCMkTVM8G1fLnegrmhkqTzdrnNbCk3...
Status Code: 200
Data: {
'count': 10,
'next': 'http://127.0.0.1:8000/api/libros/?page=2',
'previous': None,
'results': [
{
'id': 1,
'titulo': 'El Quijote',
'autor': 'Miguel de Cervantes',
...
},
...
]
}
📚 EXPLICACIÓN TÉCNICA
¿Cómo funciona DEFAULT_AUTHENTICATION_CLASSES?
Django REST Framework intenta autenticar en el orden especificado:
- Intenta el primer método
- Si funciona: ✅ Usuario autenticado
- Si falla: Pasa al siguiente
- Intenta el segundo método
- Si funciona: ✅ Usuario autenticado
- Si falla: Pasa al siguiente
- Si todos fallan: Retorna 401 Unauthorized
¿Por qué OAuth2Authentication primero?
- Tokens OAuth tienen formato específico más fácil de identificar
- JWTAuthentication puede confundirse con otros tipos de token
- OAuth2Authentication rechaza rápido si no es token OAuth
💡 ¿AFECTA A JWT?
NO. Cambiar el orden NO afecta el funcionamiento de JWT.
Si llega un token JWT válido:
- OAuth2Authentication lo rechaza (no es token OAuth)
- Pasa a JWTAuthentication
- JWTAuthentication lo valida ✅
Ambos tipos de token funcionan perfectamente.
✅ CHECKLIST DE VERIFICACIÓN
Antes de continuar, verifica que corregiste:
| # | Corrección | Aplicada |
|---|---|---|
| 1 | Eliminado .Models. en OAUTH2_PROVIDER settings |
☐ |
| 2 | Instalado django-extensions y agregado a INSTALLED_APPS |
☐ |
| 3 | Unificado redirect_uri en ambas funciones de oauth_views.py |
☐ |
| 4 | OAuth2Authentication ANTES de JWTAuthentication en REST_FRAMEWORK | ☐ |
| ✓ | python manage.py check sin errores |
☐ |
| ✓ | python manage.py show_urls funciona |
☐ |
| ✓ | Login con Google funciona correctamente | ☐ |
| ✓ | python test_oauth.py retorna 200 OK |
☐ |
📚 RECURSOS Y AYUDA ADICIONAL
🔗 Otras guías de correcciones:
💡 Consejos para evitar errores:
- Lee con atención: Cada carácter cuenta en programación
- Copia y pega con cuidado: Verifica que no haya caracteres extra
- Prueba frecuentemente:
python manage.py checkdespués de cada cambio - Usa Git: Haz commits frecuentes para poder revertir cambios
- Lee los mensajes de error: Django es muy descriptivo en sus errores
📧 ¿Encontraste otro error?
Si encuentras un error que NO está en esta guía:
- Documenta el error completo (screenshot + mensaje)
- Anota qué estabas haciendo cuando ocurrió
- Comparte con tus compañeros
- Ayudarás a futuros estudiantes 🎓