⭐️OAuth2.0: Stateの役割について

前提

  • OAuth 2.0: ユーザーの許可を得て、アプリがユーザーのリソースにアクセスする仕組み(認可)
  • OIDC: OAuth 2.0 に「誰がログインしたか」を示す ID トークンを足したもの(認証)

state の流れ

An opaque value used by the client to maintain state between the request and callback. … The parameter SHOULD be used for preventing cross-site request forgery as described in Section 10.12. — RFC 6749 4.1.1

訳: リクエストからコールバックまでの間、状態を保つために Client が使う、中身に意味を持たない値。…… 10.12 節にあるクロスサイトリクエストフォージェリ(CSRF)を防ぐために使うべきである(SHOULD)。

Client がランダムな state を作ってセッションに保存し、戻ってきた値と比べる。

sequenceDiagram
    participant U as ブラウザ
    participant C as Client
    participant AS as 認可サーバー

    U->>C: ログイン開始
    C->>C: state=abc を保存
    C->>U: 認可サーバーへ(state=abc)
    U->>AS: ログインして許可
    AS->>U: callback へ(code, state=abc)
    U->>C: /callback?code=...&state=abc
    C->>C: abc = abc → OK
    C->>AS: code をトークンに交換
    AS->>C: アクセストークン

state がない場合

攻撃者の code を被害者のブラウザに送り込める(CSRF)。

sequenceDiagram
    participant A as 攻撃者
    participant V as 被害者のブラウザ
    participant C as Client
    participant AS as 認可サーバー

    A->>C: ログイン開始
    C->>A: 認可サーバーへ
    A->>AS: 攻撃者のアカウントでログインして許可
    AS->>A: callback へ(攻撃者の code)
    Note over A: callback には行かずに止める
    A->>V: /callback?code=攻撃者のcode を踏ませる
    V->>C: /callback?code=攻撃者のcode
    C->>C: 確認できないので受け入れる
    C->>AS: 攻撃者の code をトークンに交換
    AS->>C: 攻撃者のアクセストークン
    Note over V,C: 被害者が攻撃者のアカウントでログインした状態になる

被害者がアップロードしたファイルやカード情報が、攻撃者のアカウントに入る。

state がある場合

被害者のセッションの state と一致しないので拒否される。攻撃者は被害者の state を知らない。

sequenceDiagram
    participant A as 攻撃者
    participant V as 被害者のブラウザ
    participant C as Client
    participant AS as 認可サーバー

    A->>C: ログイン開始
    C->>A: 認可サーバーへ(攻撃者の state=abc)
    A->>AS: 攻撃者のアカウントでログインして許可
    AS->>A: callback へ(攻撃者の code, state=abc)
    V->>C: ログイン開始
    C->>C: 被害者の state=xyz を保存
    A->>V: /callback?code=攻撃者のcode&state=abc を踏ませる
    V->>C: /callback?code=攻撃者のcode&state=abc
    C->>C: xyz ≠ abc → 拒否
    Note over C,AS: code の交換まで進まない

state と PKCE の違い

PKCE: 開始時に秘密値を作り、code 交換時に提示する。秘密値を持たない者は code を使えない。

statePKCE
主な目的CSRF 対策code の盗難・注入対策
確認する人Client(callback 時)認可サーバー(code 交換時)
CSRF防げる副次的に防げる

PKCE で CSRF も防げる理由: 攻撃者の code は攻撃者の秘密値に紐づいている。被害者の Client は自分の秘密値で交換しようとするので、認可サーバーが拒否する。

as a side effect, it prevents CSRF even in the presence of strong attackers — RFC 9700 2.1.1

訳: 副次的な効果として、強力な攻撃者がいる場合でも CSRF を防ぐ。

https://datatracker.ietf.org/doc/html/rfc6749#section-10.12 https://datatracker.ietf.org/doc/html/rfc9700#section-2.1.1 https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1