【问题标题】:Validating an Azure AD generated JWT signature and algorithm in .NET Core 3.1在 .NET Core 3.1 中验证 Azure AD 生成的 JWT 签名和算法
【发布时间】:2021-12-07 22:17:04
【问题描述】:

我是 Azure AD 的新手。我们正在使用 v1.0 令牌。我有一个 Azure JWT 令牌验证例程,主要基于 ValidateSignatureAzureTokenValidation 以下是我的 ClaimsTransformer:

public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
<do something>
var token = httpContextAccessor.HttpContext.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
if (Validate(token))
{ 
             <proceed to add claims>
}

和我的验证程序:

 public bool Validate(string token)
        {
            string stsEndpoint = "https://login.microsoftonline.com/common/.well-known/openid-configuration";
            ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsEndpoint, new OpenIdConnectConfigurationRetriever());
            OpenIdConnectConfiguration config = configManager.GetConfigurationAsync().Result;
            TokenValidationParameters parameters = new TokenValidationParameters
            {
                ValidIssuer = "https://sts.windows.net/<mytenant-id>",
                ValidAudience = <my client-id>,
                IssuerSigningKeys = config.SigningKeys,
                ValidateAudience = true,
                ValidateIssuer = true,
                ValidateLifetime = true,
            };
            JwtSecurityTokenHandler tokendHandler = new JwtSecurityTokenHandler();
            SecurityToken jwt;
            bool verified;
            try
            {
               var handler = tokendHandler.ValidateToken(token, validationParameters, out jwt);
               var signature = ((System.IdentityModel.Tokens.Jwt.JwtSecurityToken)jwt).RawSignature;
                string algorithm = ((System.IdentityModel.Tokens.Jwt.JwtSecurityToken)jwt).Header["alg"].ToString();
                if (signature.Length == 0 || algorithm.ToLower().Equals("none"))
                {
                    tokenVerified = false;
                }
                tokenVerified = true;
            }
            catch
            {
                tokenVerified = false;
            }
            return tokenVerified;
        }

请告诉我我做的是否正确,或者我可以使用(在我的验证(字符串令牌)中)

try
{
   var result = tokendHandler.ValidateToken(token, validationParameters, out _);
   verified = true;
}
catch {
   verified = false;
}

并且是,检查算法(不接受 alg 中的“无”)和签名存在是必需的,或者这种检查方式是否正确?没有“秘钥”

【问题讨论】:

  • 您没有在应用程序中实施标准 Azure AD JWT 身份验证的任何原因?为什么要编写手动验证?
  • 你好,没有理由,因为我是新手,我不知道是否存在。有没有套路?还是我遗漏了一些明显的东西(大多数情况下我可能不知道)。你能帮忙吗?
  • 这是构建受 Azure AD JWT 保护的 API 的官方示例:github.com/Azure-Samples/…

标签: azure-active-directory jwt


【解决方案1】:

JwtBearer 中间件与 Web 应用程序中的 OpenID Connect 中间件一样,根据 TokenValidationParameters 的值验证令牌。根据需要解密令牌,提取声明并验证签名。然后中间件通过检查这些数据来验证令牌:

    Audience: The token is targeted for the web API.
    Sub: It was issued for an app that's allowed to call the web API.
    Issuer: It was issued by a trusted security token service (STS).
    Expiry: Its lifetime is in range.
    Signature: It wasn't tampered with.

更多详情请参考document

示例:

           String token = "Token";  
            string myTenant = "Tenant Name";  
            var myAudience = "Audience";  
            var myIssuer = String.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}/v2.0", myTenant);  
            var mySecret = "Secrete";  
            var mySecurityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(mySecret));              
            var stsDiscoveryEndpoint = String.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}/.well-known/openid-configuration", myTenant);  
            var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());  
            var config = await configManager.GetConfigurationAsync();  
  
            var tokenHandler = new JwtSecurityTokenHandler();  
  
            var validationParameters = new TokenValidationParameters  
            {  
                ValidAudience = myAudience,  
                ValidIssuer = myIssuer,  
                IssuerSigningKeys = config.SigningKeys,  
                ValidateLifetime = false,  
                IssuerSigningKey = mySecurityKey  
            };  
  
            var validatedToken = (SecurityToken)new JwtSecurityToken();  
  
            // Throws an Exception as the token is invalid (expired, invalid-formatted, etc.)  
            tokenHandler.ValidateToken(token, validationParameters, out validatedToken);  
            Console.WriteLine(validatedToken);  
            Console.ReadLine();

输出

【讨论】:

  • 谢谢@ShrustiJoshi-MT。但正如您在我的代码中看到的那样,我没有“mySecurityKey”。 Azure 和本地 API 之间没有共享秘密。这个秘密是验证签名的必要条件吗?有没有办法在没有这个密钥的情况下验证令牌的签名?
猜你喜欢
  • 1970-01-01
  • 2018-06-23
  • 2020-06-16
  • 2021-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-25
  • 2017-06-20
相关资源
最近更新 更多