Start with the word “decode”

A compact JSON Web Token is a string representation of a token. The JWT specification defines signed and encrypted token forms, and JWT Best Current Practices discusses secure validation choices. For a signed JWT in compact serialization, the familiar form has a protected header, a payload, and a signature separated by periods. The first two parts are encoded so they can be carried in a URL-safe compact form; decoding them makes the header and claims readable. That operation does not establish that the sender created the token, that the contents were left unchanged, or that the current application should accept it.

This distinction is easy to miss because decoded output looks authoritative. A payload might show a user identifier, role, expiration time, or audience. Those are statements inside the token. A recipient must still apply the token's validation rules before relying on them. The JWT specification defines the format and registered claims, while the best-current-practice guidance discusses secure validation choices. The exact checks depend on the system that issued the token and the service receiving it.

Separate syntax from cryptographic verification

Decoding asks whether the visible segments can be interpreted as the expected JSON structures. A verifier asks whether the protected signing input and signature match an allowed cryptographic algorithm and trusted key. The two tasks answer different questions. If someone changes a claim and re-encodes the payload, the result can remain readable while no longer matching the original signature.

Algorithm selection is a critical part of verification. The receiving application should use an explicit policy for accepted algorithms and keys rather than trusting a token's unverified header to choose arbitrary behavior. It should also establish which issuer and audience it expects. A valid signature from the wrong issuer, or a token intended for a different service, is not automatically acceptable. Authorization is a further decision: even a valid token can lack the permission required for a particular operation.

Some compact tokens use JSON Web Encryption rather than a three-part signed form; encrypted compact serialization has a different number of segments. A decoder that only handles signed three-part JWTs should say so. An unsecured JWT using the “none” algorithm has an empty signature segment in its compact representation. That shape is a format case, not evidence that a recipient should trust the token. An application should reject unsecured tokens unless its explicit protocol design allows them and all relevant controls are understood.

Read time claims carefully

The registered claims include exp, nbf, and iat. Their values use NumericDate, a number of seconds from the Unix epoch, as defined in RFC 7519. The exp claim identifies a time on or after which a token must not be accepted; nbf identifies a time before which it must not be accepted. The iat claim records when the token was issued. These claims are not all mandatory in every JWT, and a recipient still needs a policy for clock tolerance and required claims.

A local clock comparison is only a reading aid. It cannot prove that a verifier uses the same clock, that its allowed skew is appropriate, or that the claim came from a trusted issuer. It also does not validate the signature or establish whether the token has been revoked. If a displayed time looks wrong, verify the unit and the source value before changing a server's clock or extending an expiry window.

Use a redacted, non-production example

Never paste a live bearer token into a website or ticket simply because a page calls itself an inspector. A bearer token may grant access to whatever its issuer authorized. Use a synthetic token with invented claims, or a redacted sample that preserves the JSON types and segment structure. If you must investigate a real token, use an approved local environment and follow the organization's secret-handling process.

Benchlight's JWT Inspector decodes the header and payload locally, displays supported time claims, and labels verification as not performed. It does not send the input to an identity provider, check a key set, or decide whether a claim is acceptable. For its three-part input, the signature segment may be empty to represent the compact unsecured format; that allowance does not make the token trusted.

Turn a token question into a verification test

When an application rejects a token, gather the exact failure reason from the verifier without copying the raw token into logs. Record the configured issuer, audience, accepted algorithms, key source, required claims, and time policy in a controlled test. Then create cases for a valid token, a changed payload, the wrong audience, an expired token, a token that is not active yet, and an unsupported algorithm. Use keys and claims made for the test environment.

A successful decoding step can help identify a malformed segment or unexpected claim type. It should not become the test's final assertion. The meaningful assertion is the receiver's behavior under its configured validation and authorization rules. Keep those tests close to the code that makes the trust decision, and avoid storing reusable production tokens in fixtures.

Calculate the time window before considering trust

Consider this deliberately fictional claims object. It is teaching data, not an issued credential:

{"sub":"demo-user","nbf":1000,"exp":1060,"iat":990}

Use a hypothetical current time of 999 seconds after the epoch. The not-before condition is not met. At time 1000, that condition is met; at time 1059, expiration has not yet been reached. At time 1060, the expiration condition fails, because acceptance requires the current time to be before exp. This example assumes zero clock tolerance so the exact boundary is visible. A verifier may implement a documented small tolerance; a decoder cannot choose the application's policy.

NumericDate uses seconds rather than milliseconds, and the specification permits non-integer values. JavaScript Date accepts milliseconds, so converting a claim for display multiplies its numeric value by 1000. Confusing the two units can produce an implausible date without producing an invalid JSON payload. A string such as "1060" is also different from the numeric value 1060. The inspector only lists finite numeric time claims; a missing entry in that display should prompt inspection of the original payload, not an assumption that verification passed.

Benchlight compares displayed claims with the computer's current clock, rounded down to whole seconds. It does not offer the hypothetical clock used above. These old sample dates would therefore appear expired on a modern machine, and its display is not a sub-second verifier. Record the actual clock and tolerance when investigating a boundary case in a real verifier.

Finally, change sub in this fictional object while leaving the time claims unchanged. The same time arithmetic still holds, but it says nothing about whether the claimed identity is authentic. Signature or decryption validation, issuer and audience checks, and the resource's authorization rules remain separate requirements. Time-window arithmetic can explain a rejection; it cannot establish permission to access a resource.