All Blogs

Quick Overview: JWT security depends on how carefully tokens are created, validated, stored, and managed. This blog covers how JWTs work, their structure, and the signing algorithms behind them. It breaks down common vulnerabilities, severity levels, and detection challenges, then walks through nine practical best practices for secure implementation, from key rotation to token revocation and end-to-end testing.
A JWT can make authentication fast and flexible, but a small validation mistake can turn that convenience into an access-control weakness. The risk is real: OWASP’s 2025 data records 1,120,673 occurrences across authentication-failure weaknesses.
The token is only as secure as its validation.
JWTs are widely used across APIs, web applications, OAuth, and OpenID Connect. OWASP specifically highlights risks such as unsecured tokens, key confusion, and improper token handling.
A secure JWT implementation requires more than signing a token. It needs secure algorithms, cryptographic protection, validated security with API penetration testing, protected keys, and controlled token lifetimes. This guide explains the best practices that help build a stronger JWT authentication and authorization layer.
Weak JWT handling is invisible until it's exploited. Start testing your APIs for free today. Get Started Free
Table of Contents
- What is a JSON Web Token (JWT)?
- How Does JWT Authentication Work?
- JWT Structure: Header, Payload and Signature
- JWT Security Risks: Severity, Detection, Remediation, and Impact
- JWT Signing Algorithms: Which One Should You Use?
- Nine JWT Security Best Practices
- To Wrap Up
What is a JSON Web Token (JWT)?
A JSON Web Token (JWT) is a compact, URL-safe format used to represent claims between parties. Defined in RFC 7519, JWTs commonly carry information about a user, session, or authorization context.
A JWT typically contains claims such as the issuer, subject, audience, expiration time, and other application-specific data. These claims can help a server determine who or what a token represents and whether it should be accepted.
JWTs can be digitally signed or protected with a Message Authentication Code (MAC) to provide integrity and authenticity. They can also be encrypted using JSON Web Encryption (JWE) when confidentiality is required. Signing does not encrypt the token.
A JWT is not inherently an authentication or security solution. It is a token format used within an authentication or authorization architecture. Its security depends on proper cryptographic protection, claim validation, key management, expiration, storage, and secure handling.
How Does JWT Authentication Work?
JWT authentication works by issuing a cryptographically protected token after successful token-based authentication, then validating its signature and relevant claims whenever the client requests a protected resource.

