Saltar al contenido

Flujo de autenticación JWT: tokens de acceso, tokens de actualización y revocación

Cómo funciona la autenticación JWT de punta a punta: emitir y validar tokens de acceso, rotar tokens de actualización, guardar tokens en el navegador y revocarlos antes.

· Fundador y desarrollador

Publicado el

Diagrama de secuencia con tres líneas de vida: app de navegador, servidor de autorización y API de pedidos. El login devuelve un token de acceso y uno de actualización. La app llama a la API con un token bearer. Un fragmento opt muestra la caducidad: 401, refresh, nuevos tokens, reintento.

Los JSON Web Tokens son populares porque una API puede comprobar uno sin llamar a nadie: verificar la firma, leer los claims y listo. Esa propiedad también es el origen de la mayoría de los problemas con JWT. Un token que no puedes consultar es un token que no puedes retirar, y los equipos lo descubren la primera vez que roban un portátil o alguien deja la empresa.

Este artículo recorre un flujo de autenticación JWT completo con tokens de acceso, tokens de actualización y un diagrama de secuencia, y luego cubre las comprobaciones que necesita toda API, dónde guardar los tokens en un navegador, la rotación de tokens de actualización, la rotación de claves y las opciones realistas de revocación.

Qué es un JWT y qué no es

Un JWT (RFC 7519) es una cadena compacta y segura para URL formada por tres partes en base64url separadas por puntos: una cabecera, un payload de claims y una firma. Decodificado, un token de acceso tiene este aspecto:

{ "alg": "RS256", "kid": "2026-10", "typ": "at+jwt" }
{
  "iss": "https://auth.example.com",
  "sub": "user_8412",
  "aud": "orders-api",
  "scope": "orders:read orders:write",
  "iat": 1793606400,
  "exp": 1793607300,
  "jti": "a3f1c9e2"
}

Tres puntos causan la mayoría de los malentendidos:

  • Un JWT firmado no está cifrado. Cualquiera que tenga el token puede leer el payload. No metas secretos ni datos personales que el portador no deba ver.
  • JWT es un formato, no un protocolo. Cómo obtiene un cliente un token se define en otro sitio, normalmente en OAuth 2.0 y OpenID Connect. El diagrama de flujo de OAuth 2.0 cubre esa parte.
  • No todos los tokens de un flujo son JWT. Los tokens de acceso suelen serlo; los de actualización suelen ser cadenas aleatorias opacas que solo el servidor de autorización puede consultar.

Los claims registrados que encontrarás en cada token:

Claim Significado Quién lo comprueba
iss Issuer, el servidor de autorización que firmó el token API
sub Subject, normalmente el ID del usuario API, para la autorización
aud Audience, la API a la que va dirigido el token API
exp, nbf, iat Caducidad, inicio de validez y hora de emisión, en segundos desde la época Unix API
jti ID único del token, útil para listas de denegación API o gateway

El flujo, paso a paso

  1. Inicio de sesión. El usuario se autentica en el servidor de autorización, normalmente con el flujo de código de autorización de OAuth con PKCE.
  2. Respuesta con tokens. El servidor de autorización devuelve un token de acceso de corta duración (un JWT, digamos de 15 minutos) y un token de actualización de larga duración.
  3. Llamada a la API. La app envía Authorization: Bearer <access token> con cada petición.
  4. Validación local. La API verifica la firma con la clave pública del servidor de autorización, que obtuvo una vez del endpoint JWKS y guardó en caché, y después comprueba los claims. No hay llamada al servidor de autorización por petición.
  5. Caducidad. Pasados 15 minutos, la API responde 401 Unauthorized.
  6. Actualización. La app envía el token de actualización al endpoint de tokens del servidor de autorización y obtiene un nuevo token de acceso y, con rotación, un nuevo token de actualización.
  7. Reintento. La app repite la petición fallida con el nuevo token de acceso.

Los pasos 3 y 4 son la razón por la que los equipos eligen JWT: miles de peticiones a la API y ningún almacén de sesiones compartido. Los pasos 5 y 6 son el precio, y ahí está la mayor parte del trabajo de seguridad.

Validar un token: la lista de comprobaciones

Toda API que acepte JWT debería hacer las mismas comprobaciones, en este orden:

  1. Permite solo los algoritmos que esperas. Nunca te fíes sin más de la cabecera alg. El RFC 8725 describe los dos ataques clásicos: alg puesto a none y un token RS256 reescrito como HS256 para que una biblioteca ingenua lo verifique usando la clave pública como secreto HMAC.
  2. Elige la clave por kid en el JWKS en caché, y vuelve a descargar el conjunto cuando veas un kid desconocido, como mucho una vez por intervalo corto.
  3. Verifica la firma.
  4. Comprueba iss y aud. Un token emitido para otra API debe fallar aquí.
  5. Comprueba exp y nbf con una pequeña tolerancia de reloj, por ejemplo 60 segundos.
  6. Comprueba el tipo de token. Los tokens de acceso del RFC 9068 llevan typ: at+jwt, lo que impide reutilizar un ID token como token de acceso.
  7. Después autoriza: scopes, roles y propiedad del recurso.

