iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
Software Development

從登入到授權-現代軟體的身分架構指南系列 第 18 篇

Day 18|ROPC 為何被禁止:從 OAuth 2.0 安全最佳實務看 OAuth 2.1

  • 分享至 

  • xImage
  •  

前言

上一篇介紹的 Implicit Grant,會讓 Access Token 直接經過瀏覽器前端;今天要看的 **Resource Owner Password Credentials(ROPC)**則更加直接:使用者先把帳號密碼交給 Client,再由 Client 使用這組帳密向 Authorization Server 交換 Token。

ROPC 曾是 OAuth 2.0 定義的核心 Grant Type,主要用於高度受信任的第一方 Client 與舊系統遷移。然而,它讓 Client 直接接觸使用者密碼,增加帳密外洩風險,也難以支援 MFA、SSO 與身份聯合等現代驗證方式。

因此,本文除了介紹 ROPC 的流程與安全問題,也會說明現行規範如何處理這種 Grant Type。OAuth 2.0 安全最佳實務(RFC 9700/BCP 240)已明確規定不得使用 ROPC,OAuth 2.1 草案也不再收錄它。

今天內容涵蓋:

  1. ROPC 是什麼
  2. ROPC 實際怎麼運作
  3. ROPC 的請求與回應參數
  4. 為什麼不應再使用
  5. ROPC 與 Implicit Grant 的差異
  6. OAuth 2.0 Security BCP 與 OAuth 2.1

一、ROPC 是什麼

ROPC 的完整名稱是 Resource Owner Password Credentials Grant。在這個流程中,Resource Owner 通常是使用者;Client 則是使用者操作的應用程式。

使用者不會被重新導向 Authorization Server 的登入頁面,而是直接在 Client 提供的介面輸入帳號密碼。Client 收到後,將這組帳密送到 Authorization Server 的 Token 端點,驗證成功後取得 Access Token,必要時也可能取得 Refresh Token。

這表示 ROPC 與一般 Authorization Code Grant 有一個根本差異:

  • Authorization Code Grant: 帳號密碼只交給 Authorization Server,Client 不會看到。
  • ROPC: 帳號密碼先交給 Client,再由 Client 轉送給 Authorization Server。

ROPC 最初只適用於 Resource Owner 與 Client 之間具有高度信任關係,而且其他授權流程都無法使用的情況。過去有些官方 App、命令列工具或舊式企業系統會採用這種做法,但「第一方 Client」並不代表帳密就能被安全處理;只要 Client 被植入惡意程式碼、錯誤記錄 Log 或保存帳密,使用者帳號就可能遭到接管。


二、ROPC 實際怎麼運作

ROPC 不會使用 Authorization 端點,也沒有瀏覽器重新導向。Client 直接收集使用者帳密,再向 Token 端點提出請求。ROPC:取得 Token 並呼叫受保護 API 的完整流程

https://ithelp.ithome.com.tw/upload/images/20260915/20181928YP11zrzWEG.png

對照上圖,流程如下:

  1. 輸入帳號密碼: 使用者在 Client Application 提供的介面輸入 username 與 password。
  2. 送出 Token Request: Client 將 grant_type=password、username、password 與需要的 scope 傳送至 Authorization Server 的 /token 端點。若 Client 屬於 Confidential Client,還必須透過 client_id 與 client_secret 等方式完成 Client Authentication。
  3. 驗證請求: Authorization Server 驗證使用者帳密,並在需要時確認 Client 身分及要求的權限範圍。
  4. 回傳 Token: 驗證成功後,Authorization Server 回傳 Access Token,並可依政策選擇是否核發 Refresh Token。
  5. 呼叫 API: Client 使用 Access Token 向 Resource Server/API 請求受保護資源。
  6. 驗證 Access Token: Resource Server 檢查 Token 的有效期限、使用對象、權限與其他必要資訊。
  7. 回傳受保護資源: 驗證通過後,Resource Server 將資料或 API Response 回傳給 Client。
  8. 顯示結果: Client 將操作結果或取得的資料呈現給使用者。

