基於Identity Server4的OAuth 2.0授權總結(4)- PKCE in Authorization Code mode
授權碼模式的過程大致是如下圖所示:
在獲取token的時候需要提供如下資訊:
1. code
2. redirect_url,
3. client_id,client secret
第二項和第三項其實是用來對通過code獲取token的client的合法性進行驗證。其中最核心的應該是client secret。通過他可以解決如下問題:
對獲取token的client進行合法性驗證。secret是在Authorization Server上註冊client的時候設定的,只有client自己知道,因此可以對client進行驗證。
這樣的話,即使code因為某種原因洩露了,沒有secret也無法獲取到token。從而提升了安全性。在傳統的Web應用中,token的獲取是發生在後端,因此secret也是儲存在後端。這樣是可行的。但是對於現在比較流行的SPA應用,token的獲取是發生在瀏覽器端,是一個公開的環境。這個方法就不可行了,因為secret不可能儲存在一個公開的環境中。
在這個場景下,就需要用PKCE(Proof Key for Code Exchange)來保證整個過程的安全性了。
PKCE主要是通過在授權的過程中增加了code_challenge和code_verifier兩個元素來對整個流程進行驗證,防止code被第三方擷取的情況。具體流程如下:
這裡面最核心的其實就是在authorize請求中增加了code_challenge引數,在token請求中增加了code_verifier引數。這兩個引數最終都是依賴於一個client生成的隨機字串。
Random String:是一個Client端生成的隨機字串(由字母,數字,- ,. ,_ ,~ 組成)
code_challenge引數的生成演算法為:BASE64URL-ENCODE(SHA256(ASCII(Random String)))。
過程解析:
1. 在申請授權時(authorize請求),client,生成隨機字串並基於它生成code_challenge傳給authorization server.(這個過程中random string 在網路中不會被暴露,因為對其進行了hash)。
2. authorization server生成授權碼後,會將code_challenge儲存起來,並與授權碼關聯。
3. 在通過授權碼獲取token的過程中,client會將隨機字串(code_verifier)傳給authorization server
4. authorization server會將code_verifier進行與第一步相同演算法進行計算得到新的code_challenge
5. authorization server將第四步中的code_challenge與第一步中的原始code_challenge進行比較,如果相同則認為申請授權的源與用code獲取token的源為同一來源。(即code沒有被第三方擷取而冒用)
實現:
服務端
Identity Server 4預設支援PKCE模式,但是是可選的(就是說client也可以不使用該方式)。如需強制client使用PKCE,只需在定義Client時將Client配置成RequirePkce即可。
new Client { ClientId = "js", RequireConsent = false, AllowedGrantTypes = GrantTypes.Code, RequireClientSecret = false, RequirePkce = true, AllowAccessTokensViaBrowser = false, AlwaysIncludeUserClaimsInIdToken = true, RedirectUris = new List<string>{"http://localhost:3000/callback.html"}, AllowedScopes = new List<string>{"api", IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Email, "profile"}, PostLogoutRedirectUris = new List<string>{ "http://localhost:3000" } },
客戶端
客戶端oidc-client庫預設會採用PKCE,也不需要額外的配置。
總結
1. 傳統Web應用的client secret是儲存在後端,不會被洩露。因而可以用於驗證client,保護code被冒用的情況。對於public client(SPA),用於傳統Web應用的secret方式不再有效。
2. PKCE通過在每個授權請求過程中新增一個隨機secret,達到了了防止授權碼被冒用,同時secret不被洩露。
3. 對於public client, PKCE目前是推薦的認證模式。