aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Web Development

What Is JWT? How Token Authentication Works

When you build an API, sooner or later you run into one question: after a user logs in, how do I recognize them on every following request? The answer to what is JWT lives exactly here. A JWT (JSON Web Token) is like a self-contained ID card that the server creates, signs, and hands to the client. The client sends that card back on every request, and the server can check the signature and say "yes, this really is a token I issued" — without ever hitting the database.

What is JWT and why use it?

In classic session management, the server keeps a session record for every logged-in user and gives the client a session id. This works, but it requires the server to remember state. If you have more than one server, they all have to share the same session store.

JWT flips that around. The token itself carries the information about the user (who they are, their role, an expiry time) and is signed with the server's secret key. The server doesn't have to remember anything; it just verifies the incoming token's signature. That's why JWT is called stateless authentication, and it's exactly why it's so common in microservices, mobile apps, and APIs.

The three parts of a token

A JWT consists of three parts separated by dots: header.payload.signature. Each part is Base64Url encoded (encoded, not encrypted — an important distinction).

  • Header: States the token type and the signing algorithm used. Example: {"alg":"HS256","typ":"JWT"}.
  • Payload: Carries the so-called claims — for example the user id (sub), the expiry time (exp), the issued-at time (iat), and any fields you add yourself (like a role).
  • Signature: The header and payload signed with the secret key. This is the part that guarantees the token wasn't tampered with.

A real token looks like this:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiIxMjMiLCJyb2xlIjoiYWRtaW4iLCJleHAiOjE3MTk1MDAwMDB9
.s5_3kF9vQk2...signature

One crucial point: the payload is not encrypted. Anyone can decode and read Base64Url. So never put secrets like passwords or credit card numbers inside a token. A token carries "identity," not secrets.

How signing works

The signature is the heart of JWT's entire security model. With the HS256 algorithm (HMAC + SHA-256), the signature is computed like this:

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

When the server verifies a token, it repeats the exact same operation: it re-signs the incoming header and payload with its own secret key and compares the result with the signature in the token. If someone tries to flip the role in the payload from user to admin, the signature won't match, because the attacker doesn't have the secret key. That's why the token is "tamper-proof."

There are two signing approaches:

  • HS256 (symmetric): A single secret key both signs and verifies. Simple and fast, but anyone who can verify can also issue tokens.
  • RS256 (asymmetric): Signs with a private key, verifies with a public key. Ideal when several services must verify tokens but should not be able to issue them.

In practice: issuing and verifying a token

In Node.js, with the jsonwebtoken library, the flow looks very clean:

const jwt = require('jsonwebtoken');

// Issue a token after a successful login
const token = jwt.sign(
  { sub: user.id, role: user.role },
  process.env.JWT_SECRET,
  { expiresIn: '15m' }
);

// Verify it on following requests
try {
  const payload = jwt.verify(token, process.env.JWT_SECRET);
  // identify the user via payload.sub
} catch (err) {
  // invalid signature or expired
}

The client usually sends this token in the Authorization: Bearer <token> header. A middleware on the server reads that header on every request, verifies it, and attaches the user to the request.

The refresh token pattern

There's a tension here: you want the token to be short-lived (so the damage is limited if it's stolen), but forcing the user to log in again every 15 minutes is a bad experience. The solution is to use two tokens:

  • Access token: Short-lived (say 15 minutes). Sent on every API request.
  • Refresh token: Long-lived (say 7 days). Used only to obtain a new access token.

When the access token expires, the client sends the refresh token to the server and receives a fresh access token in return — the user notices nothing. The important security details:

  • You need to store the refresh token server-side (or keep a blocklist) so that "log out" can actually revoke it. A pure access token is stateless, so it stays valid until it expires.
  • Keeping the refresh token in an HttpOnly cookie in the browser prevents JavaScript from reading it and stealing it via XSS.
  • Issuing a new refresh token on every use and invalidating the old one (rotation) sharply reduces the risk of theft.

Common mistakes

  • Putting secrets in the payload: The payload is public, don't forget.
  • Not setting an expiry (exp): A token with no expiry stays valid forever once stolen.
  • Accepting alg: none: Configure your library to explicitly state which algorithms it will accept.
  • Hard-coding the secret: The key belongs in an environment variable (.env), not in the repo.

Frequently Asked Questions

Is a JWT encrypted?

No. By default a JWT is signed, not encrypted. Its contents are readable but cannot be altered. If you also need to hide the contents, JWE (JSON Web Encryption) is a separate standard — but in most cases the right move is simply to never put sensitive data in the token.

Where should I store the token?

There's no single perfect answer. localStorage is easy but exposed to XSS. An HttpOnly cookie is protected against XSS but requires a CSRF defense. In mobile apps, secure storage (Keychain/Keystore) is preferred.

Can I revoke a single JWT?

A pure JWT is stateless, so it can't be revoked directly; it stays valid until it expires. If you need revocation, you use the short-lived access token plus a server-side refresh token (blocklist) approach.

Getting authentication right is the foundation of a project's security. If you need help setting up JWT, a refresh token flow, or a secure API architecture in general, get in touch with me — let's lay a solid foundation together.

Bu kategorideki tüm yazılar →

Devamı için