寫在前面
前幾天看了園友的一篇文章被廣泛使用的OAuth2.0的密碼模式已經廢了,放棄吧 被再次提起: Implicit Flow Password Grant,均已被標記為Legacy
,且OAuth2.1裡面已經刪除了,目前OAuth2.1只剩三種flow:
- Authorization Code+ PKCE
- Client Credentials
- Device Code
作為完美踩坑Implicit
和 Password
兩種flow的人,有點感慨,特來發表下自己的愚見;
並帶著以下問題:
- 在SPA(單頁面應用程式Vue等)中不再用Implicit flow,還能用什麼?
- 在Native App和小程式等Public Client中不再用Password flow,還能用什麼?
Implicit 和 Password 的問題
以下均為個人理解,不保證全對
Implicit的問題
- 1、比較容易洩露access_token(下文簡稱token), 比如有的開發者條件不允許,web 服務用http的協議直接上生產(正確是一定要用https);
- 2、token直接暴露在請求裡,如果token許可權不控制好的話使用者能輕而易舉呼叫不該有許可權的介面;
解決方案:
改為用 :Authorization Code + PKCE
Password的問題
園友已經說的很清楚了我總結下;
- 1、最大的問題就是違背了委託授權的原則,比如我的Web服務用微信登入用的Password flow的話,那意思是需要在我的登入頁面裡面填寫微信的賬號和密碼,這眼見的不可思議和不合理吧;
我個人看法:
雖然目前OAuth2最佳實踐中已經明確要求不能使用這種模式,但是 原有已經使用是這種模式的自有App還是可以接著使用的 沒有問題;因為自有App和自有授權中心沒有需要授權,是一起的;
如果是新開發App呢,還是優先考慮:Authorization Code + PKCE,畢竟Password已經是過時的流程了;
思考Authorization Code+ PKCE在Native App使用的問題
先回顧Authorization code Flow
(圖來自)
回顧流程和請求
我這裡是web服務,用的是SPA的客戶端,授權服務用的是IdentityServer4;
假設授權服務是:https://localhost:44356/ 客戶端是:https://localhost:44357/
- A、先判斷登入、未登入先引導使用者去授權伺服器授權(一般是開啟授權方登入頁面);
判斷登入
登入頁面
- C、登入成功返回Authorization code;
登入成功回撥
- D、通過code去授權中心token endpoint換取token;
ok,以上流程後拿到token後面的請求Resource Owner就沒問題了。
Authorization code Flow在Native App中使用有何問題
首先是Authorization code流程裡面的,code引數傳遞通過重定向的方式,在原生App裡一般這樣重定向一般有兩種方式:
- 1、是繫結URL Scheme通過類似app-name://?code=的方法把code傳遞給原生客戶端;
- 2、在本地起個HTTP伺服器通過http://localhost:port/?code=的方法監聽code
這兩種方式都有被第三方惡意應用佔用URL Scheme或者localhost埠擷取code的風險。
另一個問題是,Authorization code code換取token的時候需要app_secret這些;
所以引出我們的PKCE流程;
Authorization Code**+ **PKCE在Native App中使用
PKCE在這篇文章裡面已經講得很清楚了,我簡單總結下:
上文我們已經清楚,Authorization code(簡稱code)流程裡面的,code傳遞給原生App的兩種方式都不安全,那麼引出PKCE的概念:
PKCE
全稱Proof Key for Code Exchange,直譯:用一個Proof key來做Code交換;
解決的問題是,既然你可以攔截我的Authorization code,那我再加一個我有,你沒有的引數(等於是票據、驗證憑據)做code交換條件就行;
PKCE步驟為:
- 1、先隨機生成一串字串叫
code_verifier
; - 2、用
code_challenge_method
方法(sha256等)把code_verifier
加密成code_challenge
; - 3、把
code_challenge
和code_challenge_method
來發起授權請求,生成關聯這兩項值的code; - 4、用code和
code_verifier
去換取token; - 5、授權伺服器返回token,和refresh token(app這個很重要);
我們可以看到,因為我們的code已經關聯code_challenge
和code_challenge_method
,即時攻擊者攔截了也沒用了,因為你沒有code_verifier
,你同樣換不到token;;
最後,可以看到整個PKCE流程設計精妙,已經解決了Code傳參問題;
總結
有了PKCE, 在Native App中使用Code傳參的話直接用原先的方式:
- 1、是繫結URL Scheme通過類似app-name://?code=的方法把code傳遞給原生客戶端;
- 2、在本地起個HTTP伺服器通過http://localhost:port/?code=的方法監聽code
傳遞code就行;
另外還有一種方式,直接在Native App裡面嵌入Webview來傳遞,在攜帶code重定向這個步驟,攔截重定向url,獲取code,換取token;
現在我看到很多App都是這樣做的;
水完,over.
參考
https://www.cnblogs.com/felordcn/p/16011138.html
https://www.cnblogs.com/myshowtime/p/15555538.html
https://medium.com/oauth-2/why-you-should-stop-using-the-oauth-implicit-grant-2436ced1c926