Express.js
Tokens y JWT con criterio
Explica cuándo usar tokens y JWT, cómo validar firma, issuer, audience y expiración, y qué límites tienen para revocación, sesiones y autorización.
- Última actualización
- Actualizada
- Nivel
- Aplicación
Express.js
Explica cuándo usar tokens y JWT, cómo validar firma, issuer, audience y expiración, y qué límites tienen para revocación, sesiones y autorización.
JWT es un formato de claims firmado. No cifra el payload, no crea una sesión completa y no resuelve automáticamente revocación, almacenamiento ni autorización.
Un JSON Web Token suele tener tres partes:
base64url(header).base64url(payload).base64url(signature)La firma permite detectar cambios y verificar quién emitió el token cuando la clave y algoritmo son confiables. El contenido del payload puede leerse sin conocer la clave.
Un servicio puede recibir una credencial autocontenida con identidad, issuer, audience y expiración sin consultar una session store en cada request.
Esto puede ser útil en APIs distribuidas, pero traslada complejidad a:
Claims estándar frecuentes:
sub: sujeto.iss: issuer.aud: audience.exp: expiración.nbf: no válido antes de.iat: momento de emisión.jti: identificador único.Claims privados pueden incluir tenant o scopes, pero no secretos ni datos que deban cambiar inmediatamente.
const payload = await jwtVerify(token, publicKey, {
issuer: 'https://identity.example.com',
audience: 'orders-api',
algorithms: ['RS256'],
});Debes validar:
nbf cuando existaDecodificar base64 no autentica.
HMAC usa el mismo secreto para firmar y verificar. Es simple, pero cualquier verificador también puede emitir tokens si conoce la clave.
RSA o EC permiten que el issuer conserve clave privada y servicios usen públicas. Facilita separación, pero requiere distribución y rotación.
Nunca aceptes el algoritmo indicado por el token sin una whitelist.
Debe ser corto y limitado:
Un access token robado suele ser válido hasta expirar o hasta que exista revocación adicional.
Permite obtener nuevos access tokens. Debe tratarse como credencial de alta sensibilidad:
No necesita ser JWT. Un valor opaco almacenado hasheado puede simplificar revocación.
El header puede incluir kid para seleccionar clave. El verificador debe obtener claves desde una fuente confiable y evitar ataques donde el token controle una URL o path arbitrario.
Durante rotación:
Un JWT autocontenido no se revoca mágicamente. Opciones:
jtiCada opción reintroduce estado o coste de consulta.
Si el token incluye roles por una hora y el usuario pierde acceso, la API podría aceptar el rol hasta expirar. Para permisos críticos:
No incluyas toda la matriz de permisos por comodidad.
Reduce lectura por JavaScript, pero el navegador la envía automáticamente y aparece riesgo CSRF.
El cliente lo añade explícitamente; reduce CSRF clásico, pero guardar el token en localStorage aumenta impacto de XSS.
La elección depende de arquitectura, clientes y threat model. No existe una ubicación universalmente “segura”.
export function makeBearerAuthentication(verifier: TokenVerifier): RequestHandler {
return async (request, response, next) => {
const authorization = request.get('authorization');
if (!authorization?.startsWith('Bearer ')) {
response.status(401).set('WWW-Authenticate', 'Bearer').json({
code: 'AUTHENTICATION_REQUIRED',
});
return;
}
const token = authorization.slice(7);
const claims = await verifier.verify(token);
response.locals.actor = {
id: claims.subject,
tenantId: claims.tenantId,
scopes: claims.scopes,
};
next();
};
}El middleware verifica credencial; la autorización del recurso ocurre después.
Sistemas distribuidos pueden diferir algunos segundos. Configura tolerancia pequeña, no ignores expiración.
Firma válida no basta; aud debe corresponder al servicio.
El token puede seguir criptográficamente válido. Decide si consultas estado actual.
Eliminar token del cliente no revoca copias robadas. Revoca refresh/session y limita access token.
Aumenta headers, logs y ancho de banda; puede superar límites de proxies.
Incluye:
nbf futuroJWT reduce lookup y facilita interoperabilidad, pero aumenta complejidad de lifecycle y revocación. Sessions simplifican invalidación, pero necesitan store. Un sistema puede usar ambos: session en navegador y tokens internos de corta duración.
aud?Authentication e identidad amplía cómo verificar credenciales y producir un actor interno confiable.