跳到內容

Implicit Flow

Implicit Flow 由 RFC 6749 Section 4.2 定義,是 OAuth 2.0 最初為瀏覽器端應用設計的授權流程。

OAuth 2.0 的核心流程是 Authorization Code Flow——Authorization Server 先核發一個短效的授權碼,Client 再用 client_secret 到後端換取 Access Token。這個設計讓 Token 從不暴露在瀏覽器中。

但 2012 年前後,Single Page Application(SPA)開始普及。SPA 沒有後端伺服器,無法安全儲存 client_secret,也沒有地方執行 Token 交換——整個應用都在使用者的瀏覽器裡跑

當時的解法是 Implicit Flow:跳過授權碼交換步驟,讓 Authorization Server 直接把 Access Token 放在 redirect URL 的 fragment 中。瀏覽器不會把 fragment 傳送到伺服器,因此 Token 不會出現在 Client 的伺服器日誌,只有頁面上的 JavaScript 能讀取。

sequenceDiagram
    actor User as 使用者 Browser
    participant AS as Authorization Server

    User->>AS: 1. 授權請求(response_type=token)
    AS->>User: 2. 使用者登入並授權
    AS-->>User: 3. Redirect to callback#access_token=...
    Note over User: 4. JS 從 window.location.hash 讀取 Token
    User->>User: 5. 直接使用 Access Token

Client 將使用者導向 Authorization Server,response_type 改為 token

https://auth.example.com/authorize?
response_type=token
&client_id=YOUR_CLIENT_ID
&redirect_uri=https://app.example.com/callback
&scope=read:profile
&state=RANDOM_STATE_VALUE

注意:沒有 code_challenge,也不需要 client_secret

使用者在 Authorization Server 完成登入與授權,流程與 Authorization Code Flow 相同。

Authorization Server 不核發授權碼,直接把 Access Token 放在 redirect URL 的 fragment 中回傳:

https://app.example.com/callback
#access_token=eyJhbGciOiJSUzI1NiJ9...
&token_type=Bearer
&expires_in=3600
&scope=read:profile
&state=RANDOM_STATE_VALUE

Fragment(# 之後的部分)是純前端的概念,瀏覽器不會把它傳送到伺服器。

頁面的 JavaScript 從 window.location.hash 解析 Token:

const params = new URLSearchParams(window.location.hash.substring(1));
const accessToken = params.get('access_token');

之後直接用這個 Token 呼叫 API,不需要任何後端介入。

相較 Authorization Code Flow,Implicit Flow 少了一次 Token 交換的往返,SPA 可以完全在前端完成授權,不需要任何後端伺服器。

Implicit Flow 刻意不核發 Refresh Token——因為 Token 已經暴露在瀏覽器中,若再提供長效的 Refresh Token,洩漏後果更嚴重。這意味著 Access Token 過期後,使用者必須重新授權。

由於沒有 Refresh Token,Authorization Server 通常會核發較短效的 Access Token(幾十分鐘),降低洩漏後的損害窗口,但也增加了重新授權的頻率。

Implicit Flow 的核心問題是 Token 直接暴露在瀏覽器端,對應 攻擊者模型 中的 A3(授權回應讀取者)。

Token 可被頁面上的 JavaScript 讀取

Section titled “Token 可被頁面上的 JavaScript 讀取”

window.location.hash 對同源的所有 JavaScript 都可見。如果頁面中有 XSS 漏洞,或引入了惡意的第三方套件,攻擊者可以直接讀取 Token。

瀏覽器在發出請求時,可能將前一頁的完整 URL(含 fragment)附在 Referer Header 中送出。如果頁面中嵌入了第三方資源(廣告、分析腳本、字體服務),這些外部請求可能帶著含有 Token 的 Referer。

fragment 是 URL 的一部分,瀏覽器歷史記錄會保留含有 Token 的完整 URL。使用者的瀏覽器歷史、公用電腦,乃至於瀏覽器外掛程式,都可能成為 Token 洩漏管道。

Authorization Code Flow 使用 code + client_secret(或 PKCE 的 code_verifier)換取 Token,Authorization Server 可以確認請求方的身分。Implicit Flow 跳過了這個步驟,任何人只要拿到 Token 就能直接使用,無法追溯 Token 的合法持有者。

PKCE 解決了 Implicit Flow 試圖解決的問題:SPA 不需要 client_secret,仍可安全地使用 Authorization Code Flow。PKCE 透過一次性的 code_verifiercode_challenge 來保護授權碼,Token 不會出現在 URL 中。