JWT(JSON Web Token)は、一度発行すると、有効期限が切れるまでそのままでは無効化できません。サーバーがログイン状態を記録しない(ステートレス)ことがJWTの特徴で、署名が正しく期限内であれば、サーバーはそのトークンを受け入れるからです。

そのため「ログアウトボタンを押したのに、トークンを持っていればAPIが使える」という状態が起こり得ます。この記事では、その理由と、ログアウトや強制失効を実現する主な方法、それぞれの使い分けを解説します。

なぜJWTは無効化できないのか

従来のセッション方式では、サーバーがセッションIDとログイン状態を保存し、ログアウト時にそのセッションを削除します。サーバー側の記録を消せば、そのIDは使えなくなります。

JWTは、ユーザー情報と有効期限をトークン自体に含め、署名で改ざんを防ぎます。サーバーは署名と有効期限を検証するだけで、トークンの状態を記録しません。これにより、どのサーバーでも検証でき、スケールしやすいという利点があります。

その裏返しとして、「このトークンはもう使えない」という情報を持つ場所がないため、有効期限が来るまで使えてしまうのです。

クライアントで削除するだけでは不十分

ログアウト時にブラウザからトークンを削除すれば、通常の操作ではもう使われません。これは必要な処理ですが、それだけでは十分ではありません。

  • トークンが漏洩していた場合、攻撃者の手元のコピーは有効なまま
  • 端末の紛失やアカウント乗っ取り時に、「全端末からログアウト」ができない
  • 権限を剥奪したユーザーのトークンも、期限まで使えてしまう

サーバー側で失効を判断できる仕組みを、要件に応じて組み合わせる必要があります。

方法1:アクセストークンを短命にして、リフレッシュトークンと組み合わせる

最も一般的な構成です。

  • アクセストークン(JWT) — 有効期限を短く(例:5〜15分)する。APIの呼び出しに使う
  • リフレッシュトークン — 有効期限を長くし、サーバー側に保存する。アクセストークンの再発行にだけ使う

ログアウト時は、サーバー側でリフレッシュトークンを削除(失効)します。アクセストークンは短い期限で自然に切れ、新しいものは発行されなくなります。

利点:APIの呼び出しごとにサーバーの状態を確認しなくて済むので、JWTの利点をほぼ保てる 注意点:アクセストークンの有効期限の間(数分)は、ログアウト後も使えてしまう。この「猶予」を許容できるかが判断基準です

リフレッシュトークンのローテーション

リフレッシュトークンを使うたびに新しいリフレッシュトークンを発行し、古いものを失効させる方式です。万一リフレッシュトークンが盗まれても、正規ユーザーと攻撃者のどちらかが古いトークンを使った時点で不正を検知し、そのトークン系列をまとめて失効させる、といった対策が取れます。

方法2:失効リスト(ブロックリスト)を持つ

ログアウトしたトークンの識別子(JWTの jti クレームなど)を、有効期限まで失効リストに保存し、APIの呼び出しごとにリストを確認する方法です。

利点:ログアウトの瞬間から、そのトークンを使えなくできる 注意点:呼び出しごとにリストの確認が必要になり、ステートレスの利点が一部失われる

リストには「有効期限までのトークン」だけを保存すればよいので、期限切れのものは自動で削除される仕組み(有効期限付きのキーを扱えるストア等)を使うと、肥大化を防げます。

方法3:ユーザーごとのトークンバージョンを持つ

ユーザー情報に「トークンのバージョン番号」を持たせ、JWTにもその番号を含めます。全端末からのログアウトやパスワード変更時にバージョンを上げると、古い番号のトークンはすべて無効になります。

利点:「全端末からログアウト」「パスワード変更時に全セッションを失効」が1操作でできる 注意点:呼び出しごとにユーザーのバージョンを確認する必要がある(キャッシュで負荷を抑えるのが一般的)

方法の比較と選び方

方法 ログアウトの即時性 サーバーの状態 向いている要件
短命アクセストークン+リフレッシュトークン 数分の猶予あり リフレッシュトークンのみ 多くのWebアプリ・モバイルアプリ
失効リスト 即時 失効したトークン 即時の失効が必須のシステム
トークンバージョン 即時(全端末単位) ユーザーごとの番号 全端末ログアウト・強制失効が必要

多くのシステムでは、方法1を基本に、必要に応じて方法2か3を組み合わせる構成が現実的です。金融・医療など、ログアウトや権限変更を即座に反映する必要がある場合は、即時性のある方法を併用します。

トークンの保存場所も、あわせて考える

ログアウトの設計と同じくらい重要なのが、ブラウザのどこにトークンを保存するかです。

  • localStorage — JavaScriptから読めるため、XSS(悪意あるスクリプトの注入)が起きるとトークンを盗まれる
  • HttpOnly属性付きのCookie — JavaScriptから読めないため、XSSによる窃取を防げる。CSRF対策(SameSite属性やトークン)とセットで使う

どちらが絶対に正しいというより、守りたい脅威に合わせて選ぶものです。リフレッシュトークンのように長く有効なものは、HttpOnly Cookieに置く構成がよく採用されます。

そもそもJWTを使うべきか

JWTは、複数のサービスやサーバー間で、ユーザー情報を持ち運ぶ用途で特に力を発揮します。一方、単一のWebアプリで、ログアウトの即時性が重要な場合は、従来のサーバーセッション方式の方がシンプルなこともあります。

「JWTを使うこと」自体を目的にせず、無効化の要件を先に決めてから方式を選ぶのが確実です。

よくある質問

Q. アクセストークンの有効期限はどれくらいにすべきですか? A. 一般的には数分〜十数分程度です。短いほどログアウト後の猶予が小さくなりますが、再発行の頻度が増えます。セキュリティ要件と使い勝手のバランスで決めます。

Q. JWTにログアウト用のフラグを入れればいいのでは? A. JWTは発行後に中身を書き換えられない(書き換えると署名が合わなくなる)ため、発行済みのトークンに後からフラグを付けることはできません。

Q. パスワードを変更したら、既存のトークンを無効にすべきですか? A. すべきです。パスワード変更は「アカウントが乗っ取られたかもしれない」ときにも行われるため、トークンバージョンの更新などで既存のトークンを失効させるのが安全です。

Q. リフレッシュトークンもJWTにすべきですか? A. どちらも可能ですが、リフレッシュトークンはサーバー側で失効させる前提なので、ランダムな文字列にしてサーバーで管理する構成も一般的です。

まとめ

  • JWTはステートレスなので、発行済みのトークンはそのままでは無効化できない
  • クライアントでの削除は必要だが、それだけでは漏洩時や乗っ取り時に対応できない
  • 基本は短命アクセストークン+リフレッシュトークン。即時性が必要なら失効リストやトークンバージョンを組み合わせる
  • 保存場所(localStorageかHttpOnly Cookieか)も、守りたい脅威に合わせて選ぶ

株式会社RJCが携わる保険・金融・決済のシステムでは、ログインの向こう側にお金や個人情報があります。認証の仕組みを「動く」だけでなく「守れる」形で設計する知識を、チームで共有しながら開発しています。

▶ RJC丸わかり https://www.r-jc.jp/guide/?mediacode=02-00001-003

▶ エントリーはこちら(1〜2分で完了します) https://www.r-jc.jp/recruitment/?mediacode=02-00001-003

株式会社RJC ― SI事業・SES事業・AI駆動開発。未経験からエンジニアに育てるのが得意な会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?