這個流程的關鍵問題在於:Client 必須先取得使用者的真實密碼,才能完成 Token 交換。 即使規格要求 Client 在交換後丟棄密碼,Authorization Server 也無法知道 Client 是否曾將密碼寫入 Log、資料庫或其他儲存位置。


三、ROPC 的請求與回應參數

Token Request

Client 會直接向 Authorization Server 的 Token 端點送出請求:

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=gloria&password=A3ddj3w&scope=read
參數 必要性 說明
grant_type 必填 固定填入 password,表示使用 ROPC
username 必填 Resource Owner 的帳號
password 必填 Resource Owner 的密碼
scope 選填 Client 要求的權限範圍

如果 Client 屬於需要驗證身分的 Confidential Client,還必須另外完成 Client Authentication。這項驗證是在確認「哪個 Client 提出請求」,與 username、password 所代表的使用者身分不同。

Token Response

驗證成功後,Authorization Server 會回傳 Access Token,並可依政策選擇是否核發 Refresh Token。回應格式與其他 Grant Type 相同:

{
  "access_token": "2YotnFZFEjr1zCsicMWpAA",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA"
}

四、為什麼不應再使用

ROPC 在 RFC 6749 中原本就是受限使用的 Grant Type。隨著 Authorization Code + PKCE、Device Authorization Grant 與工作負載身分等替代方案成熟,已經沒有必要繼續讓 Client 經手使用者密碼。

主要問題包括:

  1. Client 直接接觸帳號密碼: 惡意程式碼、除錯紀錄、Log、記憶體內容或錯誤的儲存方式,都可能使完整帳密外洩。
  2. 難以支援 MFA: 標準 ROPC 只有一次 Token Request,缺少讓 Authorization Server 插入推播確認、Passkey、生物辨識等互動式驗證的流程。
  3. 無法運用 SSO 與身份聯合: 流程沒有瀏覽器重新導向,因此無法正常使用既有的 SSO Session,也難以支援「使用 Google 登入」等外部 IdP。
  4. 缺少清楚的授權畫面: 使用者只看到 Client 的帳密輸入介面,無法像 Authorization Code Grant 一樣,在 Authorization Server 上確認要求的權限範圍。
  5. 增加釣魚風險: ROPC 讓使用者習慣在 Client 介面輸入主要帳號密碼,更難判斷應用程式是否可信。

⚠️ 現行規範: RFC 9700 對 ROPC 使用的是 MUST NOT,也就是不得使用,而不只是「不建議」。OAuth 2.1 草案也未再納入這個 Grant Type。新系統不應實作 ROPC,既有系統則應停止新增使用情境並規劃遷移。


五、ROPC 與 Implicit Grant 的差異

ROPC 與上一篇的 Implicit Grant 都不再適合新系統,但兩者的問題並不相同:

比較項目 Implicit Grant ROPC
Client 取得的敏感資料 Authorization Server 核發的 Access Token 使用者的帳號密碼
是否使用 Authorization 端點 使用,透過瀏覽器重新導向 不使用,直接呼叫 Token 端點
主要風險 Access Token 在瀏覽器前端流程中外洩或遭到注入 使用者密碼直接暴露給 Client
是否能正常支援 MFA/SSO 可進行互動式登入,但 Token 回傳方式不安全 標準流程缺乏互動空間,難以支援現代 MFA 與 SSO
RFC 9700 的立場 一般情況 SHOULD NOT 使用 MUST NOT 使用
現代替代方案 Authorization Code + PKCE 有使用者時採 Authorization Code + PKCE;無使用者時依情境採 Client Credentials 等機制

