Blogs/Technology

What Is JWT? JSON Web Tokens Explained

Written byDavid M Mundackal
Aug 13, 2026
13 Min Read
What Is JWT? JSON Web Tokens Explained Hero

JSON Web Tokens appear in login flows, APIs, mobile applications, single sign-on systems, and communication between backend services. Their compact format makes them convenient, but that convenience has also produced a surprising number of insecure implementations.

In our experience working with authentication systems, the hardest part of JWT is rarely generating the token. The difficult part is deciding what the token should represent, validating it correctly, storing it safely, and handling expiration and revocation without weakening the entire authentication flow.

This guide explains how JWT works, what it protects, where it fits, and the security decisions that matter in a production application.

What Is a JWT?

A JSON Web Token, commonly called a JWT, is a compact, URL-safe format for transmitting a set of claims between parties. A claim is a statement such as the identity of a user, the system that issued the token, its intended recipient, or the time at which it expires.

The official JWT standard is RFC 7519. JWT defines the structure of the token, while related JOSE standards define how its contents can be signed, authenticated, or encrypted.

A common signed JWT contains three Base64URL-encoded sections separated by periods:

header.payload.signature

A token might look like this:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiJ1c2VyXzEyMyIsImlzcyI6Imh0dHBzOi8vYXV0aC5leGFtcGxlLmNvbSIsImF1ZCI6Imh0dHBzOi8vYXBpLmV4YW1wbGUuY29tIn0.
signature-bytes

The periods are part of the compact serialization. Line breaks have been added above only to make the example easier to read.

The Most Important JWT Fact

A signed JWT is normally readable by anyone who obtains it.

Base64URL encoding is an encoding scheme, not encryption. Anyone can decode the header and payload without possessing the signing key. The signature protects the token against undetected modification, but it does not make the claims private.

Sensitive information such as passwords, private keys, payment details, medical records, or unnecessary personal data should therefore stay out of an ordinary signed JWT.

Encryption requires a JSON Web Encryption token, commonly called JWE, or another secure transport and data-protection design. Most access tokens encountered in application development are signed JWS tokens rather than encrypted JWEs.

The Three Parts of a JWT

1. Header

The header describes how the token is protected. A typical header contains an algorithm and a token type:

{
  "alg": "RS256",
  "typ": "JWT"
}

The alg value identifies the signature or message-authentication algorithm. RS256, for example, uses an RSA private key to sign the token and the corresponding public key to verify it.

The verifier must use a predefined allowlist of acceptable algorithms. Trusting whichever algorithm arrives in the token header allows an attacker to influence a security decision that belongs to the application.

2. Payload

The payload contains the JWT claims set:

{
  "iss": "https://auth.example.com",
  "sub": "user_123",
  "aud": "https://api.example.com",
  "iat": 1786600000,
  "exp": 1786600900,
  "scope": "orders:read"
}

Claims can be registered, public, or private. Registered claims provide standardized names, while private claims support application-specific information.

Common registered claims include:

ClaimMeaningTypical validation
issIssuerMust match the trusted authorization server
subSubjectIdentifies the user or entity represented by the token
audAudienceMust include the API or service processing the token
expExpiration timeToken must be rejected at or after this time
nbfNot beforeToken must not be accepted before this time
iatIssued atHelps determine the token's age
jtiJWT IDProvides a unique identifier that can support replay controls
iss
Meaning
Issuer
Typical validation
Must match the trusted authorization server
1 of 7

RFC 7519 makes many registered claims optional at the generic format level. A real application or protocol should define which claims are required and reject tokens that do not satisfy that profile.

3. Signature

The signature covers the encoded header and payload:

signingInput = base64url(header) + "." + base64url(payload)
signature = sign(signingInput, signingKey)

The receiving service reconstructs the signing input and verifies the signature using the appropriate key. A changed payload produces a failed verification result because it no longer matches the signature.

Signature verification proves that the protected content was produced by a party holding the expected signing key and that the protected bytes have not changed. Trust still depends on selecting the correct issuer, key, algorithm, audience, and token type.

How JWT Authentication Works

A typical JWT authentication flow begins when a user sends credentials or completes an identity-provider login. The authorization server verifies the login and issues an access token. The client then presents that token when calling a protected API.

Authorization: Bearer <access-token>

