認証トークン完全ガイド:種類・仕組み・脆弱性と実装ベストプラクティス

はじめに

認証トークンは、モダンなWebやAPIの認証・認可で中心的な役割を果たします。システム間でユーザやクライアントの身元や権限を伝達するために使われ、設計次第で利便性とセキュリティに大きな差が出ます。本稿では認証トークンの種類、内部構造、発行と検証、保管、脆弱性と対策、運用上のベストプラクティスまでを詳しく解説します。

認証トークンの基本概念と主要な種類

認証トークンとは、ある主体が認証済みであることを示すデータのことです。一般的な種類は次の通りです。

  • セッションID(サーバ状態型): サーバ側にセッション情報を保持し、クライアントにはセッションIDをクッキーなどで渡す方式。状態管理が必要だがサーバで容易に無効化できる。
  • JWT(JSON Web Token): 自己完結型トークン。ペイロードにクレームと呼ばれる情報を含み、署名によって改ざん検出が可能。ステートレスなAPIで広く使われる。
  • OAuth2アクセストークン・リフレッシュトークン: サードパーティ認可で使われる。アクセストークンは短命、リフレッシュトークンは長命でアクセストークン再発行に使う。
  • APIキー: 単純なトークン文字列でサービス識別に使う。権限管理や失効が難しいため注意が必要。

JWTの構造と注意点

JWTは通常3つの部分で構成され、ドットで区切られます。ヘッダ、ペイロード、署名です。ヘッダには使用アルゴリズム、ペイロードにはiss, sub, aud, exp, nbf, iat, jtiなどのクレームが含まれます。署名はHS256やRS256などで作成され、トークンの整合性を保ちます。

注意点:

  • algの取り扱い: クライアントから送られたヘッダのalgをそのまま信頼すると危険。サーバは期待するアルゴリズムのみを許可する。
  • 署名と暗号化の違い: 署名は改ざん検出、暗号化は内容秘匿を意味する。JWTは通常署名のみであり、機密情報は格納しない。
  • トークンサイズ: クレームを増やしすぎるとHTTPヘッダやCookieのサイズ制限に影響する。

発行・検証フローと設計上の決定事項

発行時には発行者(iss)、有効期限(exp)、対象(aud)などを厳密に設定します。検証時は次を確認します: 署名検証、issとaudの一致、exp/nbfの範囲、jtiの重複チェックなど。さらに必要に応じてスコープや権限の照合を行います。

設計上の決定事項:

  • 有効期限を短くして再発行を前提にするか、長命トークンを使うか
  • ステートレスでスケールさせるか、トークン失効のためにサーバ側でブラックリスト等を管理するか
  • 署名に対称鍵(HMAC)を使うか、公開鍵基盤(RS/ES)を使うか

保存場所の比較とセキュリティ考慮

クライアント側の保存場所はセキュリティに直結します。主な選択肢とその利点・欠点は以下の通りです。

  • HttpOnly Secure Cookie: XSSからの窃取に強く、SameSite属性でCSRF対策を補強できる。ただしクロスサイト利用やサブドメインの扱いに注意。
  • localStorage/sessionStorage: JavaScriptから容易に扱えるがXSSに弱い。機密性の高いトークン保存には不向き。
  • ブラウザメモリ(リロードで消える): XSSリスク低減のための選択肢だが、リロードでユーザ体験が落ちる。

主要な脆弱性と具体的対策

代表的な脆弱性とそれぞれの対策を示します。

  • XSS(クロスサイトスクリプティング): トークン窃取の主要手段。対策はコンテンツセキュリティポリシー(CSP)、入力のサニタイズ、HttpOnlyクッキーの活用。
  • CSRF(クロスサイトリクエストフォージェリ): ブラウザ自動送信されるクッキーが原因で発生。対策はSameSite属性、CSRFトークンの導入、ステートフルな検証。
  • リプレイ攻撃: 同じトークンを再利用される問題。対策は短寿命トークン、jtiによる一回限り検証、TLSの徹底。
  • リフレッシュトークンの漏洩: 長命のリフレッシュトークンは特に危険。対策は回転(refresh token rotation)、保存場所を厳格にし、不審な再利用を検知して全セッションを無効化する。
  • 鍵管理の不備: 署名鍵の漏洩は致命的。対策は鍵の定期ローテーション、ハードウェアセキュリティモジュール(HSM)利用、公開鍵の公開位置を明確にする(jwksエンドポイント)

OAuth2とOpenID Connectにおけるトークン設計

OAuth2ではアクセストークンとリフレッシュトークンが使われ、OpenID Connect(OIDC)はIDトークンを追加します。設計のポイントは次の通りです。

  • アクセストークンはリソースアクセス用に短寿命にする
  • リフレッシュトークンは安全な保管と使用ポリシーで保護し、可能なら回転を行う
  • PKCEをパブリッククライアントで必須化して認可コードインタセプトを防ぐ
  • IDトークンはユーザ情報を伝えるため、必要最小限のクレームに限定する

トークン失効と検証の実装パターン

トークン失効をどう扱うかで実装は大きく変わります。代表的な方法:

  • ブラックリスト(サーバ側保存): 失効トークンの識別子を保存して検証時に照会する。リアルタイムに無効化できるがスケーラビリティと管理コストが増す。
  • 短寿命トークン戦略: アクセストークンを極短にし、リフレッシュトークンで延長する。ブラックリスト負担を減らせる。
  • トークンイントロスペクション: OAuth 2.0のイントロスペクションエンドポイントでトークンの状態を問い合わせる方式。リソースサーバは中央での有効性確認が可能。

ログや監査、検出による運用強化

トークンの運用には監査と不正検出が重要です。推奨事項:

  • 発行ログと利用ログを分離して保存し、異常な利用パターンを検出する
  • jtiとクライアント識別子を用いて再利用や多地点同時利用を検出する
  • リフレッシュトークンの再利用検出によりアラートを上げ、必要なら全セッションを無効化する

実装上のチェックリスト

トークン実装時に確認すべきポイントをまとめます。

  • HTTPS/TLSは必須で全通信を暗号化しているか
  • トークンの有効期限は最小限に設定しているか
  • 署名アルゴリズムと鍵の管理は安全に行っているか
  • クライアント側の保存場所は脅威モデルに応じて選定しているか
  • リフレッシュトークンに対して回転や検出を実装しているか
  • CSRF/XSS対策が適切に施されているか
  • 失効やローテーションの運用手順が文書化されているか

よくある誤解と落とし穴

一般的な誤解をいくつか挙げます。まず、JWT = セキュアではないという言い方は誤りで、使い方次第で安全にも脆弱にもなります。署名されていれば改ざんは検出できるが、内容の秘匿はされない点を混同しないこと。次に、ステートレスにしたから運用負荷が無くなるわけではなく、鍵ローテーションや失効検知のための仕組みが必要になります。

まとめと推奨アーキテクチャ

トークン設計は妥協の連続です。推奨の基本方針は次の通りです。アクセストークンは短寿命、保存はHttpOnlyかつSecureなCookie、リフレッシュトークンは回転と厳格な保管、署名は公開鍵方式で鍵ローテーションを用意、イントロスペクションやブラックリストで失効対応を可能にする。また、監査と異常検出を運用に組み込み、必要時に全セッション無効化できる体制を作ることが重要です。

参考文献

RFC 7519 JSON Web Token

RFC 6749 OAuth 2.0

OpenID Connect Core 1.0

OWASP Top Ten

OWASP Cheat Sheets