IDX10501:签名验证失败。尝试的密钥:'System.IdentityModel.Tokens.X509AsymmetricSecurityKey'

Posted

技术标签:

【中文标题】IDX10501:签名验证失败。尝试的密钥:\'System.IdentityModel.Tokens.X509AsymmetricSecurityKey\'【英文标题】:IDX10501: Signature validation failed. Key tried: 'System.IdentityModel.Tokens.X509AsymmetricSecurityKey'IDX10501:签名验证失败。尝试的密钥:'System.IdentityModel.Tokens.X509AsymmetricSecurityKey' 【发布时间】:2017-12-31 04:02:50 【问题描述】:

我正在尝试验证来自 Azure 的令牌。我使用 Adal.js 来获取令牌。 当我尝试验证令牌时,每次都会收到相同的错误消息:

IDX10501:签名验证失败。尝试的密钥:'System.IdentityModel.Tokens.X509AsymmetricSecurityKey'。 令牌:'"typ":"JWT",...

消息中省略的令牌看起来就像我在客户端上看到的一样,并且来自以下 3 个 url 的信息似乎已正确添加到数据结构中,即我可以看到填充的字段是我所期望的查看下面的链接和我在客户端上的令牌。

https://login.windows.net/id.onmicrosoft.com/federationmetadata/2007-06/federationmetadata.xml

https://login.microsoftonline.com/id.onmicrosoft.com/.well-known/openid-configuration

https://login.microsoftonline.com/common/discovery/keys

但每当我到达最后一行 ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(... 时,我总是会遇到同样的错误。

关于如何使令牌验证的任何想法?

        // Get the jwt bearer token from the authorization header
        string jwtToken = null;
        AuthenticationHeaderValue authHeader = request.Headers.Authorization;
        if (authHeader != null)
        
            jwtToken = authHeader.Parameter;
        

        string issuer;
        List<SecurityToken> signingTokens;

        // The issuer and signingTokens are cached for 24 hours. They are updated if any of the conditions in the if condition is true.            
        if (DateTime.UtcNow.Subtract(_stsMetadataRetrievalTime).TotalHours > 24 || string.IsNullOrEmpty(_issuer) || _signingTokens == null)
        
            // Get tenant information that's used to validate incoming jwt tokens
            string stsDiscoveryEndpoint = string.Format("0/.well-known/openid-configuration", authority);
            ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint);
            OpenIdConnectConfiguration config = await configManager.GetConfigurationAsync();
            _issuer = config.Issuer;
            _signingTokens = config.SigningTokens.ToList();

            _stsMetadataRetrievalTime = DateTime.UtcNow;
        

        issuer = _issuer;
        signingTokens = _signingTokens;

        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

        TokenValidationParameters validationParameters = new TokenValidationParameters
        
            ValidAudience = audience,
            ValidIssuer = issuer,
            IssuerSigningTokens = signingTokens,
            CertificateValidator = X509CertificateValidator.None
        ;

        try 
            // Validate token.
            SecurityToken validatedToken = new JwtSecurityToken();
            ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(jwtToken, validationParameters, out validatedToken);
           

更新 以防在初始化客户端和服务器时我缺少一些东西。

Adal.js 初始化选项是:

    var endpoints = 
        "https://graph.windows.net": "https://graph.windows.net"
    ;
    var configOptions = 
        tenant: "<ad>.onmicrosoft.com", // Optional by default, it sends common
        clientId: "<app ID from azure portal>",
        postLogoutRedirectUri: window.location.origin,
        endpoints: endpoints,
    
    window.authContext = new AuthenticationContext(configOptions);

服务器初始化选项是:

    static string aadInstance = "https://login.microsoftonline.com/0";
    static string tenant = "<ad>.onmicrosoft.com";
    static string audience = "<app ID from azure portal>";
    string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);

    static string scopeClaimType = "http://schemas.microsoft.com/identity/claims/scope";

【问题讨论】:

当您在令牌处look 时,标头中的kid 是否与login.microsoftonline.com/common/discovery/keys 中列出的任何kids 匹配? 是的,它们匹配 【参考方案1】:

您想实现什么场景?您拥有的令牌用于 AAD Graph API,您无需对其进行验证。使用该令牌执行 api 调用时,microsoft graph 服务器端将验证访问令牌。

此外,在您的服务器端初始化选项中,您将受众设置为来自 azure 门户的应用 ID,这意味着在验证访问令牌时,访问令牌的受众应该与来自 azure 门户的应用 ID 匹配,但访问的受众令牌是 https://graph.windows.net,因为您正在为 Azure AD Graph api 获取令牌。

如果访问令牌是给你自己的api,你需要在你的api中验证访问令牌,你可以使用OWIN中间件来处理令牌:

app.UseWindowsAzureActiveDirectoryBearerAuthentication(
                new WindowsAzureActiveDirectoryBearerAuthenticationOptions
                
                    Audience = ConfigurationManager.AppSettings["ida:Audience"],
                    Tenant = ConfigurationManager.AppSettings["ida:Tenant"],

                );

或手动验证 JWT 令牌,例如 this code sample。

【讨论】:

我正在尝试将令牌用于我自己的 api。不幸的是,我的 api 不是 mvc,而且似乎对 restful api 的支持很少......到目前为止,我已经为 Azure AD 工作了几个 MVC 示例,但是在我自己的 api 中尝试使用调用时运气为零 您可以在 azure ad 中注册另一个应用程序以保护您自己的 api,在您的客户端应用程序中,获取令牌以访问您的 api 应用程序,然后在您的 api 中,手动验证访问令牌(受众应该是您的api app url) 如上面的代码示例所示。

以上是关于IDX10501:签名验证失败。尝试的密钥:'System.IdentityModel.Tokens.X509AsymmetricSecurityKey'的主要内容,如果未能解决你的问题,请参考以下文章

收到 IDX10501 的错误信息:签名验证失败。使用 Azure AD 时无法匹配密钥

Azure AD B2C 错误 - IDX10501:签名验证失败

IDX10501:签名验证失败。无法匹配键

每日获取 :: SecurityTokenSignatureKeyNotFoundException: IDX10501: 签名验证失败。无法匹配键:

Azure b2c 错误:IDX10501:签名验证失败。无法匹配键:孩子:'gLv****************'

签名验证失败。没有提供安全密钥来验证签名