The API extracts the bearer token and performs cryptographic and claims validation. A valid token allows the API to use the approved claims when making its authorization decision.

The complete flow is:

  1. The user authenticates with an authorization server.
  2. The server issues a short-lived access token.
  3. The client sends the token to the intended API over HTTPS.
  4. The API verifies the signature and required claims.
  5. The API applies its own authorization rules.
  6. The API accepts or rejects the request.

Authentication and authorization remain separate concerns. A valid token may identify the caller, but the API must still decide whether that caller can perform the requested action on the requested resource.

Decoding Is Not Verification

Many JWT libraries provide a function that decodes a token without verifying it. Decoding is useful for inspection, logging, or selecting the key that might verify the signature, but decoded claims are still untrusted input.

During code reviews, we have encountered applications that decoded a token, read an admin claim, and treated the result as authenticated. An attacker could construct a new payload containing "admin": true because creating Base64URL text requires no secret.

Production authorization must use a verification function that validates the signature and required claims. The node-jsonwebtoken documentation makes the same distinction and warns that even a verified payload should be treated as untrusted input whose expected properties must be checked.

JWT Signing Algorithms

JWT implementations commonly use symmetric or asymmetric signing.

HMAC: HS256, HS384, and HS512

HMAC uses the same secret to sign and verify tokens. It can work well when one trusted system both issues and verifies the tokens, or when every verifier is fully trusted to issue tokens too.

Sharing an HMAC secret with several services expands the security boundary. Every service able to verify the token can also create a valid token. A strong, randomly generated secret must be stored in a secret manager rather than committed to source code.

RSA and RSA-PSS: RS256 and PS256

RSA uses a private key for signing and a public key for verification. APIs can verify tokens without gaining the ability to issue them.

Let’s Build a Reliable Backend Together

F22 Labs developers secure backend systems that handle growth, protect user data, and integrate modern standards like JWT.

This separation is useful in systems with one authorization server and multiple resource servers. Public keys can be distributed through a trusted JSON Web Key Set, while the private signing key remains restricted to the issuer.

Elliptic Curve and EdDSA

Elliptic-curve and Edwards-curve algorithms can provide strong signatures with smaller keys or signatures than traditional RSA choices. Library, platform, identity-provider, and compliance support should guide the final selection.

Algorithm choice belongs in a fixed server configuration. RFC 8725, JSON Web Token Best Current Practices, requires libraries to let callers specify supported algorithms and prohibits using algorithms outside that set during cryptographic processing.

A Secure Node.js Example

The following example uses the jose library and an asymmetric signing key. Production keys should come from a managed key service, hardware security module, or protected secret store rather than being generated every time the process starts.

import {
  SignJWT,
  generateKeyPair,
  jwtVerify,
} from "jose";

const issuer = "https://auth.example.com";
const audience = "https://api.example.com";
const algorithm = "RS256";

const { privateKey, publicKey } = await generateKeyPair(algorithm);

const accessToken = await new SignJWT({
  scope: "orders:read",
})
  .setProtectedHeader({ alg: algorithm, typ: "JWT" })
  .setIssuer(issuer)
  .setSubject("user_123")
  .setAudience(audience)
  .setIssuedAt()
  .setJti(crypto.randomUUID())
  .setExpirationTime("15m")
  .sign(privateKey);

const { payload, protectedHeader } = await jwtVerify(
  accessToken,
  publicKey,
  {
    algorithms: [algorithm],
    issuer,
    audience,
  },
);

console.log(protectedHeader.alg);
console.log(payload.sub);

The important part is not the call that creates the token. Security comes from fixing the permitted algorithm, verifying the trusted issuer and intended audience, enforcing expiration, protecting the private key, and authorizing the request using expected claims.

The jose project supports JWT signing, signature verification, claims validation, JWK, JWKS, JWS, and JWE across supported JavaScript runtimes. Its current capabilities are documented in the official jose repository.

Access Tokens, ID Tokens, and Refresh Tokens

JWT describes a token format; it does not define one universal token purpose. Two tokens can both be JWTs while carrying different meanings and requiring different validation rules.

Access Token

An access token authorizes calls to a resource server or API. The API should validate that it is the token's intended audience and apply the included scope or permissions according to its authorization policy.

