OpenID Connectでは、セキュリティ対策として使用するパラメータがいくつか存在します。
statenonce-
code_challenge/code_verifier(PKCE)
いずれも「リクエスト時に値を送信し、レスポンス時に値を検証する」ということを行っていますが、それぞれ検証するタイミングと防ぐ攻撃の種類が異なります。
検証のフロー
認可コードフローを前提としています。
各パラメータがどのタイミングで検証されるか示した図を以下に示します。
括弧内がリクエストに付随するパラメータ(state, nonce, PKCE関連)で、パラメータが関係する箇所は色で強調しています。
state
stateはCSRFを防ぐために利用します。
CSRFとは例えば、認可コード付きのリダイレクションエンドポイントへのリンクを他人に送りつけて攻撃者のIDとしてログインさせることです。
被害者がそのまま気づかずにお金をチャージしたり個人情報を入力すると、攻撃者はそのリソースを窃取することができます。
stateはこのような攻撃を防ぐための仕組みです。
認可エンドポイントは受け取ったstateのパラメータをそのままリダイレクトリンクに付与するようになっているので、
- 認可コードリクエスト時の
state - リダイレクションエンドポイントアクセス時の
state
Clientはこれらを比較することで、リダイレクションエンドポイントへのアクセスが自分が開始した認可フローによるものなのかどうかを検証することができます。
nonce
nonceはリプレイ攻撃を防ぐために利用します。
リプレイ攻撃とは、何らかの方法で窃取した他人のIDトークンを使ってClientで認証することです。
これを防ぐためにnonceがあります。
認可リクエスト時に渡したnonceは、そのままIDトークンのClaimに格納されるようになっているので、
- 認可コードリクエスト時の
nonce - IDトークンのClaimに含まれる
nonce
Clientはこれらを比較することで、IDトークンが自分の認可フローで発行されたものかを検証することができます。
PKCE関連のパラメータ
code_challenge, code_verifierは認可コード横取り攻撃を防ぐためにあります。
認可コード横取り攻撃とは、(URLスキームを利用した)認可レスポンスのリダイレクト時に意図しないアプリが発火し、認可コードを取られてしまうことです。
PKCEによってアプリの同一性を確認します。
- 認可リクエスト時に送られた
code_challengeの値 - アクセストークンリクエスト時に送られた
code_verifierをハッシュ化した値
これらの値が同一であるかIdPが検証することで、アプリの同一性を検証でき、認可コードが盗まれてもトークンを取得することを防ぐことができます。
まとめ
これらのパラメータはどれも認可フローの整合性を検証するための仕組みですが、
それぞれ防ぐ攻撃の種類が異なります。
| パラメータ | 対策する攻撃 | 攻撃の内容例 | 検証内容 |
|---|---|---|---|
| state | CSRF | 攻撃者の認可レスポンスを標的に踏ませる | リクエスト時の値とリダイレクト時の値を比較 |
| nonce | リプレイ攻撃 | 他人のIDトークンを再利用する | リクエスト時の値とIDトークンのnonceを比較 |
| code_challenge, code_verifier(PKCE) | 認可コード横取り攻撃 | リダイレクトのURLスキーマで発火する偽アプリを用意する |
code_verifierのハッシュ値とcode_challengeを比較 |