What is a JWT and Why Does It Matter?
JSON Web Token (JWT, pronounced "jot") is an open standard for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed using a secret or a public/private key pair.
JWTs have become the de facto standard for modern web authentication, API authorization, and information exchange. They are stateless, compact, URL-safe, and work seamlessly across different platforms and programming languages. Whether you are building a single-page application, a mobile app, or a microservices architecture, chances are you will encounter JWTs.
The appeal of JWTs lies in their self-contained nature. A single token carries not only identity information but also metadata about itself — its issuer, its expiration time, the algorithm used for signing, and custom claims relevant to your application. This means servers do not need to query a database or session store on every request; everything they need is right there in the token.
- Authentication: The most common use case, enabling single sign-on
- Authorization: Controlling access to APIs and protected resources
- Information exchange: Securely transmitting data between services
- Stateless sessions: Server-side scalability without session stores
The Three Parts of a JWT
A JSON Web Token consists of three parts separated by dots: the Header, the Payload, and the Signature. The token looks like a string of random characters, but each section has a specific meaning and structure.
The Header typically contains two fields: the type of token (typ), which is JWT, and the signing algorithm (alg) being used, such as HS256, RS256, or ES256. This header is Base64Url encoded to form the first part of the token.
The Payload is the second part and contains the claims. Claims are statements about an entity (typically the user) and additional metadata. There are three types of claims: registered claims (like iss for issuer, exp for expiration time, sub for subject), public claims (custom but collision-resistant names), and private claims (custom claims agreed between parties). The payload is also Base64Url encoded.
The Signature is created by taking the encoded header, the encoded payload, a secret or private key, and the algorithm specified in the header, then signing them. The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message was not changed along the way.
It is crucial to understand that Base64Url encoding is not encryption. Anyone who intercepts a JWT can easily decode the header and payload. This is why you should never put sensitive information — such as passwords, credit card numbers, or health records — inside a JWT payload. The signature only ensures integrity and authenticity, not confidentiality.
How JWT Authentication Works
The typical JWT authentication flow begins when a user logs in with their credentials. The server validates the credentials, then creates a JWT containing information about the user (user ID, role, permissions, etc.) and signs it with a secret key or private key. The server sends this token back to the client.
The client stores the token — usually in localStorage, sessionStorage, or an HttpOnly cookie — and includes it in the Authorization header of subsequent requests using the Bearer schema. The server then verifies the token signature on each request. If the signature is valid and the token has not expired, the server trusts the claims inside and processes the request accordingly.
One of the key benefits of this approach is statelessness. Since the token contains all the information needed for authentication, the server does not need to look up session data in a database on every request. This makes horizontal scaling much easier: you can add more server instances without worrying about session affinity or shared session stores.
However, statelessness also introduces challenges. Because the server does not track tokens, it cannot easily revoke a specific token if it is compromised. The token will remain valid until it expires, unless you implement additional mechanisms like token blacklists or short-lived access tokens paired with refresh tokens.
Common Security Vulnerabilities
Despite their popularity, JWTs are often misused, leading to serious security vulnerabilities. Understanding these pitfalls is essential for any developer working with JWT-based authentication.
One of the most well-known JWT vulnerabilities is the "none algorithm" attack. Some JWT libraries will accept tokens with the algorithm set to "none", meaning no signature verification at all. An attacker can craft a token with any payload they want, set the algorithm to "none", and gain unauthorized access. Always ensure your JWT library rejects tokens with the "none" algorithm and that you explicitly specify which algorithms you accept.
Algorithm confusion is another dangerous attack. If a server supports both symmetric (HS256) and asymmetric (RS256) algorithms, an attacker might take a token signed with RS256 and re-sign it with HS256 using the public key as the secret. If the server does not properly validate that the algorithm in the header matches the expected algorithm, the forged token will be accepted. The fix is simple: always verify that the algorithm in the token header matches the algorithm you expect to use.
Weak signing keys are a common mistake, especially with HMAC algorithms. If your secret key is short or easily guessable, an attacker who obtains a token can brute-force the key offline and then forge arbitrary tokens. Use long, randomly generated secrets (at least 256 bits for HS256) and protect them as you would any other credential.
Other issues include missing signature verification (surprisingly common in poorly implemented systems), not checking token expiration, not validating the issuer and audience claims, and storing tokens in insecure locations vulnerable to XSS attacks.
- Never accept the "none" algorithm
- Verify the algorithm matches expectations (prevent algorithm confusion)
- Use strong, randomly generated signing keys
- Always validate exp, iss, and aud claims
- Store tokens securely to prevent XSS and CSRF attacks
- Use short-lived access tokens with refresh tokens
Best Practices for JWT Security
Implementing JWTs securely requires attention to detail at every step — from token creation to storage, verification, and revocation. Following established best practices will help you avoid the most common security mistakes.
Choose the right signing algorithm for your use case. If you have a single server issuing and verifying tokens, HMAC with SHA-256 (HS256) is simple and secure as long as you use a strong secret. If you have multiple services or a distributed system where the issuer and verifier are different, consider using RSA (RS256) or ECDSA (ES256) with public/private key pairs. Only the issuer needs the private key; verifiers only need the public key.
Keep payloads small. Every byte in the payload contributes to the total token size, and since tokens are sent with every request, large tokens increase bandwidth usage and can hit size limits (for example, some servers reject headers larger than 8KB). Include only essential claims in the access token and fetch additional user data from your API when needed.
Set appropriate expiration times. Short-lived access tokens (15 minutes to 1 hour) limit the window of opportunity if a token is compromised. Pair them with refresh tokens (which can have longer lifetimes) so users do not have to log in constantly. Implement token rotation and revocation for refresh tokens to maintain security.
Validate everything. Do not just check the signature. Verify that the issuer (iss) is who you expect, that the audience (aud) includes your service, and that the token is within its valid time window (check both exp and nbf if present). Reject any token that fails any of these checks.
JWT Parser Tools and Debugging
When working with JWTs, a reliable parser tool is indispensable. You will frequently need to inspect the contents of a token during development, debugging, or incident response. A good JWT parser shows you the decoded header and payload in a human-readable format, highlights timestamp-based claims with their human-readable equivalents, and lets you examine the signature part.
Our JWT Parser tool works entirely in your browser, meaning the token you paste never leaves your computer. This is important from a security perspective — you should never paste production tokens into untrusted online tools, as those tools might log or store them. A client-side parser eliminates this risk entirely.
The parser can help you debug common issues. If a token is not being accepted, paste it into the parser and check: Is it properly formatted with three dot-separated parts? Does the header specify the algorithm you expect? Is the token expired or not yet valid according to the exp and nbf claims? Does the payload contain the expected claims?
Remember that a parser cannot verify the signature of a JWT without knowing the secret key or public key. Parsing and verifying are two different operations. Always verify the signature on the server side before trusting any token. The parser is a development and debugging aid, not a security verification tool.