Con la biblioteca jose en Node.js, casi toda la lista es una sola llamada:

import { createRemoteJWKSet, jwtVerify } from 'jose'

const JWKS = createRemoteJWKSet(new URL('https://auth.example.com/.well-known/jwks.json'))

export async function verifyAccessToken(token: string) {
  const { payload } = await jwtVerify(token, JWKS, {
    issuer: 'https://auth.example.com',
    audience: 'orders-api',
    algorithms: ['RS256'],
    typ: 'at+jwt',
    clockTolerance: 60,
  })
  return payload // scopes and sub are checked by the caller
}

¿Cuánto debería durar un token de acceso?

La duración es la ventana en la que un token robado funciona y no se puede retirar. Más corta significa más segura y más tráfico de actualización. Para un usuario activo durante una jornada laboral de ocho horas:

Duración del token de acceso Exposición si lo roban Actualizaciones por usuario y día
5 minutos 5 minutos 96
15 minutos 15 minutos 32
1 hora 1 hora 8
24 horas 24 horas 1

La mayoría de los equipos se quedan entre 5 y 15 minutos para los tokens de acceso. Un token de acceso que dura un día es una cookie de sesión que no puedes revocar.

Rotación de tokens de actualización

Un token de actualización vive días o semanas, así que filtrar uno es peor que filtrar un token de acceso. El RFC 9700, la mejor práctica actual de seguridad de OAuth, exige una de dos protecciones para los tokens de actualización que guardan los clientes públicos, como las apps de navegador y las apps móviles:

  • Tokens de actualización vinculados al emisor, ligados a una clave que tiene el cliente, con TLS mutuo o DPoP.
  • Rotación: cada actualización devuelve un nuevo token de actualización e invalida el anterior, mientras el servidor de autorización recuerda la cadena. Si un atacante y el cliente legítimo usan el mismo token, uno de ellos presenta un token invalidado y el servidor revoca el token de actualización activo, lo que termina la cadena para ambos.

La rotación convierte un token de actualización robado, que sería un problema de semanas, en uno que termina la próxima vez que el cliente legítimo actualiza. El coste: el usuario tiene que volver a iniciar sesión, y tu endpoint de tokens debe soportar que dos pestañas actualicen a la vez sin disparar la detección de reutilización, normalmente con un breve periodo de gracia.

Dónde guardar los tokens en un navegador

Almacenamiento Legible por JavaScript Riesgo principal Notas
localStorage Sí Cualquier XSS puede robar los tokens Sobrevive a las recargas; evítalo para los tokens de actualización
Solo en memoria Sí, mientras la página vive XSS durante la sesión Se pierde al recargar; actualiza al arrancar
Cookie HttpOnly No CSRF Usa Secure, SameSite y tokens CSRF en las peticiones que cambian estado
Backend for frontend No; los tokens se quedan en el servidor Gestión de sesiones en el servidor El navegador solo tiene una cookie de sesión

El borrador del IETF sobre OAuth para aplicaciones basadas en navegador describe el patrón backend for frontend como la opción que mantiene los tokens completamente fuera del alcance de JavaScript. Si guardas los tokens en el navegador, mantén el token de acceso en memoria y el de actualización en una cookie HttpOnly limitada al endpoint de tokens.

Revocación: lo que funciona de verdad

No puedes «desfirmar» un JWT. Solo puedes hacer que la API deje de aceptarlo, y cada opción devuelve parte del estado que te ahorrabas:

Estrategia Cómo funciona Coste
Caducidad corta Los tokens mueren solos en minutos Ninguno; la ventana de exposición se mantiene
Revocar el token de actualización La siguiente actualización falla, así que el acceso termina en la próxima caducidad Una consulta en el endpoint de tokens, que ya tiene estado
Lista de denegación por jti Los gateways rechazan los ID listados hasta su exp Una caché compartida, consultada en cada petición
Corte por usuario Rechazar los tokens emitidos antes de una marca de tiempo guardada para ese usuario Una consulta por usuario, cacheable
Introspección La API pregunta al servidor de autorización por cada token (RFC 7662) Una llamada de red; úsala solo en endpoints de alto riesgo

Una combinación práctica: tokens de acceso de 15 minutos o menos, tokens de actualización rotatorios que se revocan al cerrar sesión y al cambiar la contraseña, y un corte por usuario para el caso poco frecuente de «cerrar sesión en todas partes ya».

Rotar las claves de firma

Las claves se filtran y los algoritmos envejecen, así que planifica la rotación desde el primer día. Publica la nueva clave pública en el JWKS más o menos un día antes de firmar con ella, para que esté en la caché de todas las APIs. Cambia la firma al nuevo kid. Mantén la clave antigua en el JWKS hasta que caduque el último token firmado con ella y después retírala. Una API que vuelve a descargar el conjunto ante un kid desconocido sobrevive a una rotación de emergencia sin reiniciar.

El diagrama del flujo JWT

Diagrama de secuencia con tres líneas de vida: app de navegador, servidor de autorización y API de pedidos. El login devuelve un token de acceso y uno de actualización. La app llama a la API con un token bearer. Un fragmento opt muestra la caducidad: 401, refresh, nuevos tokens, reintento.

5 componentes · 12 conexiones

Abrir en Archboard
Contenido del diagrama
  • Browser app
  • Auth server
  • Orders API
  • access token expired
  • 1. Sign in (OAuth code flow + PKCE)
  • 2. Access token (JWT, 15 min) + refresh token
  • 3. GET /orders, Authorization: Bearer JWT
  • GET /.well-known/jwks.json (once, then cached)
  • public keys
  • 4. 200 OK
  • 5. GET /orders (expired JWT)
  • 6. 401 Unauthorized
  • 7. POST /token (refresh token)
  • 8. New token pair, old refresh token invalidated
  • 9. Retry GET /orders with new JWT
  • 10. 200 OK
Una app de navegador inicia sesión, llama a una API con un token de acceso JWT de corta duración y usa un token de actualización rotatorio cuando el de acceso caduca. La API valida los tokens localmente con claves del endpoint JWKS del servidor de autorización.

Cómo leerlo:

  • Tres líneas de vida. La app de navegador a la izquierda, el servidor de autorización en el centro y la API de pedidos a la derecha. El tiempo avanza hacia abajo.
  • El inicio de sesión y la respuesta con tokens arriba: la app recibe un token de acceso y uno de actualización.
  • El camino feliz: la petición bearer a la API y su respuesta. La API valida el token con las claves JWKS en caché y nunca llama al servidor de autorización.
  • El fragmento opt cubre la caducidad: 401, actualización, un nuevo par de tokens con el token de actualización anterior invalidado y la petición reintentada.
  • El bloque Markdown muestra el token decodificado y las comprobaciones de validación.

Dibujar flujos de autenticación que los revisores puedan comprobar

  • Nombra cada token en cada flecha, con su tipo y su duración: «token de acceso (JWT, 15 min)». La ambigüedad sobre qué token viaja adónde esconde bugs reales.
  • Muestra dónde se valida. Pon una nota en la línea de vida que verifica la firma y di de dónde salen sus claves.
  • Dibuja los caminos de fallo. La caducidad, la reutilización de tokens de actualización y el cierre de sesión van en fragmentos; ahí empiezan la mayoría de los incidentes.
  • Deja los secretos fuera del dibujo. Usa valores de ejemplo; los diagramas se comparten más de lo que esperas.

El ejemplo de diagrama de secuencia trata en detalle las líneas de vida y los fragmentos, y el diagrama de arquitectura zero trust muestra dónde encajan las comprobaciones de tokens en un modelo de acceso más amplio.

Constrúyelo en Archboard

  1. Inicia sesión con Google o GitHub y crea un diagrama.
  2. Añade tres nodos Línea de vida del pack Secuencia: Browser app, Auth server y Orders API.
  3. Dibuja los mensajes como aristas entre las líneas de vida, de arriba abajo: inicio de sesión, respuesta con tokens, la petición bearer y su respuesta. Etiqueta cada uno con el token que lleva.
  4. Añade un Fragmento combinado del pack Secuencia con el operador opt alrededor del camino de caducidad: 401, petición de actualización, nuevo par de tokens, reintento.
  5. Añade un bloque Markdown del pack Básico con el token decodificado y la lista de comprobaciones.

El ejemplo usa 5 nodos de diagrama, dentro del plan Free.

Preguntas frecuentes

¿Los JWT están cifrados? Los JWT firmados no. El payload está codificado en base64url y cualquiera que tenga el token puede leerlo. Existe JSON Web Encryption para los tokens cifrados, pero la mayoría de los tokens de acceso solo van firmados.

¿Debería guardar un JWT en localStorage? Evítalo para cualquier cosa de larga duración. Cualquier bug de cross-site scripting puede leer localStorage. Guarda los tokens de acceso en memoria y los de actualización en una cookie HttpOnly, o mantén los tokens en un backend for frontend.

¿Cómo cierro la sesión de un usuario si los JWT no tienen estado? Revoca el token de actualización para que no se emitan nuevos tokens de acceso, y mantén cortos los tokens de acceso. Para un efecto inmediato, añade una marca de corte por usuario o una lista de denegación por jti que tu API compruebe.

¿Qué diferencia hay entre un ID token y un token de acceso? Un ID token le dice al cliente quién ha iniciado sesión y está destinado al cliente. Un token de acceso está destinado a una API. Las APIs deberían rechazar los ID tokens; las comprobaciones de typ y aud lo hacen explícito.

¿Debería usar HS256 o RS256? HS256 usa un único secreto compartido, así que cualquier servicio que verifique tokens también puede emitirlos. RS256 o ES256 permite a las APIs verificar con una clave pública mientras solo el servidor de autorización tiene la clave privada, que es la opción más segura por defecto cuando hay más de un servicio.

Empieza gratis — un puesto, sin tarjeta de crédito.

Artículos relacionados

← Volver al blog

Abre un lienzo en un minuto

Inicia sesión con Google o GitHub. Gratis para un asiento. Mejora el plan cuando se una el equipo.