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日) |
| 保存場所 | メモリ、または短命Cookie | HttpOnly Cookie |
セキュリティベストプラクティス
- 適切な有効期限を設定する
- 強力な秘密鍵を使用する
- アルゴリズムを明示的に指定する
- HttpOnly Cookieで保存する
- センシティブな情報を含めない
実装例
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の問題と対策
よくある実装ミス
- 秘密鍵のハードコード
環境変数やシークレット管理サービス(AWS Secrets Manager等)を必ず使用してください。
- アルゴリズムの未指定
jwt.verify() でアルゴリズムを明示しないと、攻撃者が "alg": "none" を使う脆弱性につながります。
// 危険
jwt.verify(token, secret);
// 安全
jwt.verify(token, secret, { algorithms: ['HS256'] });
- トークン失効の未対応
パスワード変更時やログアウト時にトークンを無効化する仕組み(ブラックリスト/バージョニング)が必要です。
トークンローテーションの実装
// リフレッシュトークン使用時に新しいペアを発行
async function refreshTokens(refreshToken: string) {
const payload = jwt.verify(refreshToken, REFRESH_SECRET);
// 古いリフレッシュトークンを無効化
await invalidateToken(refreshToken);
// 新しいトークンペアを生成
return generateTokens(payload.sub, payload.role);
}
関連記事
認証・認可をさらに深く学ぶために:
- OAuth 2.0 / OpenID Connect - 外部認証プロバイダとの連携
- 認証・認可パターン - 設計パターンの比較
- REST API設計原則 - セキュアなAPI設計
- Webセキュリティベストプラクティス - 総合的なセキュリティ対策
- 暗号化の基礎 - 署名アルゴリズムの仕組み
まとめ
JWTは、ステートレスな認証を実現する強力なツールです。構造を理解し、適切に実装することで、セキュアでスケーラブルな認証システムを構築できます。
特にアルゴリズムの明示指定、適切な有効期限設定、トークンローテーションの実装は、本番環境では必須の対策です。
← 一覧に戻る