Autenticación con JWT
Los JWT (JSON Web Tokens) se usan cuando tu aplicación tiene usuarios humanos que inician sesión. Cada usuario tiene su propio token, asociado a una empresa.
Flujo básico
1. Usuario introduce email + password
2. Tu app llama a POST /auth/login
3. Recibe access_token (JWT) + refresh_token
4. Guarda ambos tokens (memoria + almacenamiento seguro)
5. Envía Authorization: Bearer <access_token> en cada petición
6. Cuando el access_token caduca (8h), pide uno nuevo con el refresh_token
Login
POST /auth/login
POST /api/auth/login HTTP/1.1
Host: api.tpvready.es
Content-Type: application/json
{
"email": "admin@farmacia.es",
"password": "miPasswordSeguro123"
}
Respuesta (200):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"expires_in": 28800,
"usuario": {
"token": "...",
"nombre": "Juan García",
"email": "admin@farmacia.es",
"rol": "admin"
}
}
Errores comunes:
| Código | Cuándo |
|---|---|
401 | Credenciales incorrectas |
403 | Usuario suspendido o empresa bloqueada |
422 | Email/password mal formados |
Usar el access_token
Incluye la cabecera Authorization en cada petición:
GET /api/clientes HTTP/1.1
Host: api.tpvready.es
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Ejemplo Python
import requests
# Tras login
access_token = "eyJ..."
resp = requests.get(
"https://api.tpvready.es/api/clientes",
headers={"Authorization": f"Bearer {access_token}"},
)
Renovar el token (refresh)
El access_token caduca a las 8 horas. Antes de que expire (o cuando recibas un 401), usa el refresh_token para obtener uno nuevo sin volver a pedir las credenciales:
POST /auth/refresh
POST /api/auth/refresh HTTP/1.1
Host: api.tpvready.es
Content-Type: application/json
{
"refresh_token": "eyJ..."
}
Respuesta: mismo formato que login, con un nuevo access_token.
Otros endpoints públicos relacionados
| Endpoint | Para qué |
|---|---|
POST /auth/registro | Registrar empresa nueva |
POST /auth/google | Login/registro con Google Sign-In |
GET /auth/verificar-email | Validar email tras registro |
POST /auth/reset-password | Solicitar email de reset |
POST /auth/reset-password/confirmar | Establecer nueva contraseña con token de email |
GET /auth/me | Datos del usuario autenticado (requiere JWT) |
Ver detalles y esquemas en la referencia interactiva.
Buenas prácticas
✅ No bloquees el JWT en localStorage si tu app es una webapp expuesta a XSS. Usa cookies HttpOnly cuando sea posible.
✅ Implementa refresh transparente. Cuando recibas un 401, intenta refresh automáticamente y reintenta la petición original. Solo redirige a login si el refresh también falla.
✅ No reutilices tokens entre dispositivos/contextos. Cada sesión debe tener su propio par access/refresh.
✅ Cierra sesión correctamente. En el lado cliente, simplemente borra los tokens. (El JWT seguirá siendo técnicamente válido hasta su expiración, pero ya no podrá usarse desde tu app.)
❌ No mandes el JWT en URLs (?token=...). Va siempre en la cabecera Authorization.
❌ No uses JWT para integraciones servidor-a-servidor. Para eso están las API Keys, que no caducan y no requieren un usuario humano.
Permisos del JWT
El JWT incluye el rol del usuario (admin, vendedor, contable, etc.). Los endpoints aplican estos permisos automáticamente:
- Admin: acceso completo a su empresa.
- Vendedor: ventas, clientes, TPV, productos (lectura).
- Contable: facturas, contabilidad, tesorería.
- Solo lectura: lectura de todo, sin escritura.
Si un usuario sin permisos intenta acceder a un endpoint restringido, recibe 403 Forbidden.
A diferencia de las API Keys con scopes, los permisos del JWT son fijos según el rol asignado en TPVReady; no se pueden personalizar por endpoint.