6 min

¿Qué es un JWT? Guía clara sobre JSON Web Tokens

Aprende qué es un JWT (JSON Web Token), cómo funcionan sus tres partes, dónde se usan y las recomendaciones de seguridad clave para evitar errores comunes.

¿Qué es un JWT? Guía clara sobre JSON Web Tokens

JWT en términos sencillos

Un JWT (JSON Web Token) es una cadena compacta y segura para URLs que representa un conjunto de información (normalmente sobre un usuario o sesión) de forma que puede transmitirse entre sistemas. A menudo lo verás como un valor largo que empieza con algo como eyJ..., enviado en una cabecera HTTP como Authorization: Bearer \u003ctoken\u003e.

¿Por qué usar un token?

Los inicios de sesión tradicionales suelen apoyarse en sesiones en el servidor: después de iniciar sesión, el servidor guarda datos de sesión y entrega al navegador una cookie con el ID de sesión. Cada petición incluye esa cookie y el servidor consulta la sesión.

Con autenticación basada en tokens, el servidor puede evitar mantener estado de sesión para cada petición del usuario. En su lugar, el cliente guarda un token (como un JWT) y lo incluye en las llamadas a la API. Esto es popular para APIs porque:

  • funciona bien entre múltiples servicios (gateways, microservicios)
  • encaja con apps móviles y SPAs que llaman APIs directamente
  • reduce la necesidad de almacenamiento de sesión compartido entre servidores

Matiz importante: “sin estado” no significa “sin comprobaciones en servidor”. Muchos sistemas reales siguen validando tokens contra el estado del usuario, rotación de claves o mecanismos de revocación.

Autenticación vs autorización (en palabras simples)

  • Autenticación responde: ¿Quién eres? (Inicias sesión y demuestras tu identidad.)
  • Autorización responde: ¿Qué puedes hacer? (Leer facturas, editar proyectos, acceder a páginas de administración, etc.)

Los JWT suelen llevar pruebas de autenticación (estás autenticado) y pistas básicas de autorización (roles, permisos, scopes), pero tu servidor debe seguir aplicando las reglas de autorización.

Dónde aparecen los JWT

Suele usarse JWT como tokens de acceso en:

  • APIs web
  • SPAs
  • apps móviles
  • sistemas que usan OAuth 2.0 u OpenID Connect (OIDC)

Estructura del JWT: cabecera, payload y firma

Un JWT es una cadena compacta formada por tres partes, cada una codificada en base64url y separadas por puntos:

header.payload.signature

Ejemplo (redactado):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNzAwMDAwMDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c…

1) Cabecera

La cabecera describe cómo se creó el token—lo más importante es el algoritmo de firma (p. ej., HS256, RS256/ES256) y el tipo de token.

Campos comunes:

  • typ: a menudo "JWT" (frecuentemente ignorado en la práctica)
  • alg: el algoritmo de firma usado
  • kid: un identificador de clave para ayudar al verificador a seleccionar la clave correcta durante la rotación

Nota de seguridad: no confíes ciegamente en la cabecera. Aplica una lista de algoritmos permitidos que realmente uses y no aceptes alg: "none".

2) Payload

El payload contiene “claims” (campos) sobre el usuario y el contexto del token: para quién es, quién lo emitió y cuándo expira.

Importante: los JWT no están cifrados por defecto. La codificación Base64URL hace que el token sea seguro para URLs; no oculta los datos. Cualquiera que obtenga el token puede decodificar la cabecera y el payload.

Por eso debes evitar poner secretos (contraseñas, claves de API) o datos personales sensibles en un JWT.

3) Firma

La firma se crea firmando la cabecera + payload con una clave:

  • HS256: una secret compartida firma y verifica
  • RS256/ES256: una clave privada firma; una clave pública verifica

La firma proporciona integridad: permite verificar que el token no fue modificado y que fue emitido por un firmante de confianza. No proporciona confidencialidad.

Consideraciones de tamaño

Como un JWT incluye cabecera y payload en cada petición donde se envía, tokens más grandes implican más ancho de banda y sobrecarga. Mantén los claims compactos y prefiere identificadores en lugar de datos voluminosos.

Payload y claims: qué puedes (y no debes) almacenar

Implementa autenticación JWT más rápido
Crea una app protegida por JWT conversando, luego afina las reglas de verificación en el modo de planificación.

Los claims suelen agruparse en dos categorías: registrados (nombres estandarizados) y personalizados (campos de tu app).

