Un JWT firmado es header.payload.signature, con cada parte en base64url sin relleno: el encabezado indica el algoritmo (alg), la clave (kid) y el tipo (typ), y la carga útil contiene claims como iss, sub, aud, exp, nbf, iat y jti (RFC 7519 §4.1), además de los claims de la aplicación. Los JWT cifrados tienen cinco partes. Cualquiera que tenga el token puede leer la carga útil de un JWT firmado: la firma protege la integridad, no la confidencialidad.
La verificación tiene dos mitades. Primero, la firma, con un algoritmo y una clave que el verificador eligió de antemano; después, los claims: emisor, audiencia, caducidad con un pequeño margen para el desfase del reloj y tipo de token, para que no se acepte un token de ID donde se espera un token de acceso. El RFC 8725 (JWT Best Current Practices) recoge estas reglas; la mayoría de las vulnerabilidades de JWT se deben a omitir alguna de ellas.
La elección del algoritmo es un compromiso que se analiza en ES256 frente a RS256 y HS256 frente a RS256. El depurador de JWT decodifica y verifica tokens localmente.