1. Authenticate User
The process begins when a user provides valid credentials or completes another authentication mechanism. The authentication server verifies the identity and determines whether the user or client is authorized to receive a token.
2. Issue JWT
After successful authentication, the server creates a JWT containing relevant claims such as sub, iss, aud, exp, and application-specific authorization information. The token is then cryptographically signed or protected with a MAC.
3. Send Token
The client receives the JWT and stores or handles it according to the application's security architecture. For subsequent requests, the client typically presents the token to the protected API or resource server, commonly through an HTTP authorization mechanism.
4. Verify Signature
The server parses the received JWT and verifies its cryptographic protection using its configured verification key. It should rely on its own security policy to determine acceptable algorithms instead of blindly trusting the token's alg header.
5. Validate Claims
After cryptographic verification, the server validates the claims required by the application context. This can include checking the expected iss, aud, exp, and nbf values, along with token type, scope, or other application-specific requirements.
6. Grant Access
If the JWT passes all required validation checks, the server uses the verified identity, and authorization claims to make an access decision. If the signature, claims, token type, or other required checks fail, the request should be rejected.
Your JWT implementation might already be forgeable. Run a full API security test to confirm. Test My APIs
JWT Structure: Header, Payload and Signature
A JWT is commonly represented as three Base64URL-encoded parts separated by periods (.). In a signed JWT using JWS Compact Serialization, these parts are the header, payload, and signature.
A simplified JWT looks like this: Header.Payload.Signature
For example:
EyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 // Header . EyJzdWIiOiIxMjM0NTYiLCJyb2xlIjoiYWRtaW4iLCJleHAiOjE3MDAwMDAwMDB9 // Payload . SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV\_adQssw5c // SignatureEach section has a specific purpose. Understanding what each part contains is important because Base64URL encoding does not provide confidentiality. Anyone who obtains a typical signed JWT can decode its header and payload.
Header
The header contains metadata about the token itself and specifies how it should be processed. It is a Base64URL-encoded JSON object that primarily defines the cryptographic parameters.
- alg (Algorithm): Specifies the signing algorithm used to secure the token, such as HS256 (HMAC with SHA-256) or RS256 (RSA Signature with SHA-256).
- typ (Type): Indicates the token type, which is standardly set to JWT.
- kid (Key ID): Specifies an optional key identifier that tells the receiving application which public key or secret to use for validation.
A decoded header may look like:
{ "alg": "HS256", "typ": "JWT" }The alg value is particularly important for JWT security. Applications should define which algorithms they accept instead of blindly allowing the token to determine the verification method.
Payload
The payload contains the "claims," which are statements about the user entity and additional metadata. This JSON object is also Base64URL-encoded and holds three categories of claims: registered, public, and private.
- sub (Subject): Identifies the principal user or entity behind the token.
- iss (Issuer): Specifies the authority that issued the token.
- aud (Audience): Identifies the intended recipient or resource server allowed to process the token.
- exp (Expiration Time): Defines the Unix timestamp after which the token must be rejected.
- iat (Issued At): Indicates when the token was created.
- jti (JWT ID): Provides a unique identifier for the token, useful for preventing replay attacks.
Here is how a simplified example of a payload:
{ "sub": "123456", "role": "admin", "iss": "[https://example.com](https://example.com)", "exp": 1700000000 }Here is something every developer needs to understand clearly. The payload is encoded, not encrypted. Anyone who gets hold of the token can decode it and read the claims inside. That is why sensitive data, like passwords or personal identification numbers, should never be placed in the payload.
Signature
The signature is the part that gives the token its trustworthiness. It is created by taking the encoded header, the encoded payload, and a secret key, then running them through the algorithm named in the header.
For HS256, it works like this:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )The signature ensures integrity and authenticity. If anyone changes even a single character in the header or payload after the token is issued, the signature will no longer match. The server will catch this mismatch immediately and reject the token. This is what makes JWTs tamper evident, even though the data inside them is visible to anyone who looks.
JWT Security Risks: Severity, Detection, Remediation, and Impact
JWT vulnerabilities can range from incorrect token validation to complete authentication bypass. The following table provides a simplified view of common JWT security risks, their typical severity, how they can be detected, and the potential impact if left unresolved.
| JWT Vulnerability | Severity | How Easily It's Detected | Effort to Fix | Real-World Impact |
|---|---|---|---|---|
| Algorithm set to "none" | Critical | Easy to catch with basic checks | Low effort to patch | Attackers bypass authentication entirely |
| Algorithm confusion (RS256 treated as HS256) | Critical | Requires deeper testing to catch | Low effort to patch | Attacker takes over accounts fully |
| No signature verification on the server | Critical | Easy to catch with basic checks | Low effort to patch | Tokens can be forged freely |
| jwk header parameter injection | Critical | Requires deeper testing to catch | Low effort to patch | Authentication can be bypassed |
| jku header parameter injection | Critical | Requires deeper testing to catch | Low effort to patch | Authentication can be bypassed |
| Weak or guessable HMAC secret | High | Easy to catch with basic checks | Moderate effort to patch | Secret can be brute-forced, tokens forged |
| kid parameter injection | High | Hard to catch, needs advanced testing | Moderate effort to patch | Token forgery, in some cases remote code execution |
| No expiration (exp) validation | High | Easy to catch with basic checks | Low effort to patch | Tokens stay valid indefinitely |
| Token stored in localStorage | High | Easy to catch with basic checks | Moderate effort to patch | Token theft through XSS attacks |
| Sensitive data placed in the payload | Medium | Easy to catch with basic checks | Low effort to patch | Exposure of user or session data |
| No audience (aud) validation | Medium | Requires deeper testing to catch | Low effort to patch | Token reused across unintended applications |
| Token lifetime set too long | Medium | Easy to catch with basic checks | Low effort to patch | Longer window for a compromised token to be misused |
JWT Signing Algorithms: Which One Should You Use?
JWT signing algorithms determine how a token is cryptographically protected, and how a server verifies that the token has not been modified. The right choice depends on your application's architecture, trust boundaries, key distribution, and security requirements.
A JWT can use different cryptographic algorithms to provide integrity and authenticity. In a signed JWT, the issuer uses a key to create the signature, while the receiving application uses the appropriate key to verify it.
The main choices are symmetric algorithms, such as HMAC, and asymmetric algorithms, such as RSA and ECDSA. The key difference is how signing and verification keys are managed.
| Algorithm Family | Examples | Key Model | Common Use |
|---|---|---|---|
| HMAC | HS256, HS384, HS512 | Same secret signs and verifies | Systems where trusted services can securely share one secret |
| RSA | RS256, RS384, RS512 | Private key signs, public key verifies | Distributed applications and APIs |
| ECDSA | ES256, ES384, ES512 | Private key signs, public key verifies | Systems requiring asymmetric signing with smaller keys |
HMAC Algorithms
HMAC algorithms use the same secret key to sign and verify JWTs. For example, HS256 uses HMAC with SHA-256. This approach can be simple when the issuer and verifier operate within the same trusted environment.
The main security concern is secret distribution. Any service that can verify the token also possesses the secret and could potentially create valid tokens. Therefore, HMAC secrets must be generated with strong entropy and protected through secure key-management practices.
RSA Algorithms
RSA-based algorithms, such as RS256, use a private key for signing and a corresponding public key for verification. The private key can remain with the trusted token issuer while other services receive only the public key.
This makes RSA useful when multiple services need to verify tokens without having the ability to issue them. However, private-key protection, key rotation, and secure public-key distribution still need to be managed carefully.
ECDSA Algorithms
ECDSA algorithms, such as ES256, also use asymmetric keys. A private key creates the signature, while the corresponding public key verifies it. ECDSA can provide strong security with smaller keys than comparable RSA configurations.
ES256 can be a good option when the application's libraries, infrastructure, and key-management systems support it reliably. The algorithm should be selected based on the complete environment rather than simply choosing it because it uses newer cryptography.
Now, which JWT algorithm should you choose?
There is no single JWT signing algorithm that is universally best. Choose an algorithm based on your trust boundaries, key distribution models, performance requirements, supported libraries, and operational capabilities.
As a practical approach:
- Choose HMAC when a small, trusted set of services can securely share a high-entropy secret.
- Choose RSA or ECDSA when you need asymmetric signing, especially when many services need to verify tokens but should not possess the signing key.
- Use an explicit algorithm allowlist for every JWT validation context.
- Avoid choosing algorithms dynamically based only on the token's alg header.
- Plan key rotation and cryptographic agility so the application can transition to another supported algorithm when requirements change.
Most importantly, algorithm selection alone does not make JWT authentication secure. The application must also verify the cryptographic protection correctly, validate relevant claims, protect signing keys, enforce token types, and handle token lifecycles securely.
Enterprise-grade JWT and API security testing shouldn't break your budget. Compare plans built for every team. Explore Plans
9 JWT Security Best Practices
Following JWT security best practices help prevent token forgery, unauthorized access, data exposure, and session abuse. Secure JWT implementations combine strong cryptography, proper claim validation, limited token lifetimes, and safe token handling.

