9 客户端认证方式 之 PKCE
開講之前需要先補充點預備知識:客戶端的類型 https://oauth.net/2/client-types
OAuth2 定義了兩種類型的客戶端:機密客戶端(confidential clients)和公共客戶端(public clients)。
- 機密客戶端(confidential clients) 指的是能夠安全地保存其 client_secret 的應用程序。例如我們的后臺服務,將 client_secret 保存在配置中,和授權服務器交互都是后臺操作,最終給到前端的只是 token,這樣client_secret是安全的。
- 公共客戶端(public clients) 指的是無法安全地保存 client_secret 的應用程序。例如運行在瀏覽器的純前端的應用程序,無論如何,將client_secret暴露在瀏覽器,都是不安全的。
ok,鋪墊完了,開講。
none
由于公共客戶端沒法安全的保存 client_secret,所以在實際應用中,公共客戶端 連 client_secret 都沒必要存了,所以SpringAuthorizationServer定義一個 none 方式來表示這種情況。那這意味著公共客戶端就不用認證了嗎?答案是否定的!OAuth2 引入了另一個驗證的機制 PKCE(Proof Key for Code Exchange)。
PKCE(Proof Key for Code Exchange)
https://oauth.net/2/pkce/
PKCE 是授權碼流程的擴展,用于防止 CSRF 和授權碼(code)注入攻擊。 所以 PKCE 一般都伴隨著授權碼模式使用,可稱之為 增強版授權碼流程,又稱 Authorization Code with PKCE Flow。
原來的授權碼流程 如下:
\1. 客戶端發起授權請求 -> 2. 用戶授權 -> 3. 客戶端拿到code -> 4. 客戶端通過code獲取token
授權碼 + PKCE 流程 對原來流程做了如下增強:
- 對于客戶端而言
- 步驟1的改造:客戶端隨機生成一個字符串(稱之為明文),通過摘要算法生成一個密文,發起授權請求時,攜帶該密文和摘要算法。
- 步驟4的改造:客戶端通過code獲取token時,需要攜帶上述明文。
- 對于授權服務器而言
- 步驟1的改造:授權服務器需要記錄客戶端此次請求的密文和摘要算法。
- 步驟4的改造:授權服務器收到客戶端的明文,使用同樣的摘要算法生成一個密文,和步驟1的密文做對比,如果相同,才算通過驗證。
一圖勝千言:
整個示例吧,再說可能都要暈了。
示例
- 步驟1(發起授權)多傳的pkce參數:
code_challenge client生成的密文
code_challenge_method:摘要算法,固定值 S256 - 步驟4(獲取Token)多傳的pkce參數:
code_verifier:明文
client_id:客戶端id
環境準備
授權服務器
同樣的,基于 快速搭建一個授權服務器 文章中的示例,修改 SecurityConfiguration 中 registeredClientRepository() 方法,如下:
@Beanpublic RegisteredClientRepository registeredClientRepository() {RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()).clientId("client1")// 公共客戶端,不需要密鑰 // .clientSecret("01234567890123456789012345678912").clientAuthenticationMethod(ClientAuthenticationMethod.NONE).clientSettings(ClientSettings.builder()// 公共客戶端(NONE方式認證)必須開啟 PKCE 流程.requireProofKey(true)// 授權碼模式需要用戶手動授權!false表示默認通過.requireAuthorizationConsent(true).build()).authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri("https://cn.bing.com").scope("read").build();return new InMemoryRegisteredClientRepository(registeredClient);}測試
綜上,便是 授權碼+PKCE 的流程。
源碼分析
這里涉及到有兩處代碼,一個授權請求是需要記錄 密文和摘要算法,一個是獲取token請求,計算明文和原來密文做驗證。
授權請求的處理類 OAuth2AuthorizationCodeRequestAuthenticationProvider
雖然經過層層包裝,但最終的效果就是 code_challenge、code_challenge_method 參數會被記錄起來,并和 授權碼(code)關聯(后續通過code才能取回密文和摘要算法做驗證)。暫時不用深究其他細節。
獲取Token請求
獲取token請求,才是真正做校驗的地方。會涉及如下關鍵類:
PublicClientAuthenticationConverter
校驗 code_verifier 參數是否存在,若不存在則報錯。
PublicClientAuthenticationProvider
核心邏輯就是:取出授權請求保存下來的code_challenge(密文)、code_challenge_method(摘要算法),和 code_verifier(明文)做校驗。其入口代碼如下:
委托給 CodeVerifierAuthenticator 處理
核心驗證邏輯就是用相同的摘要算法計算明文,生成一個密文和 原來的密文對比。
以上,便是 pkce 整個流程。其他細節,讀者可自行擴展了解啦啦啦~
end
總結
以上是生活随笔為你收集整理的9 客户端认证方式 之 PKCE的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SVG绘画
- 下一篇: 最凄美的爱情故事,让每对爱人更长久的文章