← Back to archive

Development · Network

Understanding JWT authentication

How cookies, sessions, and JWTs handle authentication, with a look at token structure, tradeoffs, and security considerations.

Read the Korean original on Velog ↗English translation

Development archive cover

When learning how applications keep users signed in, cookies, sessions, and JWTs often appear together. They are not direct replacements for one another: they divide storage and verification responsibilities differently. Understanding those differences is a useful starting point.

Cookies and sessions

HTTP is stateless. Cookies and sessions let web applications maintain information about a user across requests.

Cookies

A cookie is a small piece of data stored in the browser. It can hold information such as a session ID or a language preference.

Sessions

A session stores user information on the server. The server creates a unique session ID and sends it to the client, commonly in a cookie. The client includes that ID in later requests so the server can identify the session.

The request–response flow

  1. The server creates a session ID when the client establishes a session.
  2. The server returns the ID in a cookie with its response.
  3. The client sends the cookie with subsequent requests.
  4. The server looks up the session and returns the appropriate response.

How cookies and sessions differ

  • Cookies store data on the client; sessions store data on the server, often using a cookie to carry the session ID.
  • Reading client-side cookie data does not require a session lookup. Server-side sessions add processing and storage work.
  • Client-side data can be altered or exposed, so it should not be trusted without validation.
  • With a session, the browser stores an identifier rather than all the session data. Protecting that identifier is still essential.
  • Persistent cookies can remain after the browser closes, until their expiration time.
  • Session cookies normally last for the browser session. The lifetime of the server-side session is managed separately.

Session storage has a cost Sessions consume server resources. Creating or retaining too many can increase memory use.

Limitations of cookie-based sessions

  • More active users require more server-side session storage.
  • Cookies travel in request headers, adding network overhead.
  • If an attacker steals a session ID, they may be able to impersonate the user. This is known as session hijacking.
  • Server-side sessions introduce state that must be managed, even though HTTP itself is stateless.

Where JWT fits

JWT stands for JSON Web Token. It is a standardized way to represent claims, often used in authentication. A signed JWT carries information that a recipient can verify without relying solely on a session lookup.

JWT structure

A signed JWT commonly has three parts: a header, a payload, and a signature. They form a string in the format header.payload.signature.

Header

The header contains metadata, including the token type and the signing algorithm.

typ: type

Identifies the token type, commonly JWT.

alg: algorithm

Identifies the algorithm used to sign the token.

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

Payload

The payload contains claims: information such as the user's identity or permissions.

Registered claims

These claim names are defined by the JWT standard.

  • iss: issuer
  • sub: subject
  • aud: audience
  • exp: expiration time
  • nbf: the time before which the token must not be accepted
  • iat: issued-at time
  • jti: JWT identifier

Public claims

Public claim names should avoid collisions. They can be registered in the IANA JSON Web Token registry or use a collision-resistant name.

Private claims

Private claims are agreed upon by the parties exchanging the token and carry information specific to their application.

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

Signature

The signature protects the integrity of the header and payload. In the HMAC example below, the server generates it using a shared secret.

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

The JWT authentication flow

  1. The user submits a username and password.
  2. The server checks the credentials and creates a JWT.
  3. The server returns the token, and the client stores it.
  4. The client includes the token in the Authorization header of subsequent requests.
  5. The server verifies the signature and checks claims such as expiration. It rejects invalid tokens.
  6. If the token is valid, the server provides access according to the user's permissions.

When an access token expires The client can use a refresh token to request a new access token. The server validates the refresh token before issuing a replacement.

Advantages of JWTs

A client can store the token, and the server can verify it without maintaining a separate session record for every access token. Signature verification detects changes to the signed content. Tokens can also support authentication between clients and APIs on different domains.

Limitations of JWTs

Encoded claims make JWTs larger than typical session IDs. A signed JWT's payload is encoded, not encrypted, so it should not contain secrets. A stolen access token may remain usable until it expires unless the application has a way to revoke it.

Further reading: JWT specification: RFC 7519.

← Back to archive