原文:https://leastprivilege.com/2017/11/15/missing-claims-in-the-asp-net-core-2-openid-connect-handler/發佈於:2017年11月環境:ASP.NET Core 2.0 原文:https://leastp ...
原文:https://leastprivilege.com/2017/11/15/missing-claims-in-the-asp-net-core-2-openid-connect-handler/
發佈於:2017年11月
環境:ASP.NET Core 2.0
通過OIDC provider 把Claims映射到ClaimsPrincipal這一步驟,在ASP.NET Core 2中新的OpenID Connect handler具有不同的行為。
這是特別令人困惑和難以診斷的,因為這裡有幾個部件聚集在一起。我們來看一下。
您可以使用我的示例OIDC客戶端來觀察到相同的結果。
將標準claim類型映射到Microsoft專有claim類型
一件令人煩惱的事情是微軟仍然認為他們知道什麼是最適合你的,將OIDC標準聲明映射到其專有聲明。
可以通過清除Microsoft JWT令牌處理程式上的入站聲明類型映射來優雅地修複:
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
基本的OpenId Connect授權請求
接下來,讓我們從客戶端請求openid scope的場景開始。
首先令人困惑的是Microsoft使用openid和profile scope預先在OpenIdConnectOptions上填充了Scope集合。這意味著如果你只想請求openid,你首先需要清除Scope集合,然後手動添加openid。
services.AddAuthentication(options => { options.DefaultScheme = "Cookies"; options.DefaultChallengeScheme = "oidc"; }) .AddCookie("Cookies", options => { options.AccessDeniedPath = "/account/denied"; }) .AddOpenIdConnect("oidc", options => { options.Authority = "https://demo.identityserver.io"; options.ClientId = "server.hybrid"; options.ClientSecret = "secret"; options.ResponseType = "code id_token"; options.SaveTokens = true; options.Scope.Clear(); options.Scope.Add("openid"); options.TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name", RoleClaimType = "role" }; });
使用ASP.NET Core v1處理程式,將返回以下聲明:nbf,exp,iss,aud,nonce,iat,c_hash,sid,sub,auth_time,idp,amr。
在V2中我們只能得到sid,sub和idp。發生了什麼?
微軟在其OpenID Connect handler中添加了一個名為ClaimActions的新概念。Claim actions用來實現自外部provider的claim如何映射(或不)到您的ClaimsPrincipal中的claim。查看OpenIdConnectOptions的構造函數,您可以看到,處理程式現在預設會跳過以下聲明:
ClaimActions.DeleteClaim("nonce"); ClaimActions.DeleteClaim("aud"); ClaimActions.DeleteClaim("azp"); ClaimActions.DeleteClaim("acr"); ClaimActions.DeleteClaim("amr"); ClaimActions.DeleteClaim("iss"); ClaimActions.DeleteClaim("iat"); ClaimActions.DeleteClaim("nbf"); ClaimActions.DeleteClaim("exp"); ClaimActions.DeleteClaim("at_hash"); ClaimActions.DeleteClaim("c_hash"); ClaimActions.DeleteClaim("auth_time"); ClaimActions.DeleteClaim("ipaddr"); ClaimActions.DeleteClaim("platf"); ClaimActions.DeleteClaim("ver");
如果您想“取消”跳過某項聲明,則需要在設置handler時刪除特定聲明。以下是獲取amr聲明的非常直觀的語法:
options.ClaimActions.Remove("amr");
從OIDC provider請求更多的Claim
當你要求更多的範圍時,例如個人資料或自定義範圍導致更多索賠,還有另一個令人困惑的細節需要註意。
根據OIDC協議中的response_type,某些聲明通過id_token進行傳輸,有些通過userinfo端點進行傳輸。我在這裡寫了關於此細節的文章。
因此,首先您需要在處理程式中啟用對userinfo端點的支持:
options.GetClaimsFromUserInfoEndpoint = true;
如果聲明由userinfo返回,ClaimsActions將用於從返回的JSON文檔映射claim到principal。這裡使用以下預設設置:
ClaimActions.MapUniqueJsonKey("sub", "sub"); ClaimActions.MapUniqueJsonKey("name", "name"); ClaimActions.MapUniqueJsonKey("given_name", "given_name"); ClaimActions.MapUniqueJsonKey("family_name", "family_name"); ClaimActions.MapUniqueJsonKey("profile", "profile"); ClaimActions.MapUniqueJsonKey("email", "email");
如果您向您的客戶發送的不屬於上述列表的claim,它會被忽略,您需要進行明確的映射。例如您希望客戶端通過userinfo(標準OIDC聲明之一,但不幸未由Microsoft映射)獲得website claim - 您需要自行添加映射:
options.ClaimActions.MapUniqueJsonKey("website", "website");
這同樣適用於您通過userinfo返回的任何其他聲明。
我希望這有幫助。簡而言之 – 你應該明確的知道你的映射,因為我相信這些預設映射將在可能會發生變化,這將導致您的客戶端應用程式出現意外行為。