Claims registrados comunes

  • iss (issuer): quién creó el token
  • sub (subject): a quién se refiere el token (a menudo un ID de usuario)
  • aud (audience): para quién está pensado el token (p. ej., una API específica)
  • exp (expiration time): cuándo debe dejar de aceptarse el token
  • iat (issued at): cuándo se creó el token
  • nbf (not before): no aceptar el token antes de este momento

Claims personalizados: mantenlos mínimos

Incluye solo lo que el servicio receptor realmente necesita para tomar una decisión de autorización.

Buenos ejemplos:

  • un identificador interno estable de usuario (user_id)
  • un pequeño conjunto de roles/privilegios (solo si puedes mantenerlos actualizados)
  • un ID de tenant/organización en aplicaciones multi-tenant

Evita claims de “conveniencia” que dupliquen muchos datos del perfil. Inflan el token, quedan obsoletos con rapidez y aumentan el impacto si el token se filtra.

Qué nunca debes poner en el payload de un JWT

Dado que el payload es legible, no almacenes:

  • contraseñas, claves de API, refresh tokens, ni ningún valor secreto
  • datos de pago, identificaciones gubernamentales o datos personales sensibles
  • nada que no quisieras que se copiase desde un navegador, proxy o registro

Si necesitas información sensible, guárdala en el servidor y pon solo una referencia (como un ID) en el token—o usa un formato de token cifrado (JWE) cuando proceda.

Cómo funciona la firma (y qué garantiza)

Firmar no es cifrar.

  • Firmar es como sellar una carta: la gente puede leerla, pero puede verificar que no se ha alterado.
  • Cifrar es como meter la carta en una caja cerrada: solo quien tiene la llave puede leerla.

Cuando se emite un JWT, el servidor firma la cabecera y el payload codificados. Cuando el token se presenta más tarde, el servidor recalcula la firma y la compara. Si alguien cambia aunque sea un carácter (p. ej., "role":"user" a "role":"admin"), la verificación falla y el token se rechaza.

JWT vs OAuth, OpenID Connect y tipos de tokens

JWT es un formato de token. OAuth 2.0 y OpenID Connect (OIDC) son protocolos que describen cómo las apps solicitan, emiten y usan tokens.

OAuth 2.0 y access/refresh tokens

OAuth 2.0 trata principalmente sobre autorización: permitir que una app acceda a una API en nombre de un usuario sin compartir la contraseña del usuario.

  • Access token: se presenta a una API para probar permiso; puede ser un JWT u un token opaco
  • Refresh token: token de vida más larga para obtener nuevos access tokens

Los access tokens suelen ser de corta duración (minutos). Duraciones cortas limitan el daño si un token se filtra.

OpenID Connect (OIDC) y ID tokens

OIDC añade autenticación (quién es el usuario) sobre OAuth 2.0 e introduce un ID token, que normalmente es un JWT.

  • ID token: para que la app cliente confirme la identidad del usuario
  • Access token: para que la API autorice peticiones

Regla clave: no uses un ID token para llamar a una API.

Si quieres más contexto sobre flujos prácticos, consulta /blog/jwt-authentication-flow.

Flujo común de autenticación con JWT

Practica la checklist de verificación
Valida temprano el emisor, la audiencia y la expiración usando un esqueleto de aplicación real.

Un flujo típico se ve así:

1) Inicio de sesión

El usuario inicia sesión (email/contraseña, SSO, etc.). Si tiene éxito, el servidor crea un JWT (a menudo un access token) con claims esenciales como el subject y la expiración.

2) Emisión del token

El servidor firma el token y lo devuelve al cliente (app web, móvil u otro servicio).

3) Llamadas a la API

Para endpoints protegidos, el cliente incluye el JWT en la cabecera Authorization:

Authorization: Bearer \u003cJWT\u003e

4) Verificación

Antes de atender la petición, la API normalmente comprueba:

  • firma (integridad + emisor de confianza)
  • exp (no caducado)
  • iss (emisor esperado)
  • aud (destinado a esta API)

Si todas las comprobaciones pasan, la API trata al usuario como autenticado y aplica reglas de autorización (p. ej., permisos a nivel de registro).

5) Una nota rápida sobre desajuste de reloj

Como los relojes de los sistemas derivan, muchos sistemas permiten un pequeño desajuste de reloj al validar claims basados en tiempo como exp (y a veces nbf). Mantén el desajuste pequeño para no alargar la validez del token más de lo previsto.

