1. 程式人生 > >IdentityServer4原始碼解析_4_令牌發放介面

IdentityServer4原始碼解析_4_令牌發放介面

# 目錄 - [identityserver4原始碼解析_1_專案結構](https://holdengong.com/identityserver4原始碼解析_1_專案結構) - [identityserver4原始碼解析_2_元資料介面](https://holdengong.com/identityserver4原始碼解析_2_元資料介面) - [identityserver4原始碼解析_3_認證介面](https://holdengong.com/identityserver4原始碼解析_3_認證介面) - [identityserver4原始碼解析_4_令牌發放介面](https://holdengong.com/identityserver4原始碼解析_4_令牌發放介面) - [identityserver4原始碼解析_5_查詢使用者資訊介面](https://holdengong.com/identityserver4原始碼解析_5_查詢使用者資訊介面) - [identityserver4原始碼解析_6_結束會話介面](https://holdengong.com/identityserver4原始碼解析_6_結束會話介面) - [identityserver4原始碼解析_7_查詢令牌資訊介面](https://holdengong.com/identityserver4原始碼解析_7_查詢令牌資訊介面) - [identityserver4原始碼解析_8_撤銷令牌介面](https://holdengong.com/identityserver4原始碼解析_8_撤銷令牌介面) # 協議 ## Token介面 oidc服務需要提供token介面,提供AccessToken,IdToken,以及RefreshToken(可選)。在授權碼模式下,token介面必須使用https。 ## 請求 必須使用POST方法,使用x-www-form-urlencoded序列化引數,clientId:clientSecret使用Basic加密放在Authorization頭中 ```http POST /token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb ``` ## 請求校驗 認證服務必須校驗下列內容: - 驗證client是否頒發了祕鑰 - 驗證為該客戶端頒發了授權碼 - 驗證授權碼有效性 - 如果可能的話,驗證授權碼是否被使用過 - 驗證redirect_uri 與發起認證請求時的值一致 ## 成功響應 在收到token請求,並校驗通過之後,認證服務返回成功報文,報文包含了身份令牌和通行令牌。資料格式使用application/json。token_type必須返回Bearer,其他型別token不在本協議範圍內。在OAuth2.0響應報文基礎上,oidc增加了id_tken。所有token包含了token或者其他敏感資訊的響應報文,必須包含以下響應頭。 ```http Cache-Control no-store Pragma no-cache ``` ## 失敗響應 如果認證失敗返回application/json格式錯誤訊息,狀態碼400 ```http HTTP/1.1 400 Bad Request Content-Type: application/json Cache-Control: no-store Pragma: no-cache { "error": "invalid_request" } ``` ## id token校驗 客戶端必須校驗返回的id token, 校驗條件如下。對照這些條件,就可以更懂Microsoft.Authentication.OpenIdConnect裡面的程式碼了,要做的事情很多。 1. 如果id token被加密,使用客戶端註冊時候約定的祕鑰和演算法解密。如果約定了加密方式,id token未被加密,客戶端應該拒絕。 2. 簽發方標識必須與iss宣告一致 3. 客戶端必須校驗aud宣告包含了它的客戶端id,如果id token未返回正確的audience或者反悔了不被新人的audience,應該拒絕 4. 如果id token包含多個audience,需要校驗是否有azp宣告。azp即Authorized party,標識被授權的client。 5. 如果包含azp宣告,客戶端需要校驗其值是否為自己的客戶端id 6. 如果id token由token介面直接頒發給客戶端(授權碼模式就是如此),客戶端必須根據alg引數值的演算法驗證簽名。客戶端必須使用簽發方提供的祕鑰。 7. alg值預設為RS256,客戶端可以在註冊的時候使用id_token_signed_response_alg引數指定配置。 8. 如果jwt的alg頭使用了基於mac地址的加密演算法,如HS256, HS384,HS512,aud宣告中的位元組會用作驗籤。(意思是會把mac地址相關資訊寫在aud宣告上?) 9. The current time MUST be before the time represented by the exp Claim. 當前時間必須早於exp(token過期時間)。 10. iat(簽發時間)可以用於拒絕過早、或者過於頻繁簽發的token,可以用於預防重放攻擊。可接受時間範圍由客戶端自行決定。 11. 如果認證請求包含了nonce引數,客戶端必須交驗認證響應中返回的nonce值是否一致。防止重放攻擊。 12. 如果客戶端請求了acr宣告(Authentication Context Class Reference,認證會話上下文,用於表示當前認證會話),必須交驗acr值是否合法。 13. 如果客戶端請求了auth_time宣告,客戶端應該校驗認證時間是否已經超出,是否需要重新認證。 ## access token校驗 如果id_token中包含了at_hash宣告,需要做下面的校驗。at_hash標明瞭access_token和id_token之間的會話關聯關係,做這個校驗可以防跨站偽造。 1. 用idtoken的alg頭標明的演算法加密access_token,比如alg位RS256,則是用HSA-256演算法加密。 2. 取hash值左邊一般使用base64url加密 3. id token中的at_hash值必須跟上個步驟得到的值一致 校驗規則很多,瞭解一下即可,絕大部分屬於客戶端需要做的部分,絕大部分跟安全有關。這一塊的實現可以參考Microsoft.Authentication.OpenIdConnect,這是客戶端的實現。我們現在看的IdentityServer是認證服務端的實現。 # 原始碼 ## 五種授權模式 有下面幾種授權模式可以請求token介面 - 授權碼模式:最常用的code換token - 混合模式:混合模式是授權碼模式+簡化模式混合使用的方式,在用授權碼code找token介面換通行/身份令牌的邏輯與授權碼模式的邏輯是一樣的。idsv4中,混合模式沒有自己的單獨實現,只是把授權碼+簡化模式的程式碼同時呼叫。 - 客戶端金鑰模式:一般用於完全信任的內部系統,金鑰換取access_token,由於沒有使用者參與,scope包含open_id是非法的 - 使用者名稱密碼模式:一般用於第三方對接、無介面互動場景。即username+password換token/id_token,password不一定是密碼,也可以是驗證碼或其他的什麼東西,這個完全取決於開發自己的實現 - 裝置流模式(略) **注意:簡化模式所有的token都是由認證介面(authorize)一次性返回的,不能使用token介面。** ## 校驗請求方法 token介面僅允許POST方法,Content-Type必須為application/x-www-form-urlencoded,否則丟擲InvalidRequest錯誤。 ```csharp public as