OAuth does not require every access token to be a JWT. An authorization server may issue an opaque access token instead. RFC 9068 defines an interoperable profile specifically for OAuth 2.0 access tokens that use JWT format.

ID Token

An OpenID Connect ID token communicates information about an authentication event to the client application. It is intended for the client identified by its audience, not as a general-purpose credential for arbitrary APIs.

Using an ID token as an API access token mixes two different security purposes and can result in incorrect validation.

Refresh Token

A refresh token allows a client to request another access token without making the user complete the full login process again. Refresh tokens usually live longer than access tokens and require stronger storage, rotation, revocation, and reuse-detection controls.

A refresh token does not have to be a JWT. An opaque, high-entropy value backed by server-side state is often easier to revoke and rotate safely.

JWT vs Session-Based Authentication

JWT and server-side sessions are both valid architectural choices. JWT did not make sessions obsolete, and neither approach is automatically more secure or scalable.

ConsiderationJWT-Based Access TokenServer-Side Session
StateClaims can be verified without a central session lookupSession data is stored by the server or a shared session service
RevocationHarder before token expiration unless state is addedUsually straightforward by deleting or invalidating the session
Payload exposureSigned payload is readableBrowser normally receives only an opaque identifier
Cross-service useConvenient with carefully scoped audiences and public keysRequires shared session access or introspection
Token sizeUsually largerSession identifier can be small
Permission changesOld claims can remain valid until expirationServer-side state can reflect changes immediately
ComplexityKey management and strict validationSession storage, replication, and CSRF controls
State
JWT-Based Access Token
Claims can be verified without a central session lookup
Server-Side Session
Session data is stored by the server or a shared session service
1 of 7

Session stores can scale horizontally using Redis, databases, or managed session services. JWT verification can reduce a central lookup, but applications frequently reintroduce state for refresh tokens, logout, revocation, risk controls, or permission changes.

In our experience, a secure server-rendered web application often benefits from a conventional session cookie. JWT becomes more compelling when independent APIs need verifiable, short-lived claims issued by a dedicated authorization service.

Advantages of JWT

Compact and Transport-Friendly

JWT compact serialization works conveniently in HTTP headers and other URL-safe contexts. Token size still matters because every request may carry the complete token, so claims should remain minimal.

Standardized Claims

Registered claim names such as iss, sub, aud, and exp give issuers and consumers a shared vocabulary. Protocol profiles can then define exactly how those claims must be used.

Distributed Verification

Asymmetric signatures let many services verify tokens using public keys without giving those services the private key needed to issue tokens.

Reduced Dependence on a Session Lookup

An API can often validate a signed access token locally. This capability may reduce latency and dependence on a central session service, although revocation and frequently changing authorization data may still require shared state.

Broad Ecosystem Support

Mature JWT and JOSE libraries exist across common programming languages and platforms. Standards-based key discovery also supports integration with identity providers and API gateways.

JWT Limitations

Revocation Is Not Built In

A valid signed token normally remains valid until it expires. Logout, account suspension, password changes, and permission removal may require short token lifetimes, a denylist, a token-version check, sender-constrained tokens, or an introspection-based design.

Claims Can Become Stale

Roles and permissions embedded in a token represent a snapshot from the time of issuance. A user whose access changes may retain old privileges until the token expires or the verifier performs an additional state check.

Bearer Tokens Can Be Replayed

A bearer token can generally be used by whoever possesses it. A valid signature does not prove that the current presenter is the user or application to which the token was originally issued.

Short lifetimes, secure transport, careful storage, refresh-token rotation, and sender-constraining technologies reduce this risk.

Tokens Increase Request Size

Large claims create large HTTP headers, increase bandwidth, and may exceed proxy or server limits. JWT payloads should contain identifiers and essential authorization data rather than complete user profiles.

Key Management Remains Difficult

Signing keys require secure generation, storage, access control, rotation, publication, and retirement. JWT moves part of the trust decision into cryptography; it does not remove operational security work.

JWT Security Best Practices

Validate More Than the Signature

A successful signature check is only one validation step. The verifier should check the expected algorithm, issuer, audience, expiration, not-before time when used, token type or purpose, and any application-required claims.

RFC 8725 also recommends mutually exclusive validation rules for different kinds of JWTs. Access tokens, ID tokens, email-verification tokens, and password-reset tokens should not become interchangeable simply because they use the same format.