簡單來說,Implicit Grant 的問題是「Token 直接經過瀏覽器」;ROPC 的問題則是「密碼直接交給 Client」。 後者暴露的是可長期登入帳號的原始憑證,因此 RFC 9700 對 ROPC 設下更嚴格限制。


六、OAuth 2.0 Security BCP 與 OAuth 2.1

ROPC 從「受限使用」轉為「不得使用」,主要來自 OAuth 2.0 安全規範的持續修正。要理解這項變化,可以先區分 OAuth 2.0 Security BCP 與 OAuth 2.1 的角色。

OAuth 2.0 Security BCP 是什麼

BCP 是 Best Current Practice(現行最佳實務) 的縮寫,用來記錄某項技術目前公認應採用的做法。OAuth 2.0 的安全最佳實務已正式發布為 RFC 9700,同時編入 BCP 240:RFC 9700 是文件編號,BCP 240 則表示它屬於「最佳實務」系列。

它不是新的 Grant Type,而是根據 OAuth 2.0 上線多年後發現的攻擊方式,重新說明現有系統應如何安全實作。內容涵蓋 Authorization Code 遭攔截或注入、Redirect URI 設定過於寬鬆、Refresh Token 外洩,以及 Implicit Grant、ROPC 等舊流程的風險。

OAuth 2.1 是什麼

OAuth 2.1 是以 OAuth 2.0 為基礎,重新整理現行安全做法的規範草案。 它沒有改掉原本的角色與授權架構,而是把 PKCE、Redirect URI 精確比對與 Refresh Token 保護等成熟做法整合進同一份草案,並不再納入 Implicit Grant 與 ROPC。

三者的關係可以整理如下:

文件 定位 主要作用
OAuth 2.0(RFC 6749) 基礎授權框架 定義角色、端點與主要 Grant Type
OAuth 2.0 Security BCP(RFC 9700/BCP 240) 現行安全指引 修正與補充 OAuth 2.0 的安全實作方式
OAuth 2.1 草案 規範整合 將 OAuth 2.0 與後續安全最佳實務收斂成較一致的基準

OAuth 2.0 定義授權框架;RFC 9700 說明現在應如何安全使用;OAuth 2.1 則嘗試將這些做法整合成一份新草案。 OAuth 2.1 目前尚未成為正式 RFC,但既有系統現在就能依照 RFC 9700 改善 OAuth 2.0 的實作。


小結

**ROPC 看似只是省略重新導向,直接用帳密交換 Token;真正的問題卻在於 Client 必須先取得使用者密碼。**只要 Client 的程式碼、Log 或儲存方式出現問題,外洩的就可能是可以直接登入帳號的原始憑證。

本文可整理成三個重點:

  • 流程設計: ROPC 讓 Client 代替 Authorization Server 收集帳密,因此難以清楚隔離 Client 與使用者憑證。
  • 現行安全立場: OAuth 2.0 安全最佳實務已收錄為 RFC 9700/BCP 240,並以 MUST NOT 明確規定不得使用 ROPC。
  • 後續規範方向: OAuth 2.1 沿用 OAuth 2.0 的核心架構,但將現行安全做法整理成新的草案,並未再納入 ROPC 與 Implicit Grant。

新系統有使用者參與時,應改用 Authorization Code + PKCE;沒有使用者參與時,則應依情境選擇 Client Credentials 或工作負載身分等機制。既有 ROPC 系統也應停止增加新的使用情境,並逐步規劃遷移。

下一篇將介紹 Passkey 為什麼安全,從 OAuth 的授權流程回到身份驗證本身,說明 Passkey 如何利用挑戰與數位簽章,在不傳送密碼的情況下完成驗證。


參考資源


上一篇
Day 17|Implicit Grant:為何不再建議使用,並改採 Authorization Code + PKCE
下一篇
Day 19|Passkey 為什麼安全:從 Challenge-簽章機制看安全性
系列文
從登入到授權-現代軟體的身分架構指南 共 22 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言