JSON Web Tokens, commonly written as JWT and pronounced jot, are a compact and self-contained way of representing claims between two parties. They are used extensively in web authentication and authorization, particularly in APIs and single-page applications where the server needs to verify who is making a request without maintaining session state on the server side.
The appeal of JWTs is that they are stateless. The server does not need to store session data or look up a session ID in a database to validate a request. All the information needed to verify the token and identify the user is contained within the token itself. The server only needs the secret key or public key to verify the token's signature.
The structure of a JWT
A JWT consists of three Base64URL-encoded parts separated by dots. The three parts are the header, the payload and the signature. An example token looks like a long string of characters with two dots dividing it into three segments. Each segment can be decoded independently to read its contents.
The header contains the token type, which is JWT, and the algorithm used to sign the token. Common algorithms include HS256, which uses HMAC with SHA-256 and a shared secret, and RS256, which uses RSA with SHA-256 and a public/private key pair. The algorithm specified in the header tells the receiving party how to verify the signature.
The payload contains the claims. Claims are statements about an entity, typically the user, and additional data. Standard claims include the subject (the user identifier), the issuer (who created the token), the audience (who the token is intended for), the expiration time, and the issued-at time. Custom claims can include any additional information the application needs, such as the user's role, permissions, or other attributes.
The signature is produced by encoding the header and payload with Base64URL, concatenating them with a dot, and then signing the result using the algorithm and key specified in the header. The signature prevents tampering with the token contents. Changing any character in the header or payload invalidates the signature, so any modification is detectable by the verifying party.
What JWTs do not do
JWTs are signed, not encrypted. The payload is Base64URL encoded, which is an encoding not an encryption. Anyone who has the token can decode the header and payload and read their contents. This is by design because the purpose of the signature is to verify authenticity and integrity, not to protect confidentiality.
Do not put sensitive information like passwords, credit card numbers or personal identification numbers in a JWT payload. The information is readable by anyone who intercepts the token. If you need to include sensitive data in a JWT that travels over public networks, use JWE, JSON Web Encryption, instead of a plain JWT.
JWTs cannot be revoked without additional infrastructure. Because the server does not maintain state, a valid token signed with the correct key is accepted until it expires, even if the user has since logged out or had their account suspended. Applications that need immediate revocation capability typically maintain a token blacklist or use short expiration times combined with refresh token rotation.
Common JWT authentication flows
In a typical web application using JWT authentication, the user submits their credentials to the login endpoint. The server verifies the credentials, creates a JWT containing the user's identifier and any relevant claims, signs it with the server's secret key, and returns it to the client. The client stores the token, typically in memory or local storage, and includes it in the Authorization header of subsequent requests as a Bearer token.
The server receiving a request with a JWT in the Authorization header extracts the token, verifies the signature using its secret or public key, checks that the token has not expired, and extracts the claims from the payload to identify the user and their permissions. No database lookup is needed for the verification itself, only for any application data the handler needs afterward.
Access tokens typically have short expiration times, often 15 minutes to an hour, to limit the window of exposure if a token is stolen. Refresh tokens with longer expiration times are used to obtain new access tokens without requiring the user to log in again. The refresh token is stored more securely, typically in an httpOnly cookie, while the access token is used directly in API requests.
Debugging JWT issues
When JWT authentication fails, the error is often in the claims rather than the signature. An expired token produces a different error from an invalid signature, which produces a different error from a token with an incorrect audience claim. Decoding the token and examining the payload reveals the expiration time, the issuer, the audience and any custom claims, which makes it straightforward to identify which claim is causing the rejection.
Timezone issues frequently cause unexpected token expiration. JWT timestamps are Unix timestamps, which are UTC by default. If the server generating the token and the server validating it have different system times, or if either system's clock is significantly wrong, tokens may appear expired immediately or never expire correctly. Checking the iat and exp claims in a decoded token against the current UTC time identifies this class of problem quickly.
- Open the JWT Decoder below.
- Paste your JWT token into the input field.
- See the header, payload and signature decoded and formatted.
- Check the claims including expiration time and user details.
Decode and inspect any JWT token instantly to debug authentication issues.