Qué es un JWT y cómo funciona la autenticación con tokens

Si alguna vez inspeccionaste las cookies o el localStorage de una web después de iniciar sesión, es probable que hayas visto una cadena larga de caracteres separada por puntos, algo como eyJhbGci...eyJzdWIi...SflKxwRJ. Eso es un JWT (JSON Web Token), el mecanismo que hoy usan la mayoría de las APIs y aplicaciones web modernas para saber quién sos sin tener que preguntarle a una base de datos en cada petición.

Qué es un JWT

JWT son las siglas de JSON Web Token, un estándar abierto definido en el RFC 7519 para transmitir información de forma compacta y autocontenida entre dos partes, típicamente un cliente y un servidor. "Autocontenida" es la palabra clave: toda la información necesaria para identificar al usuario y validar el token viaja dentro del propio token, en formato JSON. El servidor no necesita guardar ese token en ningún sitio para poder verificarlo después, lo cual es la diferencia central frente a los sistemas de sesión tradicionales.

La estructura de un JWT: header, payload y signature

Un JWT siempre tiene la misma forma: tres bloques de texto separados por puntos.

header.payload.signature

Cada uno de esos tres bloques está codificado en Base64URL (una variante de Base64 segura para usar en URLs), no cifrado. Esto es importante y lo desarrollamos más abajo. Podés ver esta estructura con un token propio decodificándolo con el decodificador de JWT, que separa automáticamente los tres bloques y te muestra el header y el payload como JSON legible.

1. Header

El header describe metadatos del propio token: normalmente el algoritmo de firma usado (por ejemplo HS256 o RS256) y el tipo de token (JWT). Es un objeto JSON pequeño, algo así:

{ "alg": "HS256", "typ": "JWT" }

2. Payload

El payload contiene los claims: la información real que el token transporta, como el identificador del usuario (sub), la fecha de expiración (exp), quién emitió el token (iss) o cualquier dato personalizado que la aplicación necesite (roles, permisos, etc.). Hay claims "registrados" por el estándar (como exp, iat, sub) y claims propios que cada aplicación puede agregar libremente.

3. Signature

La signature es el resultado de aplicar el algoritmo indicado en el header sobre el header y el payload combinados, usando un secreto (en algoritmos simétricos como HS256) o una clave privada (en algoritmos asimétricos como RS256). Su función no es ocultar información, sino garantizar integridad: si alguien modifica un solo carácter del header o del payload después de emitido el token, la firma deja de coincidir y el servidor lo rechaza al verificarlo.

Cómo funciona la autenticación con tokens

El flujo típico es así:

  1. El usuario inicia sesión con su usuario y contraseña.
  2. El servidor valida las credenciales y, si son correctas, genera un JWT firmado con la identidad del usuario y lo devuelve al cliente.
  3. El cliente guarda ese token (en memoria, localStorage o una cookie) y lo envía en cada petición posterior, normalmente en la cabecera Authorization: Bearer <token>.
  4. El servidor, al recibir cada petición, verifica la firma del token con su secreto o clave pública. Si la firma es válida y el token no expiró, confía en los datos del payload sin necesidad de consultar una base de datos de sesiones.

Esa es la diferencia de fondo frente a la autenticación por sesiones tradicionales: una sesión clásica obliga al servidor a guardar un identificador de sesión en memoria o en una base de datos y consultarlo en cada petición (autenticación stateful); un JWT es stateless porque toda la verificación depende únicamente de la firma criptográfica, no de una consulta externa. Eso facilita escalar horizontalmente (cualquier servidor con el secreto puede verificar el token, no hace falta compartir un almacén de sesiones), aunque también trae una contrapartida: revocar un JWT antes de su expiración natural no es tan directo como borrar una fila de una tabla de sesiones.

Un JWT no es lo mismo que un dato cifrado

Este es el malentendido más común y también el más importante de aclarar: el header y el payload de un JWT no están cifrados, están codificados en Base64URL. Codificar no es lo mismo que cifrar: cualquiera que tenga el token puede decodificar el header y el payload y leer su contenido en texto plano, sin necesitar ninguna clave. Podés comprobarlo pegando cualquier JWT en el decodificador de JWT: vas a ver el JSON completo sin necesitar el secret usado para firmarlo.

Lo único que la firma protege es que el contenido no haya sido alterado, no que sea secreto. Por eso una buena práctica de seguridad es no incluir en el payload información sensible (contraseñas, datos personales críticos, secretos de negocio): cualquiera que intercepte el token puede leerla. Si necesitás confidencialidad además de integridad, el estándar contempla una variante llamada JWE (JSON Web Encryption), que sí cifra el contenido, pero es mucho menos común que el JWS estándar (el JWT "normal" firmado que describimos arriba).

Cómo depurar un JWT sin exponer tokens sensibles

Cuando algo falla en un flujo de autenticación —un token que no se acepta, un claim que no llega como se esperaba—, la forma más rápida de diagnosticarlo es decodificar el token y mirar su contenido directamente. Para eso conviene usar una herramienta que procese el token completamente en tu navegador, sin enviarlo a ningún servidor externo, algo especialmente relevante si el token que estás depurando es de un entorno de producción real. El decodificador de JWT de Herramientastic hace exactamente eso: decodifica el header y el payload en tu propio navegador, sin transmitir el token a ningún servidor, y sin validar ni necesitar el secret de firma (porque no lo verifica, solo lo muestra de forma legible).

Podés explorar el resto de utilidades para desarrolladores en la categoría de texto de Herramientastic.