Guías JWT

Claims JWT explicados: cómo leo iss, aud, exp y sub

Explicación práctica de los claims JWT más comunes y de cómo separo su lectura de la verificación de firma y de las reglas de aceptación de la aplicación.

Por JWTDecoder.toolsÚltima verificación 2026-09-13

Voz editorial: la primera persona describe el flujo de trabajo documentado de JWTDecoder.tools; JWTDecoder.tools es el editor y autor organizacional.

iss · sub · aud · exp · nbf · iat · jti claim map
iss · sub · aud · exp · nbf · iat · jti

Cuando decodifico un JWT no leo los claims al azar. Uso una secuencia repetible para responder rápido cuatro preguntas: quién lo emitió, para quién es, si está dentro de su ventana temporal y qué datos de autorización entiende la aplicación.

Normalmente empiezo con JWT Decoder y voy de registered claims a claims específicos del protocolo o del producto.

El orden que uso al inspeccionar un payload

Para algo como:

{
  "iss": "https://auth.example.com/",
  "sub": "user_123",
  "aud": "api://orders",
  "scope": "orders:read orders:write",
  "iat": 1789200000,
  "exp": 1789203600
}

mi orden suele ser:

  1. iss — quién dice haber emitido el token.
  2. aud — para qué API o recipient fue emitido.
  3. exp y nbf — si está temporalmente activo.
  4. iat — cuándo dice haber sido emitido.
  5. sub — qué sujeto representa.
  6. scope, roles, groups — datos de autorización.
  7. jti, azp, auth_time, acr, amr — contexto adicional si el protocolo lo define.

Este orden me ayuda a separar authentication de authorization.

iss: issuer

{ "iss": "https://login.example.com/" }

Comparo este valor con el issuer configurado por la API. No confío en él porque “parece correcto”.

RFC 8725 añade una condición importante: las keys usadas para verificar deben pertenecer al issuer que la aplicación confía.

Si hay mismatch uso JWT Debugger y la guía de issuer validation para comparar valor, trusted metadata y key source.

aud: audience

Puede ser string:

{ "aud": "api://orders" }

o array:

{ "aud": ["api://orders", "api://reporting"] }

Si Orders espera api://orders y recibe api://billing, tengo una explicación fuerte para 401 incluso con firma válida.

La guía de audience mismatch cubre environment y token-type mistakes.

exp: expiration

exp usa NumericDate en segundos. Para verlo como fecha uso JWT Expiry Checker.

Un exp en el futuro no demuestra que el token sea válido; solo indica que una condición temporal no ha fallado.

La guía del claim exp entra en unidades y clock skew.

nbf: not before

Si nbf está en el futuro, el token puede estar sin expirar y aun así no ser aceptable todavía.

Cerca del límite comparo clocks de issuer y verifier.

iat: issued at

Uso iat como contexto para preguntas como:

  • ¿pertenece al login que estoy investigando?
  • ¿es demasiado antiguo?
  • ¿el lifetime iat→exp tiene sentido?
  • ¿está sorprendentemente en el futuro?

No convierto iat en una regla universal de expiración sin policy explícita.

sub: subject

sub puede representar usuario, servicio u otro principal. No asumo semántica sin mirar el issuer.

También evito tratar sub de issuers diferentes como un identificador global único; muchas veces la pareja iss + sub es el contexto correcto.

jti: JWT ID

Puede identificar un token concreto, pero su mera presencia no crea replay protection ni revocation. Eso requiere policy y, a menudo, state server-side.

scope, roles y groups

{
  "scope": "profile orders:read",
  "roles": ["support", "billing"],
  "groups": ["employees"]
}

Son muy útiles para debugging, pero no tienen semántica universal. Cada provider define cómo expresa permissions.

Si authentication pasa pero llega 403, estos son los campos que reviso después.

Claims extra en OAuth/OIDC

Según provider y token type puedo revisar:

  • azp — authorized party;
  • auth_time — momento de authentication;
  • acr — authentication context class;
  • amr — métodos de authentication.

Solo los uso para decisiones cuando la documentación del protocolo/provider les da significado concreto.

Mi regla antes de confiar en cualquier claim

  1. Decode: leo qué dice.
  2. Verify: compruebo firma con trusted key.
  3. Validate: comparo issuer, audience, tiempo y permisos con policy.

No salto de step 1 a “usuario autenticado”.

Mi checklist de claims

  1. Decodifico JWT sin confiar todavía.
  2. Comparo iss con configured issuer.
  3. Comparo aud con current API.
  4. Leo exp, nbf, iat como una timeline.
  5. Interpreto sub dentro del issuer.
  6. Reviso scope/roles/groups tras resolver authentication.
  7. Verifico firma con key source vinculado al issuer.
  8. Comparo claims específicos con documentación del provider.

Así evito perderme en payloads grandes: primero busco trust, recipient, time y authorization.

Fuentes y referencias

Guías relacionadas