1. Use Strong Signing Algorithms
Choose a signing algorithm that matches your application's trust model and key-management architecture. Applications should explicitly allow only expected algorithms and reject unexpected values instead of relying on the JWT's alg header to determine security policy.
For symmetric signing, use a cryptographically strong secret with sufficient entropy. For asymmetric signing, protect private keys carefully and distribute public verification keys securely. Avoid outdated or inappropriate algorithms, and review algorithm choices as cryptographic guidance and application requirements evolve.
2. Validate Every Token Claim
Do not treat JWT claims as trustworthy simply because they are present in a decoded token. After verifying the token's cryptographic protection, validate claims required by your application's security context and authorization model.
Check claims such as iss, aud, exp, and nbf where applicable. You should also validate sub, jti, scopes, roles, or token-type indicators when your application depends on them. Define expected values and reject tokens that fail required validation.
3. Set Short Expiration Times
Use short-lived access tokens to reduce the period during which a compromised JWT can be misused. The appropriate lifetime depends on the application's risk, session requirements, and architecture, so there is no single expiration value suitable for every system.
Pay particular attention to the exp claim and reject tokens after their expiration time. If longer sessions are required, use a separate refresh-token mechanism with appropriate protection, rotation, and revocation controls rather than unnecessarily extending access-token lifetimes.
4. Avoid Sensitive Data in Payload
A typical signed JWT does not hide its payload. Its contents are Base64URL-encoded and can be decoded by anyone who obtains the token. Therefore, avoid placing passwords, private keys, credentials, or unnecessary confidential information in JWT claims.
Keep the payload limited to information required for the application's purpose. When confidentiality is genuinely required, use an appropriately designed encryption mechanism such as JWE. Remember that signing provides integrity and authenticity, while encryption provides confidentiality.
5. Store Tokens Securely
JWT storage should be selected according to the application's architecture and threat model. Browser-accessible storage can expose tokens to client-side attacks such as cross-site scripting (XSS), while cookies introduce different considerations, including cross-site request forgery (CSRF).
Use HTTPS to protect tokens during transmission and apply appropriate cookie protections when cookies are used, such as Secure, HttpOnly, and suitable SameSite settings. Avoid exposing tokens through URLs, unnecessary logs, browser history, or other locations where they can be unintentionally disclosed.
6. Enforce Algorithm Allowlisting
Applications should define an explicit allowlist of cryptographic algorithms that each JWT validation context accepts. Never let the token's alg header independently determine which algorithm the server uses for verification. Unexpected or unsupported algorithms should be rejected.
Algorithm allowlisting helps prevent algorithm confusion and unexpected unsecured-token attacks. The accepted algorithm should match the key type and application's trust model. Validation rules should also remain consistent across services so that the same token cannot be interpreted differently by different components.
7. Rotate Signing Keys Regularly
Regular signing key rotation limits the impact of a compromised JWT signing key. Establish a defined rotation process that replaces keys before they become unnecessarily exposed while ensuring valid tokens can still be verified during the transition period.
Use secure key-management systems rather than hardcoding production keys in application code or configuration files. Maintain appropriate key identifiers and verification-key distribution mechanisms and remove retired keys only after the tokens and systems that depend on them no longer require verification.
8. Implement Token Revocation
JWTs do not automatically provide token revocation after issuance. If a token is stolen, simply deleting a client-side copy does not necessarily invalidate the token. Applications should therefore design explicit session and token invalidation controls.
Depending on the architecture, revocation can involve short-lived access tokens, refresh-token rotation, server-side token status checks, session identifiers, or deny lists for compromised tokens. High-risk applications should also define procedures for responding to credential compromise, logout, account recovery, and other security events.
9. Test JWT Security End-to-End
JWT security testing should verify the complete token validation and authorization process, not just whether a token has a valid signature. Test how the application handles modified tokens, unexpected algorithms, invalid signatures, expired tokens, and malformed claims.
Include tests for incorrect iss and aud values, nbf boundaries, token reuse, token-type confusion, key rotation, revocation, and authorization decisions. Test protected APIs and alternate application paths as well, because inconsistent JWT validation across endpoints can create exploitable security gaps.
Have questions about securing your JWT implementation at scale? Our security team is ready to help. Contact Us
To Wrap Up
JWTs provide a compact way to carry claims between trusted parties, but the format itself does not guarantee security. Strong protection depends on correct cryptographic validation, trusted key management, and application-specific claim verification.
A secure implementation should allow only expected algorithms, verify signatures, validate claims such as iss, aud, and exp, and use strong signing keys. Tokens should also have appropriate lifetimes and contain only necessary information.
Token handling is equally important. HTTPS, secure storage, refresh-token protection, revocation strategies, and clear token-type validation help reduce exposure when tokens are compromised. These controls should reflect the application's architecture and threat model.
JWT security should also be tested continuously across authentication and authorization flows. Testing modified tokens, invalid claims, algorithm changes, token reuse, key rotation, and revoked sessions helps identify weaknesses before attackers can exploit them.
If you want to check whether your web app and APIs are secure and resilient against real-world attacks, sign up with ZeroThreat and run a free scan to verify.
Frequently Asked Questions
What are the different types of JWT?
JWT is a token format, not a classification such as access, ID, or refresh token. JWTs are commonly implemented as JWS for integrity and authentication, or JWE when encryption and confidentiality are required. Access and ID tokens may use JWTs, while refresh tokens do not have to be JWTs.
What are the risks of JWT authentication?
Is JWT enough for security?
Can a JWT token be stolen?
Are JWTs encrypted?
How do you validate a JWT securely?
Explore ZeroThreat
Automate security testing, save time, and avoid the pitfalls of manual work with ZeroThreat.


