state パラメータが提供されています。state パラメータは、クライアントが認可リクエストで設定した状態に関する情報を保持し、レスポンスでクライアントがその情報を利用できるようにします。
CSRF攻撃
state パラメータを使用する主な理由は、開始しようとしている各認証リクエストに関連付けられた、一意で推測困難な値を使って CSRF攻撃 を軽減することです。この値を使うことで、レスポンスで返された値が送信した値と一致することを確認し、攻撃を防ぐことができます。
state パラメータは文字列なので、ほかの情報をエンコードして含めることもできます。認証リクエストの開始時にランダムな値を送信し、レスポンスの処理時に受信した値を検証します。検証を行えるように、クライアントアプリケーション側で何らかの情報 (cookie、session、または localstorage) を保存しておきます。一致しない state を含むレスポンスを受け取った場合、それは送信していないリクエストに対するレスポンスか、誰かがレスポンスを偽造しようとしていることを示しているため、自分が攻撃の標的になっている可能性があると判断できます。
CSRF攻撃は、攻撃者が偽造したリクエストへのレスポンスを見る手段を持たないため、ユーザーデータの取得ではなく、アクションを開始するような state-changing リクエストを特に標的にします。最も基本的なケースでは、state パラメータは、認証で受け取ったレスポンスとリクエストを対応付けるために使用する であるべきです。
シングルページアプリケーションで使用される Auth0.js を含め、最近の OIDC および SDK の多くは、state の生成と検証を自動的に処理します。
state パラメータの値を設定して照合する
-
リクエストをIDプロバイダー (IdP) にリダイレクトする前に、アプリでランダムな文字列を生成します。たとえば、次のようにします。
state に指定できる長さは無制限ではありません。
414 Request-URI Too Largeエラーが発生した場合は、より短い値を試してください。 -
その文字列をローカルに保存します。たとえば、次のようにします。
-
リクエストに
stateパラメータを追加します (必要に応じて URL エンコードしてください) 。たとえば、次のようにします。リクエストを送信すると、ユーザーは Auth0 によってアプリケーションへリダイレクトされます。このリダイレクトにはstateの値が含まれます。使用する接続の種類によっては、この値はリクエスト本文またはクエリ文字列に含まれる場合があることに注意してください。 -
返された
stateの値を取得し、先ほど保存した値と比較します。値が一致した場合は認証レスポンスを受け入れ、一致しない場合は拒否します。
ユーザーをリダイレクトする
state パラメータを使うと、認証プロセスが始まる前にユーザーがいた場所へ戻せるよう、アプリケーションの状態をエンコードできます。たとえば、ユーザーがアプリケーション内の保護されたページにアクセスしようとした際、その操作をきっかけに認証リクエストが送信される場合は、その URL を保存しておけば、認証完了後にユーザーを目的のページへリダイレクトできます。
リダイレクト URL などの必要な状態データとあわせて、nonce をローカル (cookie、session、または local storage) に生成して保存します。プロトコルメッセージでは、その nonce を state として使用します。返された state が保存済みの nonce と一致したら、その OAuth2 メッセージを受け入れ、対応する状態データをストレージから取得します。これは auth0.js で採用している方法です。
保存した URL を使用してユーザーをリダイレクトする
- 上で説明したように、CSRF 攻撃を軽減するために使用した nonce の state パラメータ値を設定します。
-
nonce をローカルに保存し、それをキーとして、ユーザーがアクセスしようとしていた URL など、その他のアプリケーションの状態情報もすべて保存します。例:
- ユーザーを認証し、生成した nonce を state として送信します。
-
callback の処理とレスポンス検証の一環として、返された state がローカルに保存した nonce と一致することを確認します。一致していれば、残りのアプリケーションの状態 (
redirectUrlなど) を取得します。 - callback の処理が完了したら、あらかじめ保存しておいた URL にユーザーをリダイレクトします。
代替のリダイレクト方法
- nonce 値を生成し、ローカルに保存します。
- nonce と必要な state (リダイレクト URL など) を保護されたメッセージにエンコードします (改ざんを防ぐため、暗号化または署名が必要です) 。
- レスポンスの処理時にそのメッセージの保護を解除し、保存されていた nonce やその他のプロパティを取得します。
- 含まれている nonce がローカルに保存したものと一致することを validate し、一致していれば OAuth2 メッセージを受け入れます。
制限事項と考慮点
- アプリケーションの種類に応じて、保存方法を選択してください。
-
セキュリティの観点から、リクエストとレスポンスはいずれも完全性が保護されていないため、ユーザーが改ざんできてしまいます。これは、
redirect_uriにパラメーターを追加する場合も同様です。 -
stateパラメータの値に使用できる長さは無制限ではありません。414 Request-URI Too Largeエラーが発生した場合は、より短い値を試してください。 -
URL を平文のまま、または予測可能な形で渡すのは安全ではありません。
stateパラメータの値は、次の条件を満たすようにしてください。- CSRF 攻撃やフィッシング攻撃への対策として使えるよう、一意で内容を推測できないものにすること。
- Cookie に保存する場合は、偽造を防ぐために署名すること。