satoshi.inoue's blog


PKCE: OAuth2.0の認可コード横取り攻撃への対策




Authorization Code Flowで認可コードを発行して、ブラウザから元のアプリにカスタムURLスキーム等で戻ってくるときに、攻撃者によってインストールされたプログラム等により、認可コードを抜き取られる攻撃です。


OAuth 2.0 public clients utilizing the Authorization Code Grant are susceptible to the authorization code interception attack. This specification describes the attack as well as a technique to mitigate against the threat through the use of Proof Key for Code Exchange (PKCE, pronounced "pixy").

RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients
Authorization Code Flowを使用するOAuth 2.0のPublic Clientは、認可コード横取り攻撃の影響を受けやすいので、コード交換のための証明鍵(PKCE、 "pixy"と発音)を使用して脅威を軽減します。


code_verifier を生成する

The client first creates a code verifier, "code_verifier", for each OAuth 2.0 [RFC6749] Authorization Request, in the following manner:
code_verifier = high-entropy cryptographic random STRING using the unreserved characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~" from Section 2.3 of [RFC3986], with a minimum length of 43 characters and a maximum length of 128 characters.

code_verifier = 予約されていない文字[A-Z] / [a-z] / [0-9] / " - " / "を使用した高エントロピー暗号化ランダムSTRING。 [RFC3986]のセクション2.3からの "/" _ "/"〜、最低長さ43文字、最大長さ128文字。  

code_challenge を生成する

The client then creates a code challenge derived from the code verifier by using one of the following transformations on the code verifier:

      code_challenge = code_verifier
      code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))

If the client is capable of using "S256", it MUST use "S256", as "S256" is Mandatory To Implement (MTI) on the server.
Clients are permitted to use "plain" only if they cannot support "S256" for some technical reason and know via out-of-band configuration that the server supports "plain".
The plain transformation is for compatibility with existing deployments and for constrained environments that can't use the S256 transformation.

S256は、SHA-256でハッシュし、base64urlでエンコードする。 ※ code_challenge_methodは、クライアントがS256を使用できる場合はこれを使用する必要があり、技術的な理由でS256をサポートできず、サーバーがplainをサポートしていることが分かっている場合に、クライアントはplainを使用できます。

Authorization Requestでパラメータを追加する

4.1.1. Authorization Requestに、code_challengecode_challenge_methodを含める。

Access Token Requestでパラメータを追加する

4.1.3. Access Token Requestに、code_verifierを含める。



When the server issues the authorization code in the authorization response, it MUST associate the "code_challenge" and "code_challenge_method" values with the authorization code so it can be verified later.

4.1.1. Authorization Requestで認可コードを発行するときに、code_challengecode_challenge_methodの値を、認可コードに紐づけて保存しておく。


Upon receipt of the request at the token endpoint, the server verifies it by calculating the code challenge from the received "code_verifier" and comparing it with the previously associated "code_challenge", after first transforming it according to the "code_challenge_method" method specified by the client.
If the "code_challenge_method" from Section 4.3 was "S256", the received "code_verifier" is hashed by SHA-256, base64url-encoded, and then compared to the "code_challenge", i.e.:

BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) == code_challenge

If the "code_challenge_method" from Section 4.3 was "plain", they are compared directly, i.e.:

code_verifier == code_challenge.

4.1.3. Access Token Requestでリクエストを受けると、サーバーは受け取ったcode_verifierからcode_challengeを計算し、認可コードに紐づけたcode_challengeと比較することによって検証します。