Pin the Allowed Algorithms

The application should explicitly configure the acceptable algorithm or small algorithm set. The token's alg header describes the token but must not determine security policy by itself.

Support for unsecured alg: none tokens should remain disabled unless an exceptionally specific protocol requires it and supplies protection elsewhere.

Validate the Issuer and Audience

The issuer identifies the authority that created the token. The audience identifies the intended recipient. Validating both prevents a correctly signed token issued for another tenant, environment, or API from being accepted in the wrong place.

Keep Access Tokens Short-Lived

A short expiration limits the useful lifetime of a stolen bearer token. The appropriate duration depends on risk and user experience, but access tokens commonly live for minutes rather than days.

Small clock-skew allowances can account for minor time differences between systems. Broad allowances weaken expiration enforcement and should be avoided.

Protect Signing Keys

Private keys and HMAC secrets should remain in a secret manager, key-management service, or hardware-backed system with limited access and audited use. Source repositories, mobile applications, browser code, logs, and ordinary configuration files are unsuitable locations for signing secrets.

Key rotation should use stable key identifiers and a controlled overlap period. Verifiers need the new public key before new tokens use it, and the old verification key must remain available until previously issued tokens expire.

Use HTTPS Everywhere

TLS protects tokens while they travel across the network. JWT signatures do not prevent an attacker from stealing and replaying a bearer token observed over an insecure connection.

Keep Sensitive Data Out of the Payload

Signed JWT claims are usually visible to the holder. Minimal claims reduce privacy exposure, token size, and the chance of stale data influencing authorization.

Design Browser Storage Deliberately

Browser token storage involves trade-offs. JavaScript-readable storage is exposed to successful cross-site scripting, while cookies can be sent automatically and therefore require appropriate HttpOnly, Secure, SameSite, and cross-site request forgery protections.

A backend-for-frontend pattern can keep OAuth tokens away from browser JavaScript and expose only a hardened session cookie to the browser. The right choice depends on the application architecture and threat model.

Let’s Build a Reliable Backend Together

F22 Labs developers secure backend systems that handle growth, protect user data, and integrate modern standards like JWT.

Rotate Refresh Tokens

Refresh-token rotation issues a new refresh token when the previous one is used and invalidates or tracks the old token. Reuse of an already rotated token can then signal theft and terminate the token family.

Refresh tokens should be scoped to the client, stored securely, and revoked when risk events occur.

Avoid Writing Tokens to Logs or URLs

Tokens in query strings can leak through browser history, server logs, analytics, copied links, and referrer headers. Authorization headers or protected cookies are safer transport mechanisms.

Logging systems should redact authorization headers, cookies, refresh tokens, and token values from errors and traces.

Common JWT Mistakes We See in Practice

Trusting Decoded Claims

Decoded claims provide no authenticity guarantee. Every authorization decision must follow successful verification using trusted configuration.

Using One Token for Every Purpose

A token issued to confirm an email address should not authorize API calls. Distinct audiences, token types, keys, claims, and validation paths reduce cross-token confusion.

Issuing Long-Lived Access Tokens

Long validity periods make theft and authorization changes harder to contain. Short access-token lifetimes paired with a controlled renewal mechanism provide a safer balance.

Storing Complete User Records in Tokens

User profiles increase token size and become stale. Stable subject identifiers and limited authorization claims are generally more appropriate.

Placing Secrets in Frontend Code

A browser or mobile application cannot safely hold a shared signing secret distributed to every installation. Public clients should rely on an authorization server rather than minting trusted access tokens themselves.

Sharing an HMAC Secret Too Widely

Every holder of an HMAC verification secret can create valid signatures. Asymmetric signing provides a safer trust boundary when many independent services need verification access.

Assuming Logout Invalidates Every Token

Removing a token from one browser does not invalidate copies elsewhere. Effective logout may require refresh-token revocation, short-lived access tokens, session termination, or a server-side revocation mechanism.

When Should You Use JWT?

JWT is a good fit when a trusted issuer needs to send compact, verifiable claims to one or more independent services. API access tokens, service-to-service identity, short-lived single-use flows, and federated identity protocols are common examples.

JWT is less compelling when one application controls both the browser and backend, immediate revocation is essential, authorization data changes frequently, or a small opaque session identifier would meet the requirement more safely.

