C# IDX10501:签名验证失败。已尝试按键:';System.IdentityModel.Tokens.X509AsymmetricSecurityKey';

C# IDX10501:签名验证失败。已尝试按键:';System.IdentityModel.Tokens.X509AsymmetricSecurityKey';,c#,validation,oauth-2.0,azure-active-directory,access-token,C#,Validation,Oauth 2.0,Azure Active Directory,Access Token,我正在尝试验证Azure中的令牌。我使用Adal.js获取令牌。 当我尝试验证令牌时,每次都会收到相同的错误消息: IDX10501:签名验证失败。已尝试密钥:“System.IdentityModel.Tokens.X509AsymmetricSecurityKey”。 标记:“{”类型“:“JWT” 消息中省略的标记看起来与我在客户端上看到的类似,并且来自以下3个URL的信息似乎正确地添加到了数据结构中,也就是说,我可以看到填充的字段,这是我在客户端上查看下面的链接和我的标记所期望的 {id

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

IDX10501:签名验证失败。已尝试密钥:“System.IdentityModel.Tokens.X509AsymmetricSecurityKey”。 标记:“{”类型“:“JWT”

消息中省略的标记看起来与我在客户端上看到的类似,并且来自以下3个URL的信息似乎正确地添加到了数据结构中,也就是说,我可以看到填充的字段,这是我在客户端上查看下面的链接和我的标记所期望的

{id}.onmicrosoft.com/federationmetadata/2007-06/federationmetadata.xml

{id}.onmicrosoft.com/.well-known/openid配置

但是每当我到达最后一行时,
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);
        }   
//从授权头获取jwt承载令牌
字符串jwtToken=null;
AuthenticationHeaderValue authHeader=request.Headers.Authorization;
if(authHeader!=null)
{
jwtToken=authHeader.Parameter;
}
字符串发行者;
列出签名令牌;
//issuer和SigningToken将被缓存24小时。如果if条件中的任何条件为true,则会对其进行更新。
if(DateTime.UtcNow.Subtract(_stsMetadataRetrievalTime).TotalHours>24 | | string.IsNullOrEmpty(_issuer)| | | |签名令牌==null)
{
//获取用于验证传入jwt令牌的租户信息
string stsDiscoveryEndpoint=string.Format(“{0}/.well-known/openid配置”,authority);
ConfigurationManager configManager=新的ConfigurationManager(stsDiscoveryEndpoint);
OpenIdConnectConfiguration配置=等待configManager.GetConfigurationAsync();
_issuer=config.issuer;
_signingTokens=config.signingTokens.ToList();
_stsmetadaretrievaltime=DateTime.UtcNow;
}
发行人=_发行人;
signingTokens=_signingTokens;
JwtSecurityTokenHandler tokenHandler=新的JwtSecurityTokenHandler();
TokenValidationParameters validationParameters=新的TokenValidationParameters
{
勇敢=观众,
ValidisUser=发行人,
IssuerSigningTokens=签名代币,
CertificateValidator=X509CertificateValidator.无
};
试一试{
//验证令牌。
SecurityToken validatedToken=新的JwtSecurityToken();
ClaimsPrincipal ClaimsPrincipal=tokenHandler.ValidateToken(jwtToken,validationParameters,out validatedToken);
}   
更新
以防万一在初始化客户端和服务器时我遗漏了一些东西

Adal.js init选项包括:

    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";
var端点={
"https://graph.windows.net": "https://graph.windows.net"
};
var配置选项={
租户:“.onmicrosoft.com”,//默认情况下为可选,它发送公共
客户ID:“,
postLogoutRedirectUri:window.location.origin,
端点:端点,
}
window.authContext=新的AuthenticationContext(配置选项);
服务器初始化选项包括:

    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";
静态字符串aadInstance=”https://login.microsoftonline.com/{0}";
静态字符串tenant=“.onmicrosoft.com”;
静态字符串受众=”;
string authority=string.Format(CultureInfo.InvariantCulture,aadInstance,tenant);
静态字符串scopeClaimType=”http://schemas.microsoft.com/identity/claims/scope";

您试图实现什么场景?您拥有的令牌用于AAD Graph API,无需验证。使用该令牌执行API调用时,microsoft Graph server端将验证访问令牌

此外,在服务器端初始化选项中,您将访问群体设置为azure portal的应用程序ID,这意味着在验证访问令牌时,访问令牌的访问群体应与azure portal的应用程序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令牌,如。

当您在令牌上时,标题中的
kid
是否与中列出的
kid
匹配?是的,它们匹配我正在尝试将令牌用于我自己的api。不幸的是,我的api不是mvc,似乎很少支持restful api…到目前为止,我已经制作了几个mvcAzure AD的示例可以工作,但在尝试使用我自己的api中的调用时没有运气。您可以在Azure AD中注册另一个应用程序以保护您自己的api,在您的客户端应用程序中,获取令牌以访问您的api应用程序,然后在您的api中,手动验证访问令牌(受众应为您的api应用程序url),如上面的代码示例所示。