OAuth2.0 State の役割


はじめに

前回は OAuth2.0 の認可コードグラントフローの I/F についてまとめました。
その中でいきなり登場したStateにフォーカスしてまとめます。

アジェンダ

  1. 認可コードグラント(復習)
  2. CSRF のための state
  3. OAuth2.0 の CSRF(Cross-Stie-Request-forgery)
  4. state を使用した認可コードグラントフロー
  5. まとめ

認可コードグラント(復習)

またか!って思われるかもしれませんが、認可コードフローはフローが長く
どこの話してるのかわかりにくいので、書いています。
(毎回すこしづつ改修してるので更に見やすくなっている...はず...)

CSRF 対策のための State

RFC6749の state の説明にはっきりと CSRF 対策のために導入すべき、と記載されています。

The parameter SHOULD be used for preventing cross-site request forgery
訳) このパラメータはcross-site request forgery(CSRF)対策のために使用すべき

これだけ読んで、おお、なるほど CSRF のためか。。。
とはならないですよね。
少なくとも私はなりませんでした。

ということで OAuth2.0 における CSRF とはどんなものなのかまとめます。

OAuth2.0 の CSRF(Cross-Stie-Request-forgery)

OAuth2.0 での CSRF はいわゆる一般的な CSRF とは少し意味が違います。
OAuth2.0 における CSRF 攻撃とは、攻撃の標的となったユーザに攻撃者のリソースを処理させる権限を与えることです。

実際のフローは下記のようになります。

  1. 攻撃者が認可フローを開始し認可画面で認可を行う
  2. 通常、認可後のレスポンスからリダイレクトするところを、何らかの方法でリダイレクトさせずに、止める
  3. 本来リダイレクトを行う値(RedirectURI + 認可コード)を攻撃対象者に送りつけ、実行させる
  4. すると攻撃者のリソースを処理することができる情報を持つトークンが、攻撃対象者に紐付けられる

このような状況下だと、以下のようなことが起こります。
攻撃対象者が Qiita への投稿をサードパーティ製のアプリで行うとします。
しかし、投稿は攻撃対象者自身のアカウントではなく、攻撃者のアカウントに投稿されてしまいます。

state を使用した認可コードグラントフロー

上記のような問題が発生する理由は、認可したユーザと認可後のリダイレクトを行ったユーザが一緒であることが担保されていない事です。
そこで、認可画面の前後で行われている処理が同じ人であるということを担保するための値が State です。
State を使用すると、下記の図のようになります。

  1. 認可リクエスト時にセッションに紐づく State を発行し、State も一緒に送ります。
  2. 認可サーバは送られてきた値をそのまま返却し
  3. 認可コードがリダイレクトされた際に、state の検証を行い、誤っていればリソースに対する処理を行わない

というフローになり、CSRF 攻撃を防いでいます。

まとめ

今回は OAuth2.0 と CSRF 対策についてまとめました。
Stateを使うことでcross-site request forgery(CSRF)を防げます。
が、このやり方だと、認可プロバイダが、クライアント正しくstateを使用できているか、を判断できません。
そのため、今日ではstateの代わりにPKCEを使用して、CSRFの対策を行ったりするようです。
次回はPKCE周りについてまとめる予定です。