簡體   English   中英

無法使用 AAD/Microsoft-Identity id_token 上的 System.IdentityModel.Tokens.Jwt 庫驗證簽名

[英]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.ProtocolsMicrosoft.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM