To decode a compact JWT, split the string on the '.' character, Base64url-decode the first two segments with java.util.Base64, and parse each segment as UTF-8 JSON. The third segment is a signature that cannot be safely inspected without a key, so decoding alone never proves a token is authentic. For a one-off inspection without adding jjwt, java-jwt, or Nimbus JOSE+JWT to your project, the JWT Decoder performs the same splitting and decoding locally in your browser. Java developers commonly paste a token into it during an OAuth callback debug, a test fixture review, or a cross-service sanity check. The tool renders the header, the payload, and the RFC 7519 registered claims it recognizes, so you can confirm what a token claims before wiring it into a Spring Security filter or a custom authentication filter. Decoding answers "what does this token say"; verification answers "should I trust what it says". Keeping that line clear is what turns a useful debug aid into a safe workflow.

how to decode jwt token in java
How to Decode a JWT Token in Java: Inspect Claims Locally

Anatomy of a Compact JWT: Header, Payload, Signature

RFC 7519 describes a compact JSON Web Token as three Base64url-encoded segments joined by single dots: header.payload.signature. Each segment uses the URL-safe alphabet defined in RFC 4648: the 26 uppercase letters, the 26 lowercase letters, the digits 0 through 9, hyphen, and underscore. Padding characters are deliberately omitted because the segment length is fixed by the encoded byte count, so a padded token is structurally invalid and a strict decoder will reject it instead of silently accepting a different format.

The header carries metadata about the token: the signing or encryption algorithm (the alg field), the optional media type (usually typ: JWT), and any other parameters the issuer chose. The payload carries the claims, including registered names from RFC 7519, public names registered elsewhere, and private names your application defined. The third segment is the signature, or an empty string for an unsecured token. A decode-only tool checks the third segment only for compact Base64url shape; its bytes are never interpreted as a verified signature.

Java's java.util.Base64 class exposes a URL-safe decoder through Base64.getUrlDecoder(). Because compact JWTs strip the trailing = characters, you usually pair it with a small padding helper, or call Base64.getMimeDecoder() with a clean segment length. Once decoded, the bytes should be interpreted as UTF-8 JSON. That is the full decode pipeline; everything else around it is verification.

Two Ways Java Developers Decode a JWT

Most Java projects reach for a third-party library rather than hand-rolling the decode. The three common choices are:

  • jjwt (io.jsonwebtoken): a fluent builder API, Spring-friendly, supports JWS and JWE.
  • java-jwt (com.auth0): a small surface area, good for token issuance and parsing.
  • Nimbus JOSE+JWT: the reference-quality library used by Spring Security OAuth.

Each library exposes parseSignedClaims(...) or decode(...) helpers that internally split, Base64url-decode, parse JSON, and, when given a key, verify the signature. The decode step is the cheap, side-effect-free part. The expensive and security-relevant part is verification, which requires a key and a policy.

For one-off inspections, debugging an OAuth callback, reading a test fixture, or comparing what two services see, pulling in a dependency is overkill. That is the gap a local browser decoder fills: it shows the header and payload of a compact token without changing your build, opening your IDE, or sending the token to a remote service.

Decode a JWT Token Locally in Your Browser

The JWT Decoder is a deliberately narrow tool that performs the same splitting and Base64url work that java.util.Base64 does, but in your browser tab. Follow these steps:

  1. Copy a compact token in the standard header.payload.signature form. Make sure no extra whitespace, line breaks, or surrounding quotes come along.
  2. Paste it into the input field on the JWT Decoder page.
  3. Select Decode JWT. The page splits the string on the two dots, validates that each segment is unpadded Base64url, decodes the header and payload as UTF-8, and parses them as JSON.
  4. Read the rendered header object, the payload object, and any RFC 7519 registered claims the page recognizes.
  5. Treat the result as unverified information. The page labels every successful decode as unverified so that a convenient inspection step is not mistaken for a security check.
  6. When you finish, clear the input field and the clipboard. Tokens can carry personal identifiers, tenant data, or scopes you do not want lingering.

