JWT Decoder

Decode JWT header and payload sections instantly. Inspect claims, check expiry, and detect the signing algorithm.

By Pankaj Kumar · DevToolsHub · Last updated Jun 2026

What this JWT decoder does

Paste a JWT and this JWT decode tool instantly returns the decoded token content — no secret or key needed, since the header and payload are Base64URL-encoded, not encrypted. Here's a JWT header example showing what comes back: {"alg":"HS256","typ":"JWT"}. Switch to the Payload tab to see the claims, and check the expiry banner to see at a glance whether the token is valid, expiring soon, or expired.

JWT debugging in ASP.NET Core

In my ASP.NET Core projects, this is the first tool I reach for when an endpoint returns 401 despite a token being present. The JWT bearer middleware validates tokens silently — it doesn't surface whether the token expired, whether the aud claim mismatched, or whether the issuer URL has a trailing slash difference. Decoding the token and reading the claims directly usually surfaces the problem in under a minute.

How to decode JWT token data online

  1. Paste the full JWT (three dot-separated segments) into the token editor.
  2. Decoding runs automatically once all three segments are present, or click Decode.
  3. Switch between the Header and Payload tabs to inspect the signing algorithm and claims.
  4. Check the expiry banner above the tabs to see at a glance whether the token is valid, expiring soon, or expired.

Five real ASP.NET Core JWT debugging scenarios

  1. A 401 returned by your API even though the client sends a token. Decode the token and check: Is exp in the past? Does aud exactly match your ValidAudience? Does iss have a trailing slash? These three mismatches account for the majority of silent JWT authentication failures.
  2. A 403 on a route decorated with [Authorize(Roles = "Admin")]. Azure AD uses a roles claim; older IdentityServer uses role; ASP.NET Core maps ClaimTypes.Role to the claim name configured in RoleClaimType. Decode the token to see which claim name your identity provider actually uses.
  3. Debugging an identity token from Azure AD B2C or Auth0 in a development environment. Paste the token from your browser's localStorage or network tab to inspect the full claim set before writing authorization policies.
  4. Verifying the exp claim after changing token lifetime in your identity provider configuration. Token lifetime changes are easy to mistype. Decode a freshly issued token to confirm the exp value matches the intended duration.
  5. Mapping claims from a third-party OAuth provider (GitHub, Google, Microsoft) into your application's user model. Each provider uses different claim names for the same data — decode the token to see the exact claim keys and values before writing the claim transformation code in OnTokenValidated.

How JWT validation works in ASP.NET Core middleware

When you call builder.Services.AddAuthentication().AddJwtBearer(), the framework registers middleware that intercepts every incoming request, extracts the token from the Authorization: Bearer ... header, validates the signature and registered claims, then populates HttpContext.User with a ClaimsPrincipal. If validation fails for any reason, the middleware short-circuits with a 401. To see the specific failure reason in your logs:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer   = true,
            ValidIssuer      = "https://your-idp.example.com/",
            ValidateAudience = true,
            ValidAudience    = "your-api-resource",
            ValidateLifetime = true,
            ClockSkew        = TimeSpan.Zero   // default is 5 min — often hides expiry bugs
        };
        options.Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = ctx =>
            {
                // ctx.Exception reveals the exact validation failure reason
                logger.LogWarning("JWT validation failed: {Message}", ctx.Exception.Message);
                return Task.CompletedTask;
            }
        };
    });

The most common cause of a silent 401 is a mismatch between the iss claim and ValidIssuer — often a trailing slash difference. Decode your token here and compare the iss value directly against your TokenValidationParameters configuration.

JWT structure (RFC 7519)

A JWT is three Base64URL segments joined by dots — header.payload.signature:

JWT structure: header, payload, and signature A JSON Web Token is three Base64URL-encoded segments joined by dots: a header containing the signing algorithm and token type, a payload containing the claims, and a signature computed from the header and payload using a secret or private key. eyJhbGciOiJIUzI1NiJ9 . eyJzdWIiOiJ1c2VyMTIzIn0 . SflKxwRJSMeKKF2Q_adQssw5c HEADERalg & typ PAYLOADclaims (sub, iss, aud, exp...) SIGNATUREverifies header + payload weren't altered
PartEncodingContains
HeaderBase64URL (RFC 4648 §5)alg (signing algorithm), typ ("JWT")
PayloadBase64URLClaims: sub, iss, aud, exp, iat, custom fields
SignatureAlgorithm-specific binaryHMAC or RSA/ECDSA hash of header.payload using secret or private key

Decoding vs verifying

This tool only does the left-hand column below — the right-hand column is what ASP.NET Core's JWT bearer middleware does automatically on every request:

