2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【認証・認可】JWT(JSON Web Token)の仕組みを理解する

Posted at

はじめに

Webアプリケーションの認証において、JWT(JSON Web Token) は今や欠かせない技術となっています。従来のセッションベース認証と比べて、ステートレスでスケーラブルな認証が実現できるため、APIやマイクロサービスアーキテクチャで広く採用されています。

この記事では、JWTの基本的な仕組みから、安全に実装するためのベストプラクティスまでを解説します。

image.png

この記事で学べること

  • JWTの構造と仕組み
  • 認証フローの全体像
  • セキュリティのベストプラクティス

対象読者

  • Web開発の基礎知識がある方
  • 認証・認可の仕組みに興味がある方
  • JWTを安全に実装したいエンジニア

JWTとは何か?

JWT(JSON Web Token) は、当事者間で情報を安全に伝達するためのオープン標準(RFC 7519)です。トークン自体に情報(クレーム)を含むため、サーバー側でセッション情報を保持する必要がありません。

従来のセッション認証との比較

項目 セッション認証 JWT認証
サーバー側の状態 セッション情報を保持(ステートフル) 保持しない(ステートレス)
スケーラビリティ サーバー間でセッション共有が必要 各サーバーで独立して検証可能
通信量 セッションIDのみ(軽量) トークン全体(やや大きい)
無効化 サーバー側で即座に可能 追加の仕組みが必要

JWTの構造を理解する

JWTは**ドット(.)**で区切られた3つの部分で構成されています。

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

1. Header(ヘッダー)

トークンのタイプと署名アルゴリズムを指定します。

header.json
{
  "alg": "HS256",
  "typ": "JWT"
}
  • alg: 署名アルゴリズム(HS256, RS256など)
  • typ: トークンタイプ(通常は"JWT")

2. Payload(ペイロード)

実際のデータ(クレーム)を格納する部分です。

payload.json
{
  "sub": "1234567890",
  "name": "田中太郎",
  "iat": 1737705600,
  "exp": 1737712800
}

標準クレーム(Registered Claims)

クレーム 説明
iss 発行者(Issuer) "https://example.com"
sub 主題(Subject)、通常はユーザーID "user123"
aud 対象者(Audience) "https://api.example.com"
exp 有効期限(Expiration Time) 1737712800
nbf 有効開始時刻(Not Before) 1737705600
iat 発行時刻(Issued At) 1737705600
jti JWT ID(一意識別子) "abc123"

ペイロードはBase64エンコードされているだけで、暗号化されていません。誰でもデコードして内容を読めるため、パスワードや個人情報などの機密データは絶対に含めないでください。

3. Signature(署名)

トークンの改ざんを検出するための署名です。

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

署名により、トークンが改ざんされていないことを検証できます。

実際のトークン例

以下は実際のJWTトークンの例です:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IueUsOS4reeahOmDjiIsImlhdCI6MTczNzcwNTYwMH0.Kj8mQZvR3xPqYz5H7wLdN2fA9gC4yB6sT1eU0iM5hXo

これをデコードすると:

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

// Payload
{ "sub": "1234567890", "name": "田中太郎", "iat": 1737705600 }

JWTの認証フロー

基本的な認証フロー

Access Token と Refresh Token

セキュリティと利便性のバランスを取るため、2種類のトークンを使い分けます。

トークン 有効期限 用途
Access Token 短い(15分〜1時間) APIへのアクセス認証
Refresh Token 長い(7日〜30日) Access Tokenの再発行

Refresh Token Rotation(ローテーション) を実装すると、Refresh Token使用のたびに新しいものを発行することで、トークン漏洩時のリスクを軽減できます。

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

1. 署名アルゴリズムの選択

アルゴリズム 種類 用途
HS256 対称鍵(共通鍵) 単一サービス向け
RS256 非対称鍵(公開鍵/秘密鍵) マイクロサービス・複数サービス向け

alg: "none" は絶対に許可しない!
サーバー側で許可するアルゴリズムをホワイトリストで明示的に指定してください。攻撃者がヘッダーを "alg": "none" に書き換えて署名検証をバイパスする攻撃が存在します。

2. トークンの有効期限設定

// ❌ 悪い例:有効期限が長すぎる
const token = jwt.sign(payload, secret, { expiresIn: '365d' });

// ✅ 良い例:短い有効期限
const accessToken = jwt.sign(payload, secret, { expiresIn: '15m' });
const refreshToken = jwt.sign(payload, refreshSecret, { expiresIn: '7d' });

3. クレームの検証

トークン検証時は、署名だけでなく以下のクレームも必ず検証しましょう:

  • exp: 有効期限が切れていないか
  • iss: 信頼できる発行者か
  • aud: 正しい対象者か

まとめ

要点の振り返り

JWTは、ステートレスな認証を実現する強力なツールです。以下のポイントを押さえて安全に実装しましょう:

  1. 構造を理解する: Header, Payload, Signatureの3部構成
  2. 短い有効期限: Access Tokenは15分〜1時間程度に設定
  3. Refresh Tokenを活用: 利便性とセキュリティのバランスを取る
  4. アルゴリズムをホワイトリスト指定: noneアルゴリズム攻撃を防ぐ
  5. 機密情報は含めない: ペイロードは暗号化されていない
  6. HttpOnly Cookieに保存: XSS攻撃からトークンを保護

参考リンク

この記事は2026年1月時点の情報に基づいています。各ライブラリのバージョンや推奨設定は変更される可能性があるため、公式ドキュメントも併せてご確認ください。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?