OAuth 2.1 是 OAuth 2.0 的下一個版本, OAuth 2.1 根據最佳安全實踐(BCP), 目前是第18個版本,對 OAuth 2.0 協議進行整合和精簡, 移除不安全的授權流程, 併發布了 OAuth 2.1 規範草案, 下面列出了和 OAuth 2.0 相比的主要區別。
⚡ 推薦使用 Authorization Code + PKCE
根據 OAuth 2.0 安全最佳實踐(Security Best Current Practices) 2.1.1 章節
授權碼 (Authorization Code) 模式大家都很熟悉了,也是最安全的授權流程, 那 PKCE 又是什麼呢? PKCE 全稱是 Proof Key for Code Exchange, 在 2015 年釋出為 RFC 7636, 我們知道, 授權碼模式雖好, 但是它不能給公開的客戶端用, 因為公開的客戶端沒有能力儲存好祕鑰(client_secret), 所以在此之前, 對於公開的客戶端, 只能使用隱式模式和密碼模式, PKCE 就是為了解決這個問題而出現的, 另外它也可以防範授權碼攔截攻擊, 實際上它的原理是客戶端提供一個自建立的證明給授權伺服器, 授權伺服器通過它來驗證客戶端,把訪問令牌(access_token) 頒發給真實的客戶端而不是偽造的,下邊是 Authorization Code + PKCE 的授權流程圖。
⚡隱式授權( Implicit Grant)已棄用
根據 OAuth 2.0 安全最佳實踐(Security Best Current Practices) 2.1.2 章節
在 OAuth 2.1 規範草案中, 授權模式中已經找不到隱式授權(Implicit Grant), 我們知道, 隱式授權是 OAuth 2.0 中的授權模式, 是授權碼模式的簡化版本, 使用者同意授權後, 直接就能返回訪問令牌 access_token, 同時這種也是不安全的。
現在您可以考慮替換為 Authorization Code + PKCE 的授權模式。
⚡ 密碼授權 (Resource Owner Password Credentials Grant)已棄用
根據 OAuth 2.0 安全最佳實踐(Security Best Current Practices) 2.4 章節
在 OAuth 2.1 規範草案中, 密碼授權也被移除, 實際上這種授權模式在 OAuth 2.0中都是不推薦使用的, 密碼授權的流程是, 使用者把賬號密碼告訴客戶端, 然後客戶端再去申請訪問令牌, 這種模式只在使用者和客戶端高度信任的情況下才使用。
試想一下, 在你手機上有一個網易雲音樂的APP, 現在要使用qq賬號登入, 這時網易雲音樂說, 你把qq賬號密碼告訴我就行了, 我拿著你的賬號密碼去QQ那邊登入, 這就很離譜了!
正確的做法是, 使用者在網易雲音樂要使用qq登入, 如果使用者也安裝了qq 的客戶端, 應該喚起qq應用, 在qq頁面完成授權操作, 然後返回到網易雲音樂。如果使用者沒有安裝qq客戶端應用, 喚起瀏覽器, 引導使用者去qq的授權頁面, 使用者授權完成後, 返回到網易雲音樂。
請注意, OAuth 是專門為委託授權而設計的,為了讓第三方應用使用授權, 它不是為身份驗證而設計的, 而 OpenID Connect(建立在 OAuth 之上)是專為身份驗證而設計, 所以, 在使用 OAuth 授權協議時, 你需要知道你使用的客戶端是第三方應用程式還是第一方應用,這很重要!因為 OAuth 2.1 已經不支援第一方應用授權!
現在您可以考慮使用 Authorization Code + PKCE 替換之前的密碼授權模式。
⚡ 使用 access_token 時, 不應該通過 URL 傳遞 token
根據 OAuth 2.0 安全最佳實踐(Security Best Current Practices) 4.3.2 章節
在使用 access_token 時, 您不應該把token放到URL中, 第一, 瀏覽器位址列本來就是暴露的, 第二, 可以檢視瀏覽記錄,找到 access_token。
正確的做法是, 把 access_token 放到 Http header 或者是 POST body 中。
⚡ 重新整理令牌 (Refresh Token) 應該是一次性的
根據 OAuth 2.0 安全最佳實踐(Security Best Current Practices) 4.13.2 章節
access_token 訪問令牌, refresh_token 重新整理令牌, 重新整理令牌可以在一段時間內獲取訪問令牌, 平衡了使用者體驗和安全性, 在 OAuth 2.1 中, refresh_token 應該是一次性的, 用過後失效, 使用 refresh_token 獲取access_token時, 還可以返回一個新的 refresh_token。
⚡ 回撥地址(Redirect URI)應該精確匹配
根據 OAuth 2.0 安全最佳實踐(Security Best Current Practices) 4.1.3 章節
在 OAuth 2.0 的授權碼流程中, 需要設定一個回撥地址 redirect_uri, 如下
https://www.authorization-server.com/oauth2/authorize?
response_type=code
&client_id=s6BhdRkqt3
&scope=user
&state=8b815ab1d177f5c8e
&redirect_uri=https://www.client.com/callback
假如有三個不同的客戶端
- a.client.com
- b.client.com
- c.client.com
這時可能會使用一個萬用字元的 redirect_uri, 比如 *.client.com, 這樣會有什麼風險呢? 實際上, 惡意程式有機會篡改 redirect_uri, 假設惡意程式的域名是 https://attacker.com, 然後把 redirect_uri 改成 https://attacker.com/.client.com, 這樣授權碼就傳送給了惡意程式。
References
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-04
OAuth 2.0 Security Best Current Practice draft-ietf-oauth-security-topics-18
https://fusionauth.io/learn/expert-advice/oauth/differences-between-oauth-2-oauth-2-1