AspectDecoding (this tool)Verifying (server middleware)
Requires a secret or key?NoYes — HS256 shared secret, or RS256/ES256 public key
Checks the signature?NoYes — rejects the request if it doesn't match
exp / nbf / aud / issDisplayed for information only, never enforcedEnforced — request is rejected on any mismatch
Who normally does thisYou, while debuggingThe JWT bearer middleware, automatically, on every request
Possible without the key?Yes — header/payload are Base64URL, not encryptedNo

Reading JWT claims in ASP.NET Core controllers

Once the JWT bearer middleware validates a token, its claims are accessible via HttpContext.User as a ClaimsPrincipal. Custom JWT claims map to ClaimsPrincipal by their exact key name from the payload:

[Authorize]
[HttpGet("profile")]
public IActionResult GetProfile()
{
    // Standard claims mapped by ASP.NET Core
    var sub  = User.FindFirstValue(ClaimTypes.NameIdentifier); // JWT "sub"
    var name = User.FindFirstValue(ClaimTypes.Name);           // JWT "name"

    // Custom claim — matches the key name exactly as it appears in the JWT payload
    var tenantId = User.FindFirstValue("tenant_id");
    var orgSlug  = User.FindFirstValue("org");

    return Ok(new { sub, name, tenantId, orgSlug });
}

Decode the token here and verify that the claim key name in the payload matches exactly what your FindFirstValue() call expects — including underscores vs hyphens and camelCase vs snake_case. Azure AD, Auth0, and custom IdentityServer deployments all use different claim name conventions.

Standard JWT claims (RFC 7519 §4.1)

  • sub (subject) — unique identifier of the user or entity the token represents
  • iss (issuer) — authority that created the token, typically a domain URL
  • aud (audience) — intended recipient; servers reject tokens with a mismatched audience
  • exp (expiration) — Unix timestamp after which the token must not be accepted
  • iat (issued at) — Unix timestamp of token creation
  • nbf (not before) — Unix timestamp before which the token must not be accepted
  • jti (JWT ID) — unique identifier used to prevent replay attacks

Frequently asked questions

Does this verify the signature? No. Signature verification requires the secret key (HS256) or public key (RS256/ES256). This tool decodes the header and payload only — which is all you need to inspect claims and debug auth failures.

Why does the JWT middleware return 401 when the token looks valid? The four most common reasons: expired token (exp in the past), audience mismatch (aud vs ValidAudience), issuer mismatch (iss vs ValidIssuer), and clock skew on the server. Decode the token here and compare each claim against your TokenValidationParameters.

What is the alg:none vulnerability? An attacker strips the signature and sets alg to "none", hoping the server accepts it without verification. ASP.NET Core's JWT bearer middleware rejects alg:none tokens correctly by default.

What RFCs govern JWT? RFC 7519 defines JWT. RFC 7518 defines the signing algorithms (JWA). RFC 7517 defines JSON Web Keys (JWK) used for public key distribution via /.well-known/jwks.json endpoints.

Security warning

Never paste a live production JWT from a real user session into any online tool. JWTs carry identity and access privileges. Generate test tokens in a development environment. This tool processes tokens in-memory and stores nothing — but the habit of protecting production tokens is more important than any specific tool's privacy policy.

This tool is built with ASP.NET Core 8, Blazor Server, and System.Text.Json and a manual Base64Url decode. It runs securely on Microsoft Azure.

Native code equivalents

Production-ready snippets — same logic the tool runs, in your language
Your data is processed within your active session only · Never stored or logged
JavaScript
Python
Go
cURL / bash
// Decode a JWT without signature verification (development / inspection only)
// RFC 7519 §3: header.payload.signature — all Base64URL encoded (RFC 4648 §5)
function decodeJwt(token) {
  const parts = token.split('.');
  if (parts.length !== 3) throw new Error('Invalid JWT: expected 3 dot-separated parts');

  const decodeBase64url = (s) => {
    const b64 = s.replace(/-/g, '+').replace(/_/g, '/');
    return JSON.parse(atob(b64.padEnd(b64.length + (4 - b64.length % 4) % 4, '=')));
  };

  return {
    header:  decodeBase64url(parts[0]),
    payload: decodeBase64url(parts[1]),
  };
}

const { header, payload } = decodeJwt(token);
console.log('Algorithm:', header.alg);
console.log('Subject:  ', payload.sub);
console.log('Expires:  ', new Date(payload.exp * 1000).toISOString());
Your input stays private. All processing happens in-memory on the server and is never stored, logged, or associated with your identity. Sensitive data — tokens, signing keys, and passwords — is safe to use here.
Input Section

JWT token

Output Section
Header
Payload

Header

JWT header

{}