ブログに戻る
セキュリティ10 min read

JWT認証:開発者ガイド

JSON Web Tokenでセキュアな認証を実装。JWT構造、セキュリティ考慮事項、ベストプラクティスを学習。

JWTとは?

JSON Web Token(JWT)は、パーティ間でJSONオブジェクトとして情報を安全に伝送するための コンパクトで自己完結型の方法を定義するオープンスタンダード(RFC 7519)です。 JWTはWebアプリケーションでの認証と情報交換に一般的に使用されます。

JWTの主要な利点

  • ステートレス: サーバーにセッションデータを保存する必要がない
  • コンパクト: 軽量で伝送効率が高い
  • 自己完結型: 必要な情報をすべて含んでいる
  • セキュア: デジタル署名で改ざんを防止
  • クロスドメイン: 異なるドメインやサービスで動作

JWT構造

JWTはドット(.)で区切られた3つの部分から構成されます:ヘッダー、ペイロード、署名。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

ヘッダー

アルゴリズムとトークンタイプを指定

1{
2  "alg": "HS256",
3  "typ": "JWT"
4}

ペイロード

クレーム(エンティティに関するステートメント)を含む

1{
2  "sub": "1234567890",
3  "name": "John Doe",
4  "iat": 1516239022,
5  "exp": 1516242622,
6  "role": "admin"
7}

署名

トークンが改ざんされていないことを検証

1HMACSHA256(
2  base64UrlEncode(header) + "." +
3  base64UrlEncode(payload),
4  secret
5)

JWT認証の動作原理

JWT認証フローは、クライアント、サーバー、保護されたリソース間のいくつかのステップを含みます。

1

ユーザーログイン

クライアントが認証サーバーに認証情報を送信

2

トークン生成

サーバーが認証情報を検証しJWTを作成

3

トークン返却

サーバーがJWTをクライアントに送信

4

後続リクエスト

クライアントがAuthorizationヘッダーにJWTを含める

5

トークン検証

サーバーがJWTを検証しリクエストを処理

実装例

ExpressでのNode.js(サーバーサイド)

1const jwt = require('jsonwebtoken');
2const bcrypt = require('bcrypt');
3
4// Login endpoint
5app.post('/login', async (req, res) => {
6  const { email, password } = req.body;
7  
8  try {
9    // Find user in database
10    const user = await User.findOne({ email });
11    if (!user) {
12      return res.status(401).json({ error: 'Invalid credentials' });
13    }
14    
15    // Verify password
16    const isValidPassword = await bcrypt.compare(password, user.passwordHash);
17    if (!isValidPassword) {
18      return res.status(401).json({ error: 'Invalid credentials' });
19    }
20    
21    // Create JWT
22    const token = jwt.sign(
23      { 
24        userId: user.id, 
25        email: user.email,
26        role: user.role 
27      },
28      process.env.JWT_SECRET,
29      { expiresIn: '1h' }
30    );
31    
32    res.json({ token, user: { id: user.id, email: user.email } });
33  } catch (error) {
34    res.status(500).json({ error: 'Server error' });
35  }
36});

Frontend JavaScript (Client-side)

1class AuthService {
2  constructor() {
3    this.token = localStorage.getItem('token');
4  }
5  
6  async login(email, password) {
7    try {
8      const response = await fetch('/api/login', {
9        method: 'POST',
10        headers: {
11          'Content-Type': 'application/json'
12        },
13        body: JSON.stringify({ email, password })
14      });
15      
16      if (!response.ok) {
17        throw new Error('Login failed');
18      }
19      
20      const data = await response.json();
21      this.token = data.token;
22      localStorage.setItem('token', this.token);
23      
24      return data;
25    } catch (error) {
26      console.error('Login error:', error);
27      throw error;
28    }
29  }
30}

セキュリティ考慮事項

トークンの保存

  • 機密トークンでのlocalStorageの使用を避ける(XSS脆弱性)
  • 自動的な含有のためにhttpOnlyクッキーを使用
  • secure、sameSiteクッキー属性を検討
  • クッキーと適切なCSRF保護を実装

秘密鍵管理

  • 強力でランダムに生成された秘密鍵を使用
  • 秘密鍵を安全に保存(環境変数、キーボルト)
  • 定期的に秘密鍵をローテーション
  • マイクロサービス向けに非対称アルゴリズム(RS256)を検討

ベストプラクティス

常にHTTPSを使用

暗号化されていない接続でJWTを送信しない

すべてのクレームを検証

有効期限、発行者、対象者、その他の関連クレームを確認

ペイロードサイズを最小化

JWTペイロードには必要な情報のみを含める

トークン更新を実装

リフレッシュトークン機構と短期間のアクセストークンを使用

トークン有効期限を適切に処理

自動トークン更新と有効期限切れ時のログアウトを実装

JWT vs 代替案

セッションベース認証

利点: サーバーサイド制御、簡単な取り消し、小さなクライアントストレージ

欠点: サーバーサイドストレージが必要、水平スケールが困難

OAuth 2.0 / OpenID Connect

利点: 業界標準、委任、包括的なフロー

欠点: より複雑な実装、追加のインフラが必要

APIキー

利点: シンプルな実装、サービス間認証に適している

欠点: 有効期限なし、スコープ制御の制限、セキュリティ上の懸念

一般的なJWTクレーム

クレーム説明
iss発行者"https://auth.example.com"
sub対象者(ユーザーID)"user123"
aud観客(対象)"api.example.com"
exp有効期限1516242622
iat発行時刻1516239022
jtiJWT ID"abc123"

まとめ

JWTは、現代のWebアプリケーションにおけるステートレス認証の堅牢なソリューションを提供します。 強力である一方、セキュリティのベストプラクティスに注意を払った慎重な実装が必要です。 代替認証方法よりもJWTを選択する際は、特定のユースケース、セキュリティ要件、 インフラの制約を考慮してください。

JWTトークンをテスト

インタラクティブなデコーダーと検証ツールでJWTトークンをデバッグ・検証。

JWTデコーダーを開く