Dónde almacenar JWTs con seguridad

Las opciones de almacenamiento cambian qué atacantes pueden robar y con qué facilidad pueden reproducir un token.

Apps en navegador: memoria vs localStorage vs cookies

Almacenamiento en memoria (a menudo recomendado para SPAs) mantiene el access token en el estado JS. Se borra al recargar y reduce el riesgo de “robarlo después”, pero un bug XSS aún puede leerlo mientras la página está activa. Combínalo con tokens de corta vida y un flujo de refresh.

localStorage/sessionStorage son fáciles pero arriesgados: cualquier XSS puede exfiltrar tokens del almacenamiento web. Si los usas, trata la prevención de XSS como algo no negociable (CSP, escape de salida, higiene de dependencias) y mantén tokens de corta duración.

Cookies seguras (a menudo el valor por defecto más seguro para web) almacenan tokens en una cookie HttpOnly para que JavaScript no pueda leerlos—reduciendo el impacto del robo por XSS. El intercambio es el riesgo de CSRF, ya que los navegadores adjuntan cookies automáticamente.

Si usas cookies, configura:

  • HttpOnly
  • Secure (solo HTTPS)
  • SameSite=Lax o SameSite=Strict (algunos flujos cross-site pueden necesitar SameSite=None; Secure)

También considera tokens CSRF para peticiones que cambian estado.

Apps móviles: prefiere el almacenamiento seguro del SO

En iOS/Android, guarda tokens en el almacenamiento seguro de la plataforma (Keychain / Keystore respaldado). Evita archivos planos o preferencias. Si tu modelo de amenaza incluye dispositivos rooteados/jailbreakeados, asume extracción posible y confía en tokens de corta vida y controles server-side.

Principio de menor privilegio

Limita lo que un token puede hacer: usa scopes/claims mínimos, mantén access tokens de corta duración y evita incrustar datos sensibles.

Errores comunes de seguridad con JWT que debes evitar

Los JWT son convenientes, pero muchos incidentes provienen de errores previsibles. Trata un JWT como efectivo: quien lo obtiene, a menudo puede gastarlo.

1) Expiraciones excesivamente largas

Si un token dura días o semanas, una filtración da al atacante toda esa ventana.

Prefiere access tokens de corta duración (minutos) y renuévalos mediante un mecanismo más seguro. Si necesitas “recordarme”, hazlo con refresh tokens y controles server-side.

2) Omitir comprobaciones de issuer y audience

Las firmas válidas no bastan. Verifica iss y aud, y valida claims temporales como exp y nbf.

3) Confiar en payloads decodificados

Decodificar no es verificar. Verifica siempre la firma en el servidor y aplica permisos en el servidor.

4) Confusión de algoritmos y claves

  • No aceptes cualquier algoritmo que declare un token. Ten una allowlist de algoritmos esperados.
  • No confundas claves simétricas (HS256) con claves asimétricas (RS256/ES256).
  • Minimiza el blast radius separando claves por entorno y rotándolas.

5) Filtración de tokens vía URLs, logs y referers

Evita poner JWTs en parámetros de consulta. Pueden acabar en el historial del navegador, logs del servidor, herramientas de analítica y cabeceras referer.

Usa Authorization: Bearer ... en su lugar.

6) Sin plan de rotación o revocación de claves

Asume que claves y tokens pueden filtrarse. Rota claves de firma, usa kid para soportar rotación suave y ten una estrategia de revocación (expiraciones cortas + capacidad para desactivar cuentas/sesiones). Para guías sobre almacenamiento, consulta /blog/where-to-store-jwts-safely.

Cuándo usar JWT (y cuándo no)

Añade autenticación JWT a móvil
Crea una app móvil en Flutter y conéctala a un backend protegido por JWT en un solo flujo.

Los JWT son útiles, pero no siempre son la mejor opción. La pregunta real es si te beneficia un token autocontenido que pueda verificarse sin consultar la base de datos en cada petición.

Casos adecuados para JWT

  • APIs sin estado a escala: verificación local (firma + expiración) sin consultas por petición
  • Múltiples servicios / microservicios: reglas de verificación compartidas y claves públicas
  • SPAs y apps móviles: clientes llamando APIs directamente
  • Access tokens de corta duración: daño reducido en caso de robo

Cuando JWT no es una buena opción

  • Se necesita revocación instantánea: las sesiones son más sencillas si necesitas “cerrar sesión en todas partes ahora” sin infraestructura adicional
  • Necesitas transportar datos sensibles: los JWT típicos están firmados, no cifrados
  • Tokens de larga duración: son de alto valor y merecen ser robados