The decision should begin with the trust model and lifecycle requirements rather than a desire to make the application “stateless.”

Frequently Asked Questions

What does JWT stand for?

JWT stands for JSON Web Token. It is a standardized format for carrying claims between parties in a compact and URL-safe representation.

Is a JWT encrypted?

A typical signed JWT is not encrypted. Its header and payload can be decoded by anyone who obtains it. Encryption requires JWE or another suitable protection mechanism.

Is Base64URL encoding secure?

Base64URL encoding makes binary data safe for URL-oriented transport. It provides no secrecy, authenticity, or tamper protection by itself.

Can someone change a JWT payload?

Anyone can create a modified payload, but a correctly implemented verifier will reject it because the signature no longer matches. This protection depends on strict signature and claims validation.

Where should a JWT be stored?

Storage depends on the client and threat model. Browser applications commonly use hardened cookies or an in-memory design, while native apps should use platform-provided secure storage.

What happens when a JWT expires?

The receiving service must reject the token at or after its exp time. The client may authenticate again or use an approved refresh mechanism to obtain another access token.

Can a JWT be revoked?

JWT itself does not define revocation. Applications can use short expiration times, deny lists, token versions, refresh-token revocation, introspection, or key rotation depending on the incident and design.

What is the difference between JWT and OAuth?

JWT is a token format. OAuth is an authorization framework. OAuth access tokens may be JWTs or opaque values, depending on the authorization server and deployment.

What is the difference between JWT and JWS?

JWT defines a claims format. JWS defines how content is protected with a digital signature or message authentication code. A commonly encountered signed JWT uses JWS compact serialization.

Should permissions be stored in a JWT?

Stable, narrowly scoped permissions can be included when the API validates them correctly. Frequently changing or highly sensitive authorization decisions often need a current server-side check as well.

Conclusion

JWT is a compact format for carrying claims, not a complete authentication system and not an automatic security upgrade. Its signature can protect integrity and authenticate the issuer, while the token's claims communicate identity, audience, validity, and authorization context.

Secure JWT implementations keep payloads minimal, use short-lived access tokens, protect signing keys, pin allowed algorithms, validate issuer and audience, separate token purposes, and plan for refresh, revocation, and key rotation.

The most useful mindset is straightforward: treat every token as untrusted input until its signature, claims, purpose, and lifecycle have all been validated.

Author-David M Mundackal
David M Mundackal

Backend Dev and tech enthusiast. Always exploring, always learning. Coding not just for a living, but for the thrill of it. Here for the tech, staying for the innovation.

Share this article

Phone

Next for you

8 Best GraphQL Libraries for Node.js in 2025 Cover

Technology

Aug 4, 202613 min read

8 Best GraphQL Libraries for Node.js in 2025

8 Best GraphQL Libraries for Node.js in 2026 Too Long? Read This First - Choose Apollo Server when you need a mature ecosystem, GraphOS integration, plugins, or Apollo Federation. - Choose GraphQL Yoga for a modern, portable server with Fetch API compatibility and built-in support for subscriptions over Server-Sent Events. - Choose Mercurius when your application already uses Fastify and runtime efficiency is a major priority. - Use GraphQL.js when you need the official JavaScript implementati

9 React Native Animation Libraries and Tools Compared Cover

Technology

Aug 4, 202615 min read

9 React Native Animation Libraries and Tools Compared

Too Long? Read This First - Use React Native Reanimated for gesture-driven, interruptible, and performance-sensitive interface animations. - Use the built-in Animated API for simple fades, transforms, and timed sequences without another dependency. - Pair React Native Gesture Handler with Reanimated for swipes, dragging, pinching, rotation, and other touch-driven experiences. - Use Lottie React Native for non-interactive motion graphics supplied by designers. - Choose React Native Skia for cust

9 Critical Practices for Secure Web Application Development Cover

Technology

Aug 4, 202616 min read

9 Critical Practices for Secure Web Application Development

Too Long? Read This First - Define security requirements and model threats before implementation begins. - Treat authentication, account recovery, and MFA as one complete identity system. - Apply server-side authorization to every protected action and object. - Prevent injection with parameterized APIs, structured validation, safe output handling, and restricted outbound requests. - Protect sessions and tokens throughout their complete lifecycle. - Minimise sensitive data and manage encryption