Azure AD - 为什么我无法验证 Azure AD 为我的 Web API 颁发的 JWT 令牌?获取“IDX10516:签名验证失败"错误 [英] Azure AD - Why can't I validate JWT token issued by Azure AD for my Web API? Getting "IDX10516: Signature validation failed" error

查看:16
本文介绍了Azure AD - 为什么我无法验证 Azure AD 为我的 Web API 颁发的 JWT 令牌?获取“IDX10516:签名验证失败"错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个受 Azure AD 保护的 Web API.我能够从 Azure AD 获取 Web API 的访问令牌并成功使用它.

我想要做的是在使用该令牌执行任何操作之前验证该令牌,以便在令牌出现问题时向用户提供有意义的错误消息.例如,我想告诉用户的一些事情是:

  1. 令牌是否已过期?
  2. 是否为正确的受众获取令牌?
  3. 令牌发行者是否有效?

但是我不能这样做,因为无论令牌是有效还是无效,我都会不断收到以下错误消息:

IDX10516:签名验证失败.无法匹配键:孩子:'System.String'.捕获的异常:'System.Text.StringBuilder'.令牌:'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'.有效生命周期:'System.Boolean'.有效发行者:'System.Boolean'

我能够在

这是我写的代码:

string authorizationToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImt..."尝试{JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();TokenValidationParameters tokenValidationParameters = new TokenValidationParameters(){ValidateLifetime = true,};var claimPrincipal = tokenHandler.ValidateToken(authorizationToken, tokenValidationParameters, out _);//这一行出现异常.}捕获(SecurityTokenExpiredException 异常){//对令牌过期异常做一些事情}捕获(SecurityTokenInvalidAudienceException 异常){//用无效的观众例外做一些事情}catch (Exception exception)//代码总是落在这个异常块中{//由于其他原因令牌无效}

正如我上面所说,无论令牌是否有效,我的代码总是落在最后一个异常块中.

谁能告诉我我在这里做错了什么?成功验证令牌需要什么?

对此的任何见解都将受到高度赞赏.

解决方案

要验证令牌,您需要指定身份提供者 (Azure AD) 用来签署令牌的密钥:

使用 Microsoft.IdentityModel.Protocols;使用 Microsoft.IdentityModel.Protocols.OpenIdConnect;使用 Microsoft.IdentityModel.Tokens;使用 System.IdentityModel.Tokens.Jwt;使用 System.Threading.Tasks;命名空间 ConsoleApp1{课堂节目{静态异步任务 Main(string[] args){var token = "<我的令牌>";var tenantid = "<我的天蓝色广告租户 ID>";//=>用于检索 AAD 用于签署令牌的密钥var openidConfigManaged = new ConfigurationManager($https://login.microsoftonline.com/{tenantid}/v2.0/.well-known/openid-configuration",新的 OpenIdConnectConfigurationRetriever(),新的 HttpDocumentRetriever());var config = 等待 openidConfigManaged.GetConfigurationAsync();var parameteres = new TokenValidationParameters(){要求观众=真,RequireExpirationTime = true,ValidateAudience = true,ValidateIssuer = true,ValidateLifetime = true,//Audience 应该是请求的资源 =>client_id 和/或资源标识符.//参考aud"在令牌中声明ValidAudiences = new[] { <我的客户 ID 或资源标识符>"},//颁发者是身份提供者//参考iss"在令牌中声明ValidIssuers = new[] { $"https://sts.windows.net/{tenantid}/"},IssuerSigningKeys = config.SigningKeys};var tokenHandler = new JwtSecurityTokenHandler();var claimPrincipal = tokenHandler.ValidateToken(token, parameteres, out _);}}}

I have a Web API that is protected by Azure AD. I am able to get access token for the Web API from Azure AD and use it successfully.

What I want to do is validate the token before performing any operation using that token so that I can give meaningful error messages to the user in case there's something wrong with the token. For example, some of the things I would like to tell user are:

  1. Whether or not the token has expired?
  2. Whether or not the token is acquired for correct audience?
  3. Whether or not the token issuer is valid?

However I am not able to do so because regardless of whether the token is valid or invalid, I am constantly getting the following error message:

IDX10516: Signature validation failed. Unable to match key: 
kid: 'System.String'.
Exceptions caught:
 'System.Text.StringBuilder'. 
token: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'. Valid Lifetime: 'System.Boolean'. Valid Issuer: 'System.Boolean'

I am successfully able to parse the token at https://jwt.io.

Under the "Header" section there, I see the following:

{
  "typ": "JWT",
  "alg": "RS256",
  "x5t": "qDm8HXaLQBeSIvYXzMt8PQ_ADFt",//obfuscated
  "kid": "qDm8HXaLQBeSIvYXzMt8PQ_ADFt"//obfuscated
}

Also, I get Signature Verified message as well as shown in the screenshot below.

Here's the code I wrote:

string authorizationToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImt...";
try
{
    JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

    TokenValidationParameters tokenValidationParameters = new TokenValidationParameters()
    {
        ValidateLifetime = true,
    };
    var claimsPrincipal = tokenHandler.ValidateToken(authorizationToken, tokenValidationParameters, out _);//Exception comes on this line.
}
catch (SecurityTokenExpiredException exception)
{
    //Do something with the token expired exception
}
catch (SecurityTokenInvalidAudienceException exception)
{
    //Do something with invalid audience exception
}
catch (Exception exception) //Code always lands in this exception block
{
    //Token is invalid because of some other reason
}

As I said above, my code is always landing in the last exception block regardless of whether the token is valid or not.

Can anyone please tell me what I am doing wrong here? What is needed to successfully validate the token?

Any insights into this will be highly appreciated.

解决方案

To validate the token, you need to specify the keys used by the identity provider (Azure AD) to sign the token:

using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var token = "<my token>";
            var tenantid = "<my azure ad  tenant id>";

            // => use to retrieve the keys used by AAD to sign the token
            var openidConfigManaged = new ConfigurationManager<OpenIdConnectConfiguration>(
                $"https://login.microsoftonline.com/{tenantid}/v2.0/.well-known/openid-configuration",
                new OpenIdConnectConfigurationRetriever(),
                new HttpDocumentRetriever());
            var config = await openidConfigManaged.GetConfigurationAsync();

            var parameteres = new TokenValidationParameters()
            {
                RequireAudience = true,
                RequireExpirationTime = true,
                ValidateAudience = true,
                ValidateIssuer = true,
                ValidateLifetime = true,
                // The Audience should be the requested resource => client_id and or resource identifier.
                // Refer to the "aud" claim in the token
                ValidAudiences = new[] { "<my client id or resource identitifer>" },
                // The issuer is the identity provider
                // Refer to the "iss" claim in the token
                ValidIssuers = new[] { $"https://sts.windows.net/{tenantid}/" }, 
                IssuerSigningKeys = config.SigningKeys
            };

            var tokenHandler = new JwtSecurityTokenHandler();
            var claimPrincipal = tokenHandler.ValidateToken(token, parameteres, out _);
        }
    }
}

这篇关于Azure AD - 为什么我无法验证 Azure AD 为我的 Web API 颁发的 JWT 令牌?获取“IDX10516:签名验证失败"错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