El recorrido de extremo a extremo
[Front] login(usuario, contraseña)
│ POST /login { usuario, contraseña }
▼
[Back] valida credenciales ──> emite token firmado (con exp)
│ 200 { token }
▼
[Front] guarda el token y lo adjunta en cada petición:
│ GET /perfil Authorization: Bearer <token>
▼
[Back] verifica el token ──> sabe quién eres ──> responde
Paso a paso
- Login: el usuario envía
usuarioycontraseña. El backend comprueba la contraseña (contra el hash guardado, nunca contra la contraseña en claro). - Emisión: si es correcta, el backend emite una credencial: un token
firmado (JWT) o un id de sesión. Incluye una caducidad (
exp). - Guardado en el front: el frontend guarda la credencial (cookie o
localStorage). - Adjuntar: en cada petición posterior el front manda la credencial. Con
JWT, en la cabecera
Authorization: Bearer <token>. - Verificación: el backend lee la cabecera, verifica la firma y la
caducidad, y carga el usuario (p. ej. en
req.usuario). - Rutas protegidas: un middleware corta el paso con 401 si no hay credencial válida, antes de llegar al handler.
Expiración y refresh tokens
Un token de acceso debe durar poco (minutos): si lo roban, el daño caduca pronto. Pero pedirle al usuario que vuelva a hacer login cada 15 minutos es horrible. Solución: dos tokens.
- Access token: vida corta, se adjunta en cada petición.
- Refresh token: vida larga, se guarda con más cuidado y solo se usa para pedir un nuevo access token cuando el anterior caduca, sin re-login.
Así combinas seguridad (ventana de robo pequeña) y comodidad (sesiones largas sin molestar al usuario).
Ejemplos
Leer 'Bearer <token>' de la cabecera Authorization
const headers = { Authorization: "Bearer abc.def.ghi" };
const cabecera = headers.Authorization || "";
const [esquema, token] = cabecera.split(" ");
console.log(esquema, token); // Bearer abc.def.ghi