理系学生日記

おまえはいつまで学生気分なのか

OAuth2.0で認可コードの漏洩を防ぐPKCE

OAuth 2.0 における通信は基本的に TLS で守られるのが基本なのだけれど、ひとつ TLS で守られない通信があります。それは Client・User-Agent 間の通信です。 Authorization Code Grant においては、認可サーバから認可コードを受けた User-Agent がその情報をクライアントに渡すときに発生します。

Authlete さんの以下の図がすごくわかりやすいのですが、User-Agent (Operation System Browser) から Malicious App に認可コードが漏れていることがわかります。 Native App では、これは Custom Scheme が悪意のある App に上書きされた場合等で発生します。 もちろん、認可コードが漏れたら、アクセストークンも漏れるので、このような認可コードの漏洩は防がなければなりません。

PKCE

これを防ぐのが、RFC 7636 で定義されている Proof Key for Code Exchange by OAuth Public Clients、通称 PKCE (ピクシー) です。 PKCE の原理はすごくシンプルで、認可サーバ側で、「認可リクエスト」を送信してきたクライアントと「トークンリクエスト」を送信してきたクライアントが同一であることを確認するという方法です。

  1. クライアントは、認可リクエストを送信する際、code_verifier という乱数を発生させた上で、ハッシュ関数 t を用いたハッシュ値を計算します。結果としてのハッシュ値 t(code_verifier) とハッシュ関数を、それぞれ code_challengecode_challenge_method として認可リクエストに含め、認可サーバに送信します。
  2. 認可サーバは、認可リクエストを受信した際、code_challengecode_challenge_method を保存しておきます。
  3. クライアントは、トークンリクエストを認可サーバに送信する際、1. で生成した code_verifier をトークンリクエストに含めます。
  4. 認可サーバは、トークンリクエストを受信すると、2. で保存した code_challenge_method である t と使って t(code_challenge) を計算し、それが、code_challenge と一致するかを検証します。

パラメータ追加のみで、認可フローを変えなくて良いので、導入しやすい方法だと思います。

上記ではハッシュ関数としていますが、実際に PKCE で使用できるのは以下の 2 つですが、まぁ S256 一択ですかね。

  1. plain: 恒等関数
  2. S256: SHA-256 でハッシュ化した値を BASE64 に変換したもの

参考文献