A complete guide to understanding JWTs — what they are, how they work, when to use them, and how encoding, decoding, validation, and verification differ.
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.
JWTs can be signed using a secret with the HMAC algorithm, or a public/private key pair using RSA or ECDSA.
Although JWTs can be encrypted to also provide secrecy between parties, the most common use case focuses on signed tokens. Signed tokens can verify the integrity of the claims contained within them, while encrypted tokens hide those claims from other parties. When tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it.
Here are the most common scenarios where JSON Web Tokens are the right tool:
Authorization header. The server can verify the token without maintaining server-side session state, enabling stateless, horizontally scalable architectures.In its compact form, JSON Web Tokens consist of three parts separated by dots (.):
A JWT therefore looks like this:
The header typically consists of two parts: the type of the token (which is JWT) and the signing algorithm being used, such as HMAC SHA256 or RSA.
This JSON is then Base64Url encoded to form the first part of the JWT.
The second part is the payload, which contains the claims. Claims are statements about an entity (typically the user) and additional metadata. There are three types of claims:
iss (issuer), exp (expiration time), sub (subject), aud (audience), iat (issued at), and others defined in RFC 7519 §4.1. Note that claim names are intentionally only three characters long — JWT is meant to be compact.The payload is then Base64Url encoded to form the second part of the JWT.
To create the signature, you take the encoded header, the encoded payload, a secret, and the algorithm specified in the header, and sign that.
For example, using the HMAC SHA256 algorithm:
The signature verifies that the message was not altered in transit. When the token is signed with a private key, it also proves that the sender is who they claim to be.
Putting it all together, the output is three Base64Url strings separated by dots — compact enough to be passed in an HTTP header or URL parameter. Here is a real encoded JWT:
You can paste this token directly into our JWT Encoder & Decoder to inspect it, or experiment with the jwt.io Debugger.
In authentication, when the user successfully logs in using their credentials, a JSON Web Token is returned by the server. Since tokens are credentials, great care must be taken to prevent security issues. In general, you should not keep tokens longer than required.
Whenever the user wants to access a protected route or resource, the user agent should send the JWT — typically in the Authorization header using the Bearer schema:
This is a stateless authorization mechanism. The server's protected routes check for a valid JWT in the Authorization header. If the token is valid, the user is allowed to access protected resources. Because the token carries all the claims, the server may not need to query a database for certain operations.
Authorization header, Cross-Origin Resource Sharing (CORS) won't be an issue because the request does not rely on cookies. However, be mindful of header size limits — some servers reject requests with headers larger than 8 KB. Avoid embedding large permission sets in tokens; consider using fine-grained authorization solutions for complex permission models.A typical JWT authentication flow works as follows:
Authorization: Bearer header.exp, aud, iss), and grants or denies access.exp claim) and the client must re-authenticate or use a refresh token.HttpOnly cookies.Let's compare JWTs against two older alternatives:
| Feature | JWT | SWT | SAML |
|---|---|---|---|
| Format | JSON (compact) | Form-encoded key-value pairs | XML (verbose) |
| Size | Small — good for HTTP headers & URLs | Small | Large — not suitable for HTTP headers |
| Signing | Symmetric (HMAC) or asymmetric (RSA, ECDSA) | Symmetric (HMAC) only | Symmetric or asymmetric (XML DSig — complex) |
| Parsing | Native in all languages via JSON parsers | Simple key-value parsing | Requires an XML parser; no natural object mapping |
| Web & mobile | Excellent — widely supported at internet scale | Limited adoption | Common in enterprise SSO; heavy for mobile |
| Standard | RFC 7519 | Informal | OASIS SAML |
Because JSON is less verbose than XML, an encoded JWT is significantly smaller than a comparable SAML assertion. JSON parsers are native to virtually all programming languages, while XML requires a dedicated parser with no natural document-to-object mapping. These properties make JWT the default choice for modern web and mobile applications.
JWT validation and verification are often used interchangeably, but they address slightly different aspects of JWT security:
| Validation | Verification | |
|---|---|---|
| What it checks | Structure, format, and claim values | Authenticity and integrity via cryptographic signature |
| Key questions | Is this token well-formed? Are the claims correct? | Was this token really issued by a trusted party? Has it been tampered with? |
| Requires a key? | No | Yes — a shared secret (HMAC) or public key (RSA/ECDSA) |
Validation generally refers to checking the structure, format, and content of the JWT:
exp claim).nbf — Not Before).iat (issued at) timestamp is in the past.Verification confirms the authenticity and integrity of the token:
alg field (e.g., HMAC, RSA, or ECDSA).iss claim matches the expected issuer.aud claim matches the expected audience (your application's identifier).verify() function. Always use a library's built-in verify method rather than manually decoding and skipping signature verification.Encoding transforms a header and payload into the compact, URL-safe JWT string:
encodedHeader.encodedPayload.encodedHeader.encodedPayload.encodedSignature.Decoding reverses the encoding process. It converts each Base64Url-encoded segment back into readable JSON. Decoding does not require any key — anyone who holds the token can decode the header and payload. This is why you must never store sensitive data in a JWT payload unless the token is also encrypted.
In many JWT libraries, "decoding" also implies verification: after decoding, the library re-computes the expected signature and compares it against the token's signature to confirm authenticity.
| Encoding | Decoding | |
|---|---|---|
| Input | Header object + payload object + signing key | JWT string (+ optional signing key for verification) |
| Output | Compact JWT string (xxx.yyy.zzz) | Readable header & payload JSON (+ validity status) |
| Requires key? | Yes — to sign the token | No to read; yes to verify authenticity |
| Hides content? | No — Base64Url is not encryption | N/A — content was never hidden |
Use our free, privacy-first JWT tool to encode, decode, and verify tokens instantly — no data leaves your browser.
Open JWT Encoder & Decoder