JWTの仕組み - トークンベース認証を理解しよう

12分 で読める | 2025.12.14

JWTとは

JWT(JSON Web Token、ジョットと読む)は、2つのシステム間で情報を安全にやり取りするためのコンパクトな形式です。RFC 7519で標準化されており、主にWebアプリケーションの認証・認可で使用されます。

JWTが解決する問題: 従来のセッションベース認証では、サーバー側でセッション情報を保持する必要がありました。JWTを使うと、サーバーはステートレスになり、スケーラビリティが向上します。

JWTの構造

JWTは3つのパートから構成され、それぞれがBase64URLエンコードされ、ドット(.)で連結されています。

xxxxx.yyyyy.zzzzz
  ↓      ↓      ↓
Header.Payload.Signature

1. Header(ヘッダー)

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

2. Payload(ペイロード)

{
  "sub": "1234567890",
  "name": "田中太郎",
  "iat": 1705234800,
  "exp": 1705238400
}

3. Signature(署名)

ヘッダーとペイロードを秘密鍵で署名したものです。

重要: JWTのペイロードはBase64URLエンコードされているだけで、暗号化されていません。機密情報をペイロードに含めないでください。

アクセストークンとリフレッシュトークン

種類アクセストークンリフレッシュトークン
用途APIアクセス認証アクセストークンの更新
有効期限短い(15分〜1時間)長い(7日〜30日)
保存場所メモリ、または短命CookieHttpOnly Cookie

セキュリティベストプラクティス

  1. 適切な有効期限を設定する
  2. 強力な秘密鍵を使用する
  3. アルゴリズムを明示的に指定する
  4. HttpOnly Cookieで保存する
  5. センシティブな情報を含めない

実装例

Node.js での JWT生成と検証

import jwt from 'jsonwebtoken';

const SECRET_KEY = process.env.JWT_SECRET!;
const REFRESH_SECRET = process.env.JWT_REFRESH_SECRET!;

// トークン生成
function generateTokens(userId: string, role: string) {
  const accessToken = jwt.sign(
    { sub: userId, role },
    SECRET_KEY,
    { expiresIn: '15m' }
  );

  const refreshToken = jwt.sign(
    { sub: userId, type: 'refresh' },
    REFRESH_SECRET,
    { expiresIn: '7d' }
  );

  return { accessToken, refreshToken };
}

// トークン検証
function verifyAccessToken(token: string) {
  try {
    return jwt.verify(token, SECRET_KEY);
  } catch (error) {
    if (error instanceof jwt.TokenExpiredError) {
      throw new Error('TOKEN_EXPIRED');
    }
    throw new Error('INVALID_TOKEN');
  }
}

現場で遭遇するJWTの問題と対策

よくある実装ミス

  1. 秘密鍵のハードコード

環境変数やシークレット管理サービス(AWS Secrets Manager等)を必ず使用してください。

  1. アルゴリズムの未指定

jwt.verify() でアルゴリズムを明示しないと、攻撃者が "alg": "none" を使う脆弱性につながります。

// 危険
jwt.verify(token, secret);

// 安全
jwt.verify(token, secret, { algorithms: ['HS256'] });
  1. トークン失効の未対応

パスワード変更時やログアウト時にトークンを無効化する仕組み(ブラックリスト/バージョニング)が必要です。

トークンローテーションの実装

// リフレッシュトークン使用時に新しいペアを発行
async function refreshTokens(refreshToken: string) {
  const payload = jwt.verify(refreshToken, REFRESH_SECRET);

  // 古いリフレッシュトークンを無効化
  await invalidateToken(refreshToken);

  // 新しいトークンペアを生成
  return generateTokens(payload.sub, payload.role);
}

関連記事

認証・認可をさらに深く学ぶために:

まとめ

JWTは、ステートレスな認証を実現する強力なツールです。構造を理解し、適切に実装することで、セキュアでスケーラブルな認証システムを構築できます。

特にアルゴリズムの明示指定、適切な有効期限設定、トークンローテーションの実装は、本番環境では必須の対策です。

← 一覧に戻る