[英]Cannot validate signature using System.IdentityModel.Tokens.Jwt library on AAD/Microsoft-Identity id_token
我在 Azure 中使用 WebApp,並啟用了 Azure Active Directory 身份驗證,並且正在從此處的/.auth/me頁面中提取id_token :
根據我的理解,當我將其粘貼到 JWT.io 時,它通過在https://login.microsoftonline.com/{tenantId}/v2.0/.well-known/openid-configuration查找 OpenId 配置來驗證簽名
然后使用jwks_uri ( https://login.microsoftonline.com/{tenantId}/discovery/v2.0/keys ) 從 JWT header 中找到基於孩子的公共簽名密鑰 (x5c Array):
但是,當我嘗試在 C# 中復制此場景時,我無法使用System.IdentityModel.Tokens.Jwt庫驗證簽名。
以下是我的一些嘗試和結果:
試圖
var idToken = "{id_token}";
var signingKey = "{x5c[0]}";
SecurityToken validatedToken;
ClaimsPrincipal claimsPrincipal;
var handler = new JwtSecurityTokenHandler();
var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("-----BEGIN CERTIFICATE-----\n" + signingKey + "\n-----END CERTIFICATE-----"));
var tokenValidationParameters = new TokenValidationParameters()
{
IssuerSigningKey = symmetricSecurityKey,
ValidateIssuerSigningKey = true,
ValidateLifetime = false,
ValidateAudience = false,
ValidateIssuer = false
};
try
{
claimsPrincipal = handler.ValidateToken(idToken, tokenValidationParameters, out validatedToken);
Console.WriteLine($"{claimsPrincipal.Identity.Name}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
結果
IDX10501:簽名驗證失敗。 無法匹配密鑰:孩子:'System.String'。 捕獲異常:'System.Text.StringBuilder'。 令牌:'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'。
試圖
var kid = "l3sQ-50cCH4xBVZLHTGwnSR7680";
var idToken = "{id_token}";
var signingKey = "{x5c[0]}";
SecurityToken validatedToken;
ClaimsPrincipal claimsPrincipal;
var handler = new JwtSecurityTokenHandler();
var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("-----BEGIN CERTIFICATE-----\n" + signingKey + "\n-----END CERTIFICATE-----")) { KeyId = kid, };
var tokenValidationParameters = new TokenValidationParameters()
{
IssuerSigningKey = symmetricSecurityKey,
ValidateIssuerSigningKey = true,
ValidateLifetime = false,
ValidateAudience = false,
ValidateIssuer = false
};
try
{
claimsPrincipal = handler.ValidateToken(idToken, tokenValidationParameters, out validatedToken);
Console.WriteLine($"{claimsPrincipal.Identity.Name}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
結果
IDX10511:簽名驗證失敗。 嘗試過的鍵:“System.Text.StringBuilder”。 孩子:'System.String'。 捕獲異常:'System.Text.StringBuilder'。 令牌:'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'。
我還嘗試了兩次嘗試,但沒有向簽名密鑰添加“-----BEGIN CERTIFICATE-----\n”和“\n-----END CERTIFICATE-----” ,結果相同以及嘗試使用ASCII編碼而不是UTF8 。
====更新====
我能夠使用Microsoft.IdentityModel.Protocols和Microsoft.IdentityModel.Protocols.OpenIdConnect庫來驗證令牌,使用以下代碼創建簽名密鑰:
var issuer = jwtToken.Issuer;
var audiences = jwtToken.Audiences;
var issuerOpenIdUri = $"{issuer}/.well-known/openid-configuration";
string stsDiscoveryEndpoint = issuerOpenIdUri;
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
OpenIdConnectConfiguration config = configManager.GetConfigurationAsync().Result;
...然后使用OpenIdConnectConfiguration將密鑰分配給TokenValidatetionParameters :
var tokenValidationParameters = new TokenValidationParameters()
{
ValidAudiences = audiences,
ValidIssuer = issuer,
IssuerSigningKeys = config.SigningKeys,
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
ValidateAudience = true,
ValidateIssuer = true
};
但是我仍然很好奇為什么我最初的嘗試行不通。 我想更好地了解幕后發生的事情。
Microsoft.IdentityModel.Tokens.X509SecurityKey 在其 KeyId 中使用 base 16 中的證書指紋。 Azure Active Directory KeyId 使用 base 64 中的證書指紋。要使用與 Azure Active Directory 使用的密鑰 ID 格式相同的密鑰 ID 格式,可以(按照您的方式)使用 Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever 並使用以這種方式簽署密鑰
myTokenValidationParameters.IssuerSigningKeys = myOpenIdConnectionConfiguration.SigningKeys;
當“aud”聲明與受眾不匹配時,也可能會發生錯誤,受眾只是客戶端 ID,可以通過在 AAD 和代碼中提供適當的范圍以及適當的受眾和 scope 並通過授予同意來緩解。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.