MagicTools
developerApril 22, 202611 views8 min read

Complete Guide to JWT Authentication: Principles, Usage, and Security Best Practices

After you log in to a web application, how does the server know that each subsequent request is made by "you"? HTTP is a stateless protocol, and each request is inherently independent, with no "memory". There are two mainstream solutions to this problem: Session Token and JWT.

JWT (JSON Web Token) has almost become the standard choice in the REST API field in recent years, widely adopted by mainstream platforms such as GitHub, Auth0, and Google. This article systematically explains everything about JWT from principles to practice.


What is JWT?

JWT is a compact, self-contained token format used to securely transmit JSON-formatted claims information between parties.

"Self-contained" is a core feature of JWT: the token itself carries user information and verification information, allowing the server to verify the token's legitimacy without querying the database. This makes JWT naturally suitable for stateless distributed architectures.

Detailed Structure of JWT

A JWT consists of three parts, separated by .:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IuW8oOS4iSIsImlhdCI6MTUxNjIzOTAyMn0
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Part 1: Header

After Base64URL decoding:

{
  "alg": "HS256",
  "typ": "JWT"
}
  • alg: Signature algorithm (HS256, RS256, ES256, etc.)
  • typ: Token type, fixed as JWT

Part 2: Payload

After Base64URL decoding:

{
  "sub": "1234567890",
  "name": "张三",
  "email": "zhangsan@example.com",
  "role": "admin",
  "iat": 1516239022,
  "exp": 1516325422
}

Payload contains "claims", divided into three categories:

Registered Claims:

Field Full Name Meaning
sub Subject Token subject (usually user ID)
iss Issuer Token issuer
aud Audience Token audience (target service)
exp Expiration Time Expiration time (Unix timestamp)
iat Issued At Issuance time
nbf Not Before Effective time (invalid before)

Custom Claims: Any fields required by the business can be added, such as role, email, permissions, etc.

⚠️ Important Warning: Payload is Base64URL encoded, not encrypted! Anyone can decode and view the content. Never store sensitive data like passwords or credit card numbers in the Payload.

Part 3: Signature

The signature calculation method:

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

Taking HS256 as an example, the server uses a secret known only to itself to perform HMAC-SHA256 hash operation on the first two parts to generate the signature.

Verification Mechanism: When the server receives a request, it recalculates the signature using the same algorithm and compares it with the signature in the token. As long as the secret is not leaked, anyone who tampers with the Header or Payload will have a mismatched signature—because they don't have the secret and cannot generate a valid signature.

JWT vs Session Token Comparison

Dimension JWT Session Token
Storage Location Client-side Server-side (Database/Redis)
Server State Stateless Stateful
Scalability Naturally supports horizontal scaling Requires session sharing (Redis)
Logout Implementation Difficult (requires blacklist mechanism) Simple (delete server-side session)
Performance Verification requires no DB query Requires query to session storage each time
Token Size Larger (typically 500B~2KB) Very small (only session ID)
Security Cannot revoke before expiration (default) Can revoke immediately
Applicable Scenarios Distributed, microservices, APIs Traditional web applications

Complete JWT Usage Flow

1. 用户登录(POST /auth/login,发送账号密码)
         ↓
2. 服务端验证凭据,生成 JWT
   - Header: { alg: "HS256", typ: "JWT" }
   - Payload: { sub: "user_123", role: "admin", exp: now+7days }
   - 用 secret 签名
         ↓
3. 服务端返回 JWT 给客户端
         ↓
4. 客户端存储 JWT(LocalStorage 或 Cookie)
         ↓
5. 客户端每次请求携带 JWT
   Authorization: Bearer <token>
         ↓
6. 服务端验证 JWT
   - 检查签名是否合法
   - 检查 exp 是否过期
   - 从 Payload 提取用户信息,处理业务逻辑

Server-side JWT generation code example (Node.js):

import jwt from 'jsonwebtoken';

// 生成 JWT
function generateToken(userId, role) {
  return jwt.sign(
    {
      sub: userId,
      role: role,
    },
    process.env.JWT_SECRET,
    {
      expiresIn: '7d',    // 7 天过期
      issuer: 'myapp.com',
    }
  );
}

// 验证 JWT(中间件)
function verifyToken(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader?.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Missing token' });
  }

  const token = authHeader.slice(7);
  try {
    const payload = jwt.verify(token, process.env.JWT_SECRET);
    req.user = payload;
    next();
  } catch (err) {
    return res.status(401).json({ error: 'Invalid or expired token' });
  }
}

Security Analysis of Token Storage Locations

This is one of the most controversial topics in JWT:

localStorage / sessionStorage

// 存储
localStorage.setItem('token', jwt);

// 使用
const token = localStorage.getItem('token');
fetch('/api/data', {
  headers: { Authorization: `Bearer ${token}` }
});

Advantages: Simple and direct, cross-subdomain access Disadvantages: Risk of XSS attacks—if the page has an XSS vulnerability, attackers can read the token from localStorage via injected scripts

// 服务端设置 Cookie(Node.js/Express)
res.cookie('access_token', jwt, {
  httpOnly: true,   // JavaScript 无法读取,防 XSS
  secure: true,     // 仅 HTTPS 传输
  sameSite: 'strict', // 防 CSRF
  maxAge: 7 * 24 * 60 * 60 * 1000, // 7 天
});