For a broader browser workflow without writing code at all, see Decode JWT Tokens Without Code in Your Browser.

What the Decoded Header and Payload Contain

The header is almost always a small JSON object with two familiar fields: alg (the algorithm the issuer used, such as HS256, RS256, or ES256) and typ (usually JWT). The payload is where the application logic lives, and it can mix registered claims, public claims, and private claims in the same flat object.

The following table summarizes the registered claims RFC 7519 defines. The decoder shows each one when present, but it never enforces any of them.

ClaimFull NameMeaning
issIssuerPrincipal that issued the JWT.
subSubjectPrincipal that is the subject of the JWT.
audAudienceRecipients the JWT is intended for.
expExpiration TimeTime after which the JWT must not be accepted.
nbfNot BeforeTime before which the JWT must not be accepted.
iatIssued AtTime at which the JWT was issued.
jtiJWT IDUnique identifier that can be used to prevent replay.

For exp, nbf, and iat, the tool shows the raw NumericDate value alongside an ISO timestamp. NumericDate is a Unix-seconds convention, not a guarantee that the token is currently acceptable, since clock skew, audience, and the issuer's policy all matter. The aud claim can be a single string or an array; the decoder renders the JSON value without deciding whether it matches your application. Custom claims remain visible in the raw payload because JWT allows private claim names, but the page assigns them no special meaning.

What the Browser Decoder Does Not Do

The page is a decode-only tool. It does not accept a secret or public key, validate a JWS signature, check an issuer, check an audience, apply clock skew, decrypt a JWE, or make an authorization decision. It does not upload the token, send it to an API, fetch a signing key, store a copy, or create an account. Decoding happens entirely in the browser.

A readable payload can still be forged, expired, meant for a different audience, or signed with a key you do not trust. If you need to validate a token, use a maintained JWT library in the service that owns the security decision and verify the algorithm, key, issuer, audience, expiry, and any application-specific requirements there. The decoder cannot reveal content in an encrypted JWE, repair a broken token, discover a signing key, or tell you whether a signature is correct.

What Java Must Still Verify Before Trusting a Token

Decoding and verifying are two different operations in any JWT library. After a successful decode, the Java side still needs to confirm:

  • The alg in the header is one your application accepts. Rejecting none and rejecting algorithm confusion (an RS256 token verified with an HMAC key) is non-negotiable.
  • The signature matches the header and payload using the expected key. The key itself must come from a trusted key store or JWKS endpoint, not from the token.
  • The iss claim matches an expected issuer identifier.
  • The aud claim includes your application's identifier when aud is required.
  • The current time is after nbf and before exp, with whatever clock skew your security policy allows.
  • Any jti value has not been seen recently if your service tracks replay.

These checks live in your authentication filter, your resource server configuration, or the Spring Security OAuth2ResourceServer setup that owns the trust decision. The browser decoder is a side channel for reading what a token claims. The Java verification path is the one that decides whether the token is acceptable.

A Safe Workflow When Inspecting Tokens as a Java Developer

JWTs frequently carry personal identifiers, tenant data, scopes, and other application-specific values even when they are not passwords. Treat them with the same caution you would give to a session cookie or an API key:

  • Obtain the token only through an environment where you are authorized to inspect it. Test fixtures and local mocks are fine; production bearer tokens captured by accident are not.
  • Paste the token into a local page rather than a public online decoder. The JWT Decoder runs in your browser and never sends the token anywhere.
  • Review the alg field and the registered claims, then clear the input field and the clipboard when you finish.
  • Avoid pasting production credentials into shared screens, issue trackers, chat messages, screenshots, or third-party online decoders.
  • If you need to convert a Unix timestamp independently, the Unix Timestamp Converter renders a NumericDate in UTC, local time, and ISO 8601 without uploading the value.

The decode step is a routine development task. Keeping the decode path private and the verify path inside your Java service is what turns a useful debug tool into a sustainable security posture.

Related reading: Generate a JWT Token Online: HS256 vs RS256.