Cuando las cookies de sesión simples son mejores

Para aplicaciones renderizadas en servidor donde la invalidación sencilla es importante, sesiones server-side con cookies HttpOnly suelen ser la opción más simple y segura.

Lista rápida para decidir

Elige JWT si necesitas verificación sin estado entre servicios y puedes mantener tokens de corta duración.

Evita JWT si necesitas revocación instantánea, piensas almacenar datos sensibles en el token, o puedes usar cookies de sesión sin fricciones.

Checklist práctico y FAQ

Checklist de verificación (qué comprobar siempre)

  1. Firma válida

Verifica usando la clave correcta y el algoritmo esperado. Rechaza firmas inválidas—sin excepciones.

  1. exp (expiración)

Asegúrate de que el token no haya expirado.

  1. nbf (not before)

Si está presente, comprueba que el token no se esté usando antes de tiempo.

  1. aud (audience)

Confirma que el token estaba destinado a tu API/servicio.

  1. iss (issuer)

Confirma que el token vino del emisor esperado.

  1. Comprobaciones de cordura (recomendadas)

Valida el formato del token, aplica un tamaño máximo y rechaza tipos de claim inesperados para reducir bugs en casos límite.

Elegir HS256 vs RS256/ES256

  • HS256 (clave simétrica): una secret compartida firma y verifica.

    • Bueno para: una única app/API controlada por un mismo equipo.
    • Ojo con: cualquier verificador que tenga la secret también puede crear tokens.
  • RS256 / ES256 (claves asimétricas): la clave privada firma; la pública verifica.

    • Bueno para: varios servicios que verifican tokens; distribuir claves públicas sin permitir firma.
    • Nota operativa: la rotación suele ser más segura porque solo el firmante posee la clave privada.

Regla práctica: si más de un sistema independiente necesita verificar tokens (o no confías completamente en cada verificador), prefiere RS256/ES256.

Monitorización y logs (sin filtrar tokens)

  • No registres tokens en bruto (cabeceras, cookies, query strings).
  • Si necesitas correlación, registra una huella del token (p. ej., un hash) o metadatos seguros (iss, aud y un ID de usuario solo si la política lo permite).
  • Vigila anomalías: fallos de firma, picos de tokens expirados, audiencias/emisores inusuales y patrones sospechosos de refresh.

Preguntas frecuentes (resumen)

¿Está cifrado un JWT?

No por defecto. La mayoría de los JWT son firmados, no cifrados, lo que significa que su contenido puede leerse si alguien tiene el token. Usa JWE o mantén datos sensibles fuera de los JWT.

¿Puedo revocar un JWT?

No fácilmente si dependes solo de access tokens autocontenidos. Enfoques comunes: tokens de corta vida, listas de denegación para eventos de alto riesgo, o refresh tokens con rotación.

¿Cuánto debería durar exp?

Lo más corto que permita tu UX y arquitectura. Muchas APIs usan minutos para access tokens, combinados con refresh tokens para sesiones más largas.

Construir apps protegidas con JWT más rápido con Koder.ai

Si implementas autenticación JWT en una API nueva o SPA, mucho del trabajo es repetitivo: configurar middleware, validar iss/aud/exp, establecer flags de cookie y evitar que el manejo de tokens aparezca en logs.

Con Koder.ai, puedes prototipar una app web (React), servicios backend (Go + PostgreSQL) o una app móvil Flutter mediante un flujo guiado por chat—iterar en un modo de planificación, usar snapshots y rollback mientras afinás la seguridad, y exportar el código cuando estés listo. Es una forma práctica de acelerar la construcción de flujos de autenticación basados en JWT manteniendo control sobre la lógica de verificación, estrategia de rotación de claves y ajustes de despliegue (incluidos dominios personalizados).

Preguntas frecuentes

¿Qué es un JWT y dónde se suele enviar?

Un JWT (JSON Web Token) es una cadena compacta y segura para URL que transporta claims (campos de datos) y puede ser verificada por un servidor. Se envía comúnmente en peticiones API mediante:

  • Authorization: Bearer <token>

La idea clave: el servidor puede validar la integridad del token (vía su firma) sin necesitar un registro de sesión por usuario en cada petición.

¿En qué se diferencia la autenticación con JWT de las sesiones en el servidor?

