2026-09-11 · 8 min read
- jwt
- oauth
- authorization
OAuth scope values are commonly represented as a space-delimited string, but deployed JWT profiles also use arrays or provider-specific claims such as scp. JWT itself does not give a generic scope claim one universal representation, so consumers must follow the issuer and token profile they trust.
Authorization begins only after cryptographic verification and validation of issuer, audience, time constraints, token type, and other profile requirements. Reading a scope-shaped claim from an unverified token is not an access decision.
Define claim syntax per trusted issuer
Document the accepted claim name and JSON type for each token profile. For a string form, define the delimiter and reject control characters or unexpected whitespace. For an array form, require strings and set limits on count and length.
- Reject null, objects, numbers, and mixed arrays.
- Decide whether an empty claim differs from a missing claim.
- Specify case sensitivity and a bounded permission vocabulary.
- Reject ambiguous duplicate claims during strict JSON processing.
Match complete permissions
Convert a valid claim into a set of complete scope values, then compare the required value for exact equality. Substring checks make orders:read match orders:read-all or permit read when the token contains bread, while prefix rules can accidentally grant future permissions.
If hierarchical or wildcard permissions are required, define and implement that grammar explicitly. Keep scope, role, group, tenant, and resource-ownership checks separate so a convenient string conversion cannot blur their security meaning.
Align every enforcement point
Gateways, service meshes, APIs, and background consumers should use the same versioned token profile and permission mapping. When an edge component forwards identity context, it must remove client-supplied copies, protect the internal channel, and state whether downstream services must also validate the original token.
- Use 401 for absent or unacceptable authentication according to the API scheme.
- Use 403 when an authenticated principal lacks required authorization.
- Avoid returning token contents in errors or logs.
- Audit the policy version and required permission, not the bearer token.
Maintain an adversarial claim matrix
Use Flashman's JWT decoder only with synthetic tokens, JSON formatter to inspect claim types, diff for policy revisions, case converter for naming fixtures, and URL tool for URI-shaped resource identifiers. Decoding does not verify a signature or issuer.
Test string and array profiles, missing and empty values, duplicate permissions, tabs and Unicode whitespace, case changes, prefix collisions, wildcard attempts, unknown claims, multiple issuers, token exchange, stale gateway headers, wrong audiences, expiry boundaries, and policy rollouts across mixed service versions.