OAuth2 Proof Key for Code Exchange(PKCE) flow

PKCE 是 Authorization code flow 的延伸 implicit flow 加強版

PKCE

code flow 的一種延伸,透過密碼學的方式,確保即時被惡意攔截 Authorization code,也無法向 Authorization Server 換到 Access Token 適合用在沒辦法安全的儲存 client_secret 的情況,像是 native 和 single-page applications(SPA)

名詞

  • code_verifier - 驗證 code_challenge,Access Token Request 必須一起帶入驗證
  • code_challenge - 從 code verifier 產生的 challenge,進行Authorization Request,產生 Authorization url 時要加上去
  • code_challenge_method - code challenge 的方法

Flow

 Protocol Flow
                                                 +-------------------+
                                                 |   Authz Server    |
       +--------+                                | +---------------+ |
       |        |--(A)- Authorization Request ---->|               | |
       |        |       + t(code_verifier), t_m  | | Authorization | |
       |        |                                | |    Endpoint   | |
       |        |<-(B)---- Authorization Code -----|               | |
       |        |                                | +---------------+ |
       | Client |                                |                   |
       |        |                                | +---------------+ |
       |        |--(C)-- Access Token Request ---->|               | |
       |        |          + code_verifier       | |    Token      | |
       |        |                                | |   Endpoint    | |
       |        |<-(D)------ Access Token ---------|               | |
       +--------+                                | +---------------+ |
                                                 +-------------------+

Code

$verifier_bytes = random_bytes(64);
$code_verifier = rtrim(strtr(base64_encode($verifier_bytes), "+/", "-_"), "=");

$challenge_bytes = hash('sha256', $code_verifier, true);
$code_challenge = rtrim(strtr(base64_encode($challenge_bytes), "+/", "-_"), "=");

create authorization_url

$authorization_url = 'https://' . AUTHORIZATION_HOST . "/oauth2/auth?code_challenage=$code_challenge
response_type=code&client_id=$client_id&redirect_uri=$redirect_uri&scope=$scope&state=$state&code_challenge_method=S256"

get access token

POST /oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=$code&client_id=$client_id&code_verifier=$code_verifier

reference