Un token puede declarar "role": "admin", incluir una fecha de expiración futura y mostrarse como un JSON perfectamente ordenado. Nada de eso demuestra quién lo emitió. La diferencia entre leer un dato y confiar en él es el punto de partida de este artículo.
Vamos a desmontar un JWT en el navegador y observar qué cambia al modificar sus claims. El playground utiliza datos ficticios, no solicita claves y no verifica firmas. Para implementar un verificador de servidor con jose, JWKS y políticas explícitas, continúa después con JWT: decodificar no es validar. Aquí nos centraremos en entender la representación.
JWT, JWS y JWE: qué estamos mirando
JWT, JSON Web Token, representa afirmaciones o claims que se intercambian entre partes. Puede transportar información de identidad o autorización dentro de un protocolo, pero el formato por sí solo no implementa un inicio de sesión. RFC 7519, sección 1.
JWS, JSON Web Signature, protege contenido mediante una firma digital o un código de autenticación de mensajes, MAC. En un JWT compacto JWS, header y payload son legibles: la protección no los cifra. Con HMAC, quien conoce el secreto compartido puede producir el MAC; en una firma asimétrica intervienen claves privada y pública. RFC 7515, secciones 1 y 3.
JWE, JSON Web Encryption, representa contenido cifrado. Su forma compacta tiene cinco segmentos: header protegido, clave cifrada, IV, ciphertext y tag de autenticación; dependiendo del algoritmo, alguno puede estar vacío. Decodificar sus segmentos no revela automáticamente los claims. Un JWT también puede combinar firma y cifrado mediante anidamiento. Este playground reconoce la cantidad de segmentos como una pista, pero no procesa ni descifra JWE. RFC 7516, sección 3.1.
Si esos términos aún se mezclan, conviene repasar hashing, cifrado y codificación. Hacer legible una representación no equivale a descifrarla.
Tres segmentos, dos puntos
La serialización compacta que exploraremos tiene esta forma:
BASE64URL(header) . BASE64URL(payload) . BASE64URL(signature)Los espacios solo ayudan a leer el esquema; no pertenecen al token.
| Segmento | Qué contiene | Qué no demuestra al leerlo |
|---|---|---|
| Header | Parámetros como alg, typ o kid | Que el algoritmo o la clave sean aceptables |
| Payload | Objeto JSON con claims | Que sus afirmaciones sean verdaderas |
| Signature | Bytes de una firma o MAC | Que la protección se haya verificado |
Para este formato, la entrada que se firma es el header codificado, un punto y el payload codificado. La firma no es un tercer JSON ni una copia cifrada del mensaje. Tampoco se debe volver a serializar el JSON para verificar: importan los segmentos recibidos. RFC 7515, sección 3.1.
Base64URL permite leer; no aporta secreto
Base64URL representa bytes con un alfabeto apropiado para URL. Utiliza - y _ donde Base64 convencional usa + y /; en JOSE se omite el relleno final =. No exige una contraseña para recuperar los bytes. RFC 4648, sección 5, RFC 7515, sección 2.
Nuestro lector comprueba caracteres y longitudes, recupera bytes y aplica UTF-8 al header y al payload. No interpreta la firma como texto. Un carácter como í puede ocupar varios bytes: tratar la salida de atob() directamente como texto Unicode produce errores. TextDecoder resuelve esa conversión y permite rechazar secuencias UTF-8 incorrectas. MDN: TextDecoder.
Playground: examina un token sin confiar en él
Usa exclusivamente tokens ficticios. Un token Bearer real puede dar acceso a quien lo posea; su exposición importa aunque no conozca una clave. No lo pegues en capturas, incidencias ni conversaciones. RFC 6750, introducción y sección 5.
Decodificar un JWT no verifica su firma ni garantiza su autenticidad.
La herramienta necesita JavaScript. El artículo sigue disponible sin él. No introduzcas tokens reales ni credenciales.
Los ejemplos declaran HS256, pero sus 32 bytes finales son relleno, no un HMAC calculado. Los dominios .example, sujetos y roles son ficticios. Las fechas se generan al elegir cada ejemplo para que puedas comparar un exp futuro con uno pasado sin depender del día de publicación.
La herramienta procesa la entrada en memoria del navegador, sin enviarla a un endpoint, guardarla en almacenamiento web ni incluirla en la URL. «Limpiar» retira entrada y resultados; también se limpian al abandonar la página. Copiar es una acción explícita: el JSON pasa al portapapeles y la herramienta no lo borra desde allí. Estas medidas no protegen frente a extensiones maliciosas o un dispositivo comprometido.
Text Forge ya tiene JWT Studio. Reutilizamos su lógica básica de lectura con adaptaciones para esta demostración. El playground tiene un alcance distinto: seguir la explicación, identificar las partes y comparar lo que podemos observar con lo que todavía no sabemos.
Tres recorridos para probarlo
- Elige «exp futuro». Localiza
algen el header ysuben el payload. Observa que la herramienta describe el tiempo, pero sigue mostrando «firma sin verificar». - Elige «Claim alterado». El rol cambia de
lectoraadminy se mantiene la firma de relleno. La lectura sigue funcionando. Esto demuestra la facilidad de representar una afirmación, no que se haya roto una firma real ni que exista un bypass en una aplicación. - Compara «exp pasado», «Sin exp» y «Malformado». Son situaciones distintas: una fecha declarada ya transcurrió, no hay claim de expiración o ni siquiera se puede interpretar el formato esperado. Ninguna salida positiva del lector autoriza una petición.
Puedes editar el texto directamente. Una entrada de cinco segmentos recibe un aviso sobre posible JWE; contar puntos no permite concluir que sea un JWE válido.
Qué significan los claims
Los nombres registrados proporcionan un vocabulario común; el perfil de cada aplicación decide cuáles exige. RFC 7519, sección 4.1.
| Claim | Lectura |
|---|---|
iss | Emisor declarado |
sub | Sujeto al que se refieren las afirmaciones; interprétalo en el contexto del emisor |
aud | Destinatario o destinatarios previstos; puede ser una cadena o un array de cadenas |
exp | Instante de expiración; llegado ese momento no debe aceptarse, salvo la tolerancia de reloj prevista |
iat | Instante de emisión declarado |
nbf | Instante antes del cual no debe aceptarse |
exp, iat y nbf usan NumericDate: segundos desde la época Unix, no milisegundos. Se permiten valores no enteros. iat no define por sí mismo una expiración. El RFC no obliga a usar todos estos claims en cualquier JWT. RFC 7519, secciones 2 y 4.1.
El playground expresa las fechas en UTC y las compara con el reloj de tu dispositivo en el instante indicado. No aplica tolerancia ni mantiene un contador en segundo plano. Pulsa «Decodificar / actualizar lectura» para recalcular. Si exp está ausente o no es numérico, no fabrica una fecha ni lo convierte automáticamente desde una cadena.
Leer una fecha es una operación mucho más pequeña que validar
Este fragmento TypeScript demuestra únicamente la conversión de un valor de prueba. No recibe ni verifica un token:
function fechaDeclaradaUtc(segundos: unknown): string {
if (typeof segundos !== 'number' || !Number.isFinite(segundos)) {
throw new Error('Se esperaba un número de segundos');
}
const milisegundos = segundos * 1000;
if (Math.abs(milisegundos) > 8.64e15) {
throw new Error('Fecha fuera del rango representable por Date');
}
return new Date(milisegundos).toISOString();
}
console.log(fechaDeclaradaUtc(0));
// 1970-01-01T00:00:00.000ZEl cero pertenece a una prueba ficticia y reproducible. Que la conversión funcione solo demuestra que podemos representar ese valor como fecha. Tampoco garantiza que el reloj local sea correcto. MDN: Date.
Qué debe comprobar el sistema que acepta un JWT
La política viene de configuración confiable, no de lo que el token solicite. RFC 8725 establece las prácticas de seguridad aplicables, entre ellas restringir algoritmos, vincular claves al emisor y validar destinatarios. RFC 8725, secciones 3.1, 3.8 y 3.9.
Para una API que espera tokens firmados:
- Firma y algoritmo: usa una biblioteca mantenida, una lista permitida y claves de confianza. Leer
algno concede permiso para usarlo.alg=noneindica ausencia de firma o MAC; no sirve como prueba criptográfica de identidad. - Issuer y audience: comprueba el emisor esperado y que el token esté destinado a esta API. No obtengas claves desde una URL arbitraria indicada por claims sin verificar.
- Contrato de claims: exige los campos que necesites, comprueba sus tipos y aplica expiración,
nbfy la política temporal acordada. Una firma correcta no sustituye estas restricciones. - Contexto de uso: distingue tipos de token y evita aceptar uno emitido para otra finalidad. Los permisos sobre un recurso requieren además una decisión de autorización.
Son controles distintos de este lector. El laboratorio de verificación con jose los implementa de manera explícita. Para entender por qué verificar identidad tampoco resuelve todos los permisos, sigue con RBAC, ABAC y autorización por objeto.
Los límites deliberados de la herramienta
Este componente es un inspector educativo, no una biblioteca de seguridad:
- Limita la entrada a 16 384 caracteres antes de procesarla. Rechaza segmentos malformados, JSON que no sea un objeto, UTF-8 incorrecto y números no finitos.
- No soporta payloads separados ni la extensión
b64=false. Esta última no debe utilizarse en JWT, según RFC 7797, sección 7. - No decide si un algoritmo, una longitud de firma, un
kido una extensióncritson aceptables. No solicita claves públicas, privadas ni secretos. - Usa
JSON.parse: si se repite una propiedad, se conserva la última; no es un detector exhaustivo de ambigüedades. El JSON formateado sirve para leer, no para reconstruir los bytes firmados. - Inserta resultados con
textContent, no como HTML. Un claim que contenga etiquetas se muestra como texto, sin ejecutarlo. MDN: textContent.
La separación de responsabilidades también evita cargar un estudio criptográfico completo dentro del artículo: el contenido es estático y la lógica interactiva se carga al acercarse al playground.
De una afirmación legible a una decisión confiable
Prueba a cambiar un claim y observa qué partes siguen siendo legibles. Después identifica lo que falta para aceptar ese token: una clave confiable, una operación criptográfica correcta y que se cumplan las reglas de uso de tu aplicación.
La pregunta útil no es solo «¿puedo leer este JSON?», sino «¿qué evidencia permite a mi aplicación confiar en estas afirmaciones para esta operación?». El playground responde a la primera; tu sistema debe resolver la segunda antes de actuar.
Referencias
- RFC 7519: JSON Web Token, estructura y claims.
- RFC 8725: prácticas de seguridad para JWT.
- RFC 7515: JWS y serialización compacta.
- RFC 7516: JWE y serialización compacta.
- RFC 4648: Base64URL.
- RFC 7797: restricciones de payload no codificado.
- RFC 6750: protección de tokens Bearer.
Comienza con un token ficticio precargado y una firma de relleno. Puedes editarlo o elegir otro ejemplo. La herramienta no envía ni guarda tus entradas. La copia es voluntaria y deja el resultado en el portapapeles de tu dispositivo.
Elige un ejemplo para comenzar.
Tres segmentos separados por puntos. Los colores identifican partes, no niveles de confianza.
Lectura puntual, sin tolerancia de reloj. Actualiza para recalcular. Estas fechas son claims no verificados: no prueban validez, identidad ni permisos.
