Azure AD - 为什么我无法验证 Azure AD 为我的 Web API 颁发的 JWT 令牌?收到“IDX10516:签名验证失败”错误

Gau*_*tri 4 azure jwt azure-active-directory

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

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

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

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

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'
Run Code Online (Sandbox Code Playgroud)

我能够成功解析 处的令牌https://jwt.io

在“标题”部分下,我看到以下内容:

{
  "typ": "JWT",
  "alg": "RS256",
  "x5t": "qDm8HXaLQBeSIvYXzMt8PQ_ADFt",//obfuscated
  "kid": "qDm8HXaLQBeSIvYXzMt8PQ_ADFt"//obfuscated
}
Run Code Online (Sandbox Code Playgroud)

另外,我收到了Signature Verified消息,如下面的屏幕截图所示。

在此输入图像描述

这是我写的代码:

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
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Tho*_*mas 5

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

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 _);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)