Menu
dev 10 min read |

JWT Structure Explained: Header, Payload, and Signature

In the modern era of web development, securing communication between clients and servers is paramount. JSON Web Tokens (JWT) have emerged as the industry standard for representing claims securely between two parties. Whether you are building a single-page application (SPA), a mobile app, or a microservices architecture, understanding how JWTs work is essential for implementing robust authentication and authorization.

While many developers use libraries to handle JWTs, a deep understanding of their internal structure allows for better debugging, security auditing, and architectural decisions. In this comprehensive guide, we will break down the three parts of a JWT, explain the authentication flow, and discuss security best practices.

What is a JSON Web Token (JWT)?

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.

The "self-contained" nature of JWTs is their biggest advantage. They carry all the necessary information about a user, which means the server doesn't need to query a database to verify the user's identity on every request. This makes JWTs ideal for distributed systems and horizontal scaling.

Common use cases include:

  • Authorization: The most common scenario for using JWT. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token.
  • Information Exchange: JWTs are a good way of securely transmitting information between parties. Because JWTs can be signed—for example, using public/private key pairs—you can be sure that the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn't been tampered with.

The Three Parts of a JWT

In its compact form, a JSON Web Token consists of three parts separated by dots (.), which are:

  • Header
  • Payload
  • Signature

Therefore, a JWT typically looks like the following:

xxxxx.yyyyy.zzzzz

Let's break down each part to see what they contain and how they are encoded. If you ever need to inspect a real token, you can use our JWT Decoder to see exactly what is inside.

Part 1: The Header

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.

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

Then, this JSON is Base64Url encoded to form the first part of the JWT. It is important to note that Base64Url encoding is not encryption; it is simply a way to represent binary-like data in a URL-friendly string format.

The alg (algorithm) field is critical. It tells the recipient how to verify the signature. However, this field has been the source of many security vulnerabilities in the past (such as the "none" algorithm attack), which is why modern libraries require you to explicitly define the expected algorithms during verification.

Part 2: The Payload (Claims)

The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional data. There are three types of claims: registered, public, and private claims.

  • Registered claims: These are a set of predefined claims which are not mandatory but recommended, to provide a set of useful, interoperable claims. Some of them are: iss (issuer), exp (expiration time), sub (subject), aud (audience), and others.
  • Public claims: These can be defined at will by those using JWTs. But to avoid collisions they should be defined in the IANA JSON Web Token Registry or be defined as a URI that contains a collision resistant namespace.
  • Private claims: These are the custom claims created to share information between parties that agree on using them and are neither registered or public claims.

An example payload might look like this:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true,
  "iat": 1516239022,
  "exp": 1516242622
}

The payload is then Base64Url encoded to form the second part of the JSON Web Token. You can use our JWT Decoder to quickly extract these claims from any token you encounter during development.

Part 3: The Signature

To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.

For example if you want to use the HMAC SHA256 algorithm, the signature will be created in the following way:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

The signature is used to verify that the message wasn't changed along the way, and, in the case of tokens signed with a private key, it can also verify that the sender of the JWT is who it says it is. This is the most critical part of the JWT, as it provides the integrity guarantee.

How JWT Authentication Works (The Flow)

The typical flow for JWT-based authentication follows these steps:

  1. Login Request: The client sends their credentials (e.g., username and password) to the server.
  2. Token Generation: The server validates the credentials and, if they are correct, creates a JWT. The server signs the JWT using a secret key or a private key.
  3. Token Response: The server sends the JWT back to the client.
  4. Storage: The client stores the token, usually in localStorage or a HttpOnly cookie.
  5. Subsequent Requests: For every request to a protected resource, the client sends the JWT in the Authorization header using the Bearer schema: Authorization: Bearer <token>.
  6. Verification: The server receives the request, extracts the token, and verifies its signature using the secret or public key. If the signature is valid and the token hasn't expired, the server grants access to the requested resource.

This flow removes the need for the server to maintain a session state in memory (or a database/Redis) for every user, which significantly reduces the overhead on the server side and enables better scalability.

Security Best Practices: Why You Shouldn't Store Secrets in JWT

A common misconception among developers is that JWTs are a secure way to hide sensitive data. This is false. Unless you are using JSON Web Encryption (JWE), the payload of a JWT is only Base64Url encoded, not encrypted.

Anyone who intercepts the token can easily decode the payload and read the information inside. Therefore, you should never store passwords, social security numbers, or other sensitive secrets in the payload. To ensure you are using strong secrets for your signing process, you can use our Password Generator to create high-entropy keys.

Key security tips:

  • Always use HTTPS: To prevent Man-in-the-Middle (MITM) attacks from stealing your tokens.
  • Keep it short: Set a short expiration time (exp claim) to minimize the window of opportunity for an attacker if a token is stolen.
  • Use HttpOnly Cookies: If you are storing JWTs in the browser, using HttpOnly and Secure flags on cookies helps protect against Cross-Site Scripting (XSS) attacks.
  • Validate the Algorithm: Don't blindly trust the alg header. Hardcode the expected algorithm in your verification logic.

JWT vs. Session Cookies: Key Differences

Choosing between JWT and traditional session cookies depends on your application's requirements. Here is a comparison:

Feature Session Cookies JSON Web Tokens
State Stateful (stored on server) Stateless (stored on client)
Scalability Harder (requires sticky sessions or shared store) Easier (completely independent)
Revocation Easy (delete from server) Hard (requires a blacklist or short expiry)
Size Small (just a session ID) Large (contains all claims)

Common JWT Algorithms (HS256 vs RS256)

There are two primary types of signing algorithms used with JWTs: symmetric and asymmetric.

HS256 (HMAC with SHA-256) is a symmetric algorithm, meaning the same secret key is used to both sign and verify the token. It is simple to implement but requires both the issuer and the consumer to share the secret securely.

RS256 (RSA Signature with SHA-256) is an asymmetric algorithm, meaning it uses a private key to sign the token and a public key to verify it. This is more secure for scenarios where the service issuing the token is different from the service consuming it (e.g., OAuth2 providers like Google or Auth0).

Algorithm Type Key Requirements Best For
HS256 Symmetric One shared secret key Internal apps, small teams
RS256 Asymmetric Private key (sign), Public key (verify) Microservices, Public APIs, Identity Providers

Conclusion

JSON Web Tokens offer a powerful and flexible way to handle authentication in modern web applications. By understanding the three-part structure—Header, Payload, and Signature—developers can build systems that are both scalable and secure. However, it is vital to remember that JWTs are tools for integrity and authentication, not secrecy.

When implementing JWTs, always prioritize security by using strong signing keys, enforcing HTTPS, and keeping payloads lean. Whether you are debugging a token with our JWT Decoder or generating a new secret with our Password Generator, having the right tools and knowledge is the first step toward building great software.