Login
Autentica a un usuario con email y contraseña, y devuelve tokens de acceso y refresh.
Endpoint
POST /api/v1/auth/login
Autenticación
No se requiere autenticación (endpoint público).
Request
Content-Type
application/json
Request Body
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
email | string | Sí | Dirección de email del usuario |
password | string | Sí | Contraseña del usuario |
Ejemplo de Request
{
"email": "juan@ejemplo.com",
"password": "ContraseñaSegura123!"
}
Response
Response Exitoso (200 OK)
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}
Campos del Response
| Campo | Tipo | Descripción |
|---|---|---|
access_token | string | Token de acceso JWT para requests de API (expira en 30 minutos) |
refresh_token | string | Token refresh JWT para obtener nuevos tokens de acceso (expira en 7 días) |
token_type | string | Siempre "bearer" |
Ejemplos
curl -X POST https://api.callcov.com/api/v1/auth/login \-H "Content-Type: application/json" \-d '{ "email": "juan@ejemplo.com", "password": "ContraseñaSegura123!"}'Flujo de Login con Gestión de Tokens
import requests
from datetime import datetime, timedelta
class CallCovClient:
def __init__(self):
self.base_url = "https://api.callcov.com/api/v1"
self.access_token = None
self.refresh_token = None
self.token_expiry = None
def login(self, email, password):
"""Login y almacenar tokens"""
response = requests.post(
f"{self.base_url}/auth/login",
json={"email": email, "password": password}
)
if response.status_code == 200:
data = response.json()
self.access_token = data['access_token']
self.refresh_token = data['refresh_token']
# El token de acceso expira en 30 minutos
self.token_expiry = datetime.now() + timedelta(minutes=30)
return True
return False
def get_headers(self):
"""Obtener headers de autorización con refresh de token"""
# Refrescar token si expiró o expira pronto (dentro de 5 minutos)
if (self.token_expiry and
datetime.now() + timedelta(minutes=5) >= self.token_expiry):
self.refresh_access_token()
return {"Authorization": f"Bearer {self.access_token}"}
def refresh_access_token(self):
"""Refrescar el token de acceso"""
response = requests.post(
f"{self.base_url}/auth/refresh",
json={"refresh_token": self.refresh_token}
)
if response.status_code == 200:
data = response.json()
self.access_token = data['access_token']
self.refresh_token = data['refresh_token']
self.token_expiry = datetime.now() + timedelta(minutes=30)
# Uso
client = CallCovClient()
if client.login("juan@ejemplo.com", "ContraseñaSegura123!"):
# Hacer requests autenticados
response = requests.get(
f"{client.base_url}/users/me",
headers=client.get_headers()
)
print(response.json())
Errores
401 Unauthorized
Email o contraseña incorrectos:
{
"detail": "Email o contraseña incorrectos"
}
403 Forbidden
La cuenta de usuario está inactiva:
{
"detail": "La cuenta de usuario está inactiva"
}
Email no verificado:
{
"detail": "Por favor verificá tu dirección de email antes de iniciar sesión"
}
Verificaciones Pre-Login
Antes de permitir el login, la API verifica:
- Usuario existe: El email está registrado
- Contraseña correcta: La contraseña coincide con la contraseña hasheada
- Cuenta activa:
is_activeestrue - Email verificado:
is_verifiedestrue
Si alguna verificación falla, el login es rechazado.
Consideraciones de Seguridad
- Contraseña nunca devuelta: Las contraseñas nunca se incluyen en los responses
- Limitación de tasa: El endpoint de login tiene limitación de tasa para prevenir ataques de fuerza bruta
- Bloqueo de cuenta: Después de 5 intentos fallidos, la cuenta se bloquea temporalmente (configurable)
- Almacenamiento seguro de contraseñas: Las contraseñas se hashean con bcrypt
- HTTPS requerido: Siempre usar HTTPS en producción
Expiración de Tokens
| Tipo de Token | Expiración | Acción Cuando Expira |
|---|---|---|
| Access Token | 30 minutos | Usar token refresh para obtener uno nuevo |
| Refresh Token | 7 días | El usuario debe iniciar sesión de nuevo |
Usando Tokens de Acceso
Después del login, incluir el token de acceso en todos los requests autenticados:
curl https://api.callcov.com/api/v1/users/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Integración con Frontend
Manejo típico de formulario de login:
async function handleLogin(email, password) {
try {
const response = await fetch('https://api.callcov.com/api/v1/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail);
}
const { access_token, refresh_token } = await response.json();
// Almacenar tokens de forma segura
localStorage.setItem('access_token', access_token);
localStorage.setItem('refresh_token', refresh_token);
// Redirigir al dashboard
window.location.href = '/dashboard';
} catch (error) {
console.error('Login falló:', error.message);
alert(error.message);
}
}
Resolución de Problemas
"Por favor verificá tu dirección de email antes de iniciar sesión"
Solución: El usuario debe verificar su email primero. Puede:
- Revisar su email para el enlace de verificación
- Hacer clic en el enlace para verificar
- O usar reenviar verificación si no recibió el email
"La cuenta de usuario está inactiva"
Solución: Contactar a soporte - la cuenta ha sido desactivada.
"Email o contraseña incorrectos"
Solución:
- Verificar ortografía del email
- Verificar contraseña (sensible a mayúsculas)
- Usar restablecimiento de contraseña si la olvidó
Relacionado
- Registrarse - Crear nueva cuenta
- Token Refresh - Obtener nuevo token de acceso
- Restablecimiento de Contraseña - Restablecer contraseña olvidada
- Perfil de Usuario - Obtener información del usuario autenticado