jwt debugging security authentication web-development

'JWT expired' と一般的な JSON Web Token エラーの解决方法

'invalid signature'、'token expired'、'malformed token' などの JWT エラーを修正するための包括的なガイド。アプリの認証問題をデバッグする方法を学びましょう。

"JWT expired" と一般的な JSON Web Token エラーの解決方法:完全ガイド

JSON Web Token (JWT) は、JSON オブジェクトとして情報を安全に送信するための業界標準です。現代のウェブやモバイルアプリケーションにおける認証 (Authentication) や認可 (Authorization) に広く使用されています。しかし、これらは暗号化された署名が施されており、厳密な有効期限ルールを持つことが多いため、デバッグの際に大きな悩みの種になることがあります。

このガイドでは、最も一般的な JWT エラーを分類し、それらが発生する理由と解決方法について解説します。


1. 一般的な JWT エラーメッセージ

Node.js の jsonwebtoken などのライブラリを使用している場合、以下のような一般的なエラー名に遭遇することがあります:

  • TokenExpiredError: トークンは有効ですが、有効期限を過ぎています。
  • JsonWebTokenError: invalid signature: トークンの署名が、提供されたシークレット/キーと一致しません。
  • JsonWebTokenError: jwt malformed: 提供された文字列が有効な JWT 構造ではありません。
  • JsonWebTokenError: jwt signature is required: 署名セクションのないトークンが提供されました。
  • JsonWebTokenError: jwt invalid audience: トークン内の aud (audience) クレームが期待される値と一致しません。

2. 主な原因と解決策

2.1 "TokenExpiredError" (JWT expired)

すべての安全な JWT には exp (有効期限) クレームが含まれているべきです。現在時刻がこの値を過ぎると、トークンは無効になります。

症状: ユーザーが突然ログアウトされたり、API リクエストが jwt expired というメッセージとともに 401 Unauthorized エラーを返し始めたりします。

解決策:

  1. リフレッシュトークン (Refresh Tokens): アクセストークンが期限切れになるたびにユーザーが手動でログインし直さなくても済むよう、「リフレッシュトークン」戦略を実装します。
  2. 時刻同期: サーバーの時計が NTP を使用して同期されていることを確認してください。数秒のズレでも問題が発生する可能性があります。
  3. iatnbf の確認: 「発行時刻」(iat) と「使用開始時刻」(nbf) クレームも正しいことを確認してください。

2.2 "invalid signature" (invalid JWT signature)

JWT は、ヘッダー (Header)、ペイロード (Payload)、署名 (Signature) の 3 つの部分で構成されています。署名は、ヘッダーとペイロードをシークレットキーでハッシュ化することで作成されます。ペイロード内の文字が 1 つでも変更されたり、間違ったシークレットキーが使用されたりすると、署名は無効になります。

原因:

  • トークンの検証に間違った secret または public key を使用している。
  • 署名に使用されたアルゴリズム (例: HS256) と検証に使用されたアルゴリズム (例: RS256) の不一致。
  • 送信中にトークンが改ざんされたか、破損した。

解決策:

  • シークレットキーの環境変数を再確認してください。
  • JWT ヘッダーの alg が、検証に使用しているアルゴリズムと一致していることを確認してください。

2.3 "jwt malformed" または "jwt decode failed"

有効な JWT は、ドット (.) で区切られた 3 つの部分 (header.payload.signature) を持つ必要があります。いずれかの部分が欠けている場合や、文字列が有効な Base64URL ではない場合、フォーマットエラーと見なされます。

原因:

  • "Bearer " プレフィックスが付いた文字列を直接ライブラリに渡している (例: atob("Bearer <token>"))。
  • トークンの一部をコピー&ペーストし損ねた。
  • トークン文字列に余分な空白や隠し文字が含まれている。

解決策: デコーダーに渡す前に、必ず Bearer プレフィックスを取り除いていることを確認してください。

const token = authHeader.split(' ')[1]; // "Bearer <token>" からトークンを抽出

2.4 "jwt invalid audience" または "jwt invalid issuer"

これらは、ペイロード内の aud (audience) または iss (issuer) クレームが、サーバーが期待する値と一致しない場合に発生します。

解決策: 認証サーバー (Auth0、Firebase、または独自のサーバーなど) の設定が、アプリケーションコードの検証オプションと一致していることを確認してください。


3. 高度なトラブルシューティング

3.1 ペイロードの検査

署名エラーが発生している場合、最初のステップは ペイロードを検査 して、期待通りのデータが含まれているか確認することです。ペイロードのデコードと読み取りにはシークレットキーは必要ありません (単なる Base64 エンコードであるため)。

3.2 アルゴリズム混同攻撃 (Algorithm Confusion Attacks)

ライブラリが期待する特定のアルゴリズムのみを許可するように構成されていることを確認してください。一部の古いライブラリは、攻撃者がヘッダーを alg: none に変更してセキュリティを回避できる攻撃に対して脆弱でした。現代のライブラリの多くはこの問題を修正していますが、常に許可するアルゴリズムを明示的に定義してください。

jwt.verify(token, secret, { algorithms: ['HS256'] });

4. 予防策とベストプラクティス

  1. 短寿命のアクセストークン: アクセストークンの有効期限を短く保ち (例: 15 分)、長いセッションにはリフレッシュトークンを使用します。
  2. 安全なシークレット: JWT シークレットをハードコードしないでください。環境変数を使用し、定期的にローテーションさせてください。
  3. すべてのリクエストを検証: サーバー側で署名を検証せずに JWT を信頼しないでください。
  4. HTTPS の使用: 「中間者攻撃」(MITM) を防ぐため、常に HTTPS 経由でトークンを送信してください。

5. よくある質問 (FAQ)

Q: シークレットなしで JWT 内部のデータを読むことはできますか?

A: はい。 ヘッダーとペイロードは Base64URL エンコードされているだけで、暗号化はされていません。トークンを持っている人なら誰でもデータを読むことができます。パスワードやクレジットカード番号などの機密情報を JWT ペイロードに入れないでください。

Q: HS256 と RS256 の違いは何ですか?

A: HS256 は署名と検証の両方に 単一の共通鍵 を使用します (対称鍵)。RS256 は署名に 秘密鍵 を、検証に 公開鍵 を使用します (非対称鍵)。これは分散システムにおいてより安全です。

Q: フロントエンドで "jwt expired" エラーをどのように処理すればよいですか?

A: API インターセプターで 401 エラーをキャッチします。エラーが "jwt expired" の場合は、リフレッシュトークンのエンドポイントの呼び出しを試みます。それが失敗した場合は、ユーザーをログインページにリダイレクトします。


6. クイックチェックツール

特定のトークンでお困りですか?当サイトの JWT デコーダー&デバッガー をご利用ください。以下のことが可能です:

  • 任意の JWT を即座にデコードし、ヘッダーとペイロードを確認。
  • 有効期限の状態iatexpnbf などのクレームを確認。
  • フォーマットエラー (malformed tokens) やエンコーディングの問題を特定。
  • 署名の検証 (ローカルでシークレットキーを入力した場合)。

関連エラー

  • JSON の 'Unexpected token' エラーの解決方法
  • 'invalid base64 string' エラーの修正方法
  • 'invalid regular expression' エラーの解決方法