La autenticación por sesión normalmente guarda estado en el servidor (un registro de sesión indexado por una cookie/ID de sesión). Con autenticación basada en JWT, el cliente presenta un token firmado en cada petición y la API lo valida.

Los JWT son populares para APIs y arquitecturas con varios servicios porque la verificación puede hacerse localmente, reduciendo la necesidad de almacenamiento de sesión compartido.

“Sin estado” aún suele incluir comprobaciones en servidor como listas de revocación, verificación del estado del usuario o rotación de claves.

¿Cuáles son las tres partes de un JWT (cabecera, payload, firma)?

Un JWT son tres partes codificadas en Base64URL separadas por puntos:

  • header.payload.signature

La cabecera describe cómo se firmó, el payload contiene claims (como sub, exp, aud) y la firma permite al servidor detectar manipulaciones.

¿Un JWT está cifrado y se puede leer su contenido?

No. Los JWT estándar suelen estar firmados, no cifrados.

  • La firma prueba integridad (no fue modificado) y autenticidad (emitido por un firmante de confianza).
  • Cualquiera que obtenga el token puede decodificar Base64URL y leer cabecera y payload.

Si necesitas confidencialidad, considera JWE (tokens cifrados) o deja los datos sensibles en el servidor y solo almacena un identificador en el JWT.

¿Qué garantiza la firma del JWT y qué no garantiza?

La firma permite verificar que el token no fue alterado y que lo creó quien posee la clave de firma.

No garantiza:

  • ocultar el contenido del payload
  • que el usuario siga activo (a menos que lo compruebes)
  • revocación automática antes de exp

Trata el token como una credencial: si se filtra, a menudo puede reutilizarse hasta que expire.

¿Qué son `alg` y `kid` en la cabecera del JWT y por qué importan?

alg indica el algoritmo usado (p. ej., HS256 vs RS256). kid es un identificador de clave que ayuda a elegir la clave de verificación durante la rotación.

Reglas de seguridad:

  • Permite solo algoritmos esperados; no aceptes cualquier alg.
  • Nunca aceptes alg: "none".
  • No dejes que un kid no confiable produzca comportamientos de búsqueda de clave inseguros.
¿Qué claims debería incluir en el payload del JWT?

Empieza con los claims registrados estándar y mantén los personalizados al mínimo.

Claims registrados comunes:

  • iss (issuer) — quién creó el token
  • sub (subject) — a quién se refiere el token / id de usuario
  • aud (audience) — para quién está pensado el token
  • exp (expiration) — cuándo expira
  • iat (issued at) — cuándo se emitió
  • nbf (not before) — no aceptar antes de este tiempo

Evita poner secretos o datos personales sensibles en el payload, ya que son legibles si el token se expone.

¿Cómo se relacionan JWT, OAuth 2.0 y OpenID Connect (access tokens vs ID tokens)?

JWT es un formato de token; OAuth 2.0 y OpenID Connect son protocolos.

Mapeo típico:

  • Access token: se usa para llamar a una API (puede ser JWT u opaco).
  • ID token (OIDC): lo usa la app cliente para confirmar la identidad (normalmente un JWT).
  • Refresh token: para obtener nuevos access tokens (suele ser opaco; es muy sensible).

Importante: no uses un ID token para llamar a una API solo porque “parece” un JWT de acceso.

¿Dónde debo almacenar JWTs de forma segura en una aplicación de navegador?

Para apps web, las opciones comunes son:

  • En memoria: reduce el riesgo de “robarlo después”, pero sigue siendo vulnerable durante un XSS activo. Combínalo con tokens de corta vida y un flujo de refresh.
  • localStorage/sessionStorage: conveniente, pero cualquier XSS puede exfiltrar tokens.
  • Cookies HttpOnly Secure: a menudo lo más seguro porque JS no puede leerlas, aunque requieren protección contra CSRF (SameSite + tokens CSRF para peticiones que cambian estado).

Sea cual sea la opción, mantén los access tokens cortos y limita privilegios.

¿Qué comprobaciones debe realizar mi API al validar un JWT?

Como mínimo, valida:

  • firma (con la clave correcta y algoritmo permitido)
  • exp (no expirado)
  • iss (emisor esperado)
  • aud (destinado a tu API)
  • nbf (si está presente)

Añade defensas prácticas:

  • imponer tamaño máximo de token
  • rechazar tipos de claim inesperados
  • permitir pequeño desajuste de reloj para evitar problemas de sincronización

Related posts