Advantages: JavaScript cannot read (prevents XSS), browser automatically carries it Disadvantages: Requires handling CSRF (use sameSite: 'strict' or CSRF token protection); not suitable for mobile apps

Conclusion: For web applications, prioritize HttpOnly cookies; for mobile apps or third-party API clients, use localStorage (while strictly guarding against XSS).

Security Precautions

1. Set Reasonable Expiration Times

// Access Token:短生命周期(15分钟~1小时)
jwt.sign(payload, secret, { expiresIn: '15m' });

// Refresh Token:较长生命周期(7~30天),存储在服务端
jwt.sign({ sub: userId }, refreshSecret, { expiresIn: '30d' });

2. Refresh Token Mechanism

Set short expiration for Access Token, use Refresh Token to obtain new Access Token, balancing security and user experience:

Access Token 过期(返回 401)
         ↓
客户端用 Refresh Token 请求 /auth/refresh
         ↓
服务端验证 Refresh Token(查数据库,确认未被吊销)
         ↓
返回新的 Access Token(+ 可选:轮换 Refresh Token)

3. Use HTTPS

JWT is transmitted in plaintext in the header; without HTTPS, it's exposed.

4. Beware of Algorithm Confusion Attacks (alg: none vulnerability)

Early JWT libraries had serious vulnerabilities: attackers modified the alg in the header to none, causing the library to skip signature verification.

// 攻击者篡改的 Header
{ "alg": "none", "typ": "JWT" }

Protection: Use the latest version of JWT libraries; explicitly specify allowed algorithms during verification:

// ✅ 显式指定算法,拒绝其他算法
jwt.verify(token, secret, { algorithms: ['HS256'] });

5. Choosing Between HS256 and RS256

HS256 RS256
Algorithm HMAC-SHA256 (symmetric) RSA-SHA256 (asymmetric)
Signature Key Single secret Private key for signing / Public key for verification
Verification Method Requires holding the secret Only requires public key, which can be public
Suitable Scenarios Single service, internal systems Microservices, third-party verification (e.g., Auth0)

FAQ

Q: Can JWT be logged out?

This is an inherent limitation of JWT. Since JWT is stateless, the server by default does not maintain token state, and the token remains valid until exp expires. There are two solutions for logout:

  1. Token Blacklist: When logging out, store the token's jti (JWT ID) in Redis, and check the blacklist during verification. Disadvantage: Introduces state, increases Redis queries, partially negating JWT's stateless advantage.
  2. Short Expiration + Refresh Token Rotation: Access Token expires in 15 minutes; when logging out, revoke the Refresh Token (delete on server), so the user can still access for up to 15 minutes but cannot renew. This is the most commonly used compromise in the industry.

Q: What is the relationship between JWT and OAuth?

OAuth 2.0 is an authorization framework that defines how clients obtain access permissions (authorization code flow, client credentials flow, etc.). JWT is a token format. They are concepts from different dimensions and can be used together: the Access Token issued by OAuth 2.0 can be in JWT format (e.g., Auth0, Google's implementation) or a random string (e.g., GitHub's Personal Access Token). Simply put: OAuth defines "how to get the token", JWT defines "what the token looks like".

Q: How to choose between HS256 and RS256?

If you have a monolithic application or internal service, choose HS256: simple implementation, high performance, manage one secret.

If your architecture is microservices, or you need third-party services to verify your token (e.g., partner systems), choose RS256: the authentication service holds the private key for signing, and other services only need the public key to verify, without sharing private information, which is more secure. IdPs like Auth0, Google, and Apple use RS256/ES256.

Summary

JWT is essentially a design that "embeds user state into the token"—it sacrifices the ability for "real-time revocation" in exchange for the horizontal scalability brought by stateless verification.

Remember these three core principles:

  1. Do not put sensitive data in Payload (Base64 is not encryption)
  2. Short expiration for Access Token + Refresh Token mechanism (balance security and experience)
  3. Store in HttpOnly cookies on the web (first line of defense against XSS)

Choose JWT in suitable scenarios; for scenarios requiring real-time revocation (e.g., government, finance), consider stateful solutions like Session + Redis—there is no silver bullet, only the right tool.

Related Articles

Tmux Terminal Multiplexer: Recommended Configuration + Complete User Manual

A complete guide to the tmux terminal multiplexer for developers, including recommended .tmux.conf configuration, common shortcut key cheat sheets, plugin recommendations, and practical tips to help you significantly improve terminal efficiency.

developerApr 22, 20267 min
6

Practical Guide to Document Format Conversion: Comprehensive Analysis of Markdown, HTML, PDF Interconversion

Comprehensive analysis of conversion methods for four major document formats: Markdown, HTML, PDF, and Word, comparing the pros and cons of various conversion tools, with practical steps and solutions to common problems, helping you choose the most suitable conversion path for different scenarios.

documentApr 22, 20268 min
6

Complete Guide to Password Security: Best Practices from Creation to Management

Every year, billions of accounts are stolen due to weak passwords or password reuse. This article systematically explains common password attack methods, password strength standards, password manager selection, and the correct use of two-factor authentication, helping you fundamentally protect your digital asset security.

utilityApr 22, 20267 min
12
Crayfish (OpenClaw) Workbench Dashboard

Crayfish (OpenClaw) Workbench Dashboard

Crayfish has strong execution capabilities, but there's no good sense of control over what it has done and what it's currently doing. I happened to see a blogger's share, so we can first build a 'Mission Control' to achieve full control!

openclawApr 22, 20264 min
11

Published by MagicTools