【问题标题】:how to validate azure active directory token in webapi如何在 webapi 中验证 azure 活动目录令牌
【发布时间】:2020-02-27 04:04:41
【问题描述】:

我正在尝试验证 angularapp 中的天蓝色活动目录令牌

我在 web api 中使用了以下代码

        [HttpGet]
    [Route("Validate")]
    public JwtSecurityToken Validate(string token)
    {
        string stsDiscoveryEndpoint = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";


        ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());

        OpenIdConnectConfiguration config = configManager.GetConfigurationAsync().Result;

        TokenValidationParameters validationParameters = new TokenValidationParameters
        {
            ValidateAudience = false,
            ValidateIssuer = false,
            IssuerSigningTokens = config.SigningTokens,
            ValidateLifetime = false
        };

        JwtSecurityTokenHandler tokendHandler = new JwtSecurityTokenHandler();

        SecurityToken jwt;

        var result = tokendHandler.ValidateToken(token, validationParameters, out jwt);

        return jwt as JwtSecurityToken;
    }

代码在IssuerSigningTokens = config.SigningTokens 处显示错误,并带有消息

TokenValidationParameters 不包含 IssuerSigningTokens

谁能给我解决办法?

我还想从 validate 方法返回我自己的令牌。

【问题讨论】:

  • 你的应用是什么类型的?如果是.NET Core App,应该是IssuerSigningKeys = config.SigningKeys
  • dotnet famwork 4.5.2

标签: asp.net-web-api azure-active-directory


【解决方案1】:

今天,我们可以使用jwtSecurityTokenHandlerSystem.IdentityModel.Tokens.Jwt

注意 System.IdentityModel.Tokens.Jwt 版本 5.x.x 需要 .NET Framework 5.x。 如果目标框架是 .NET Framework 4.5.x 或 4.6.x,则采用 System.IdentityModel.Tokens.Jwt 包的最新稳定 4.x.x 版本。

验证 JWT

public override async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
    ...

    // validate JWT
    try
    {
        await JwtValidator.ValidateJwtToken(token, cancellationToken);
    }
    catch (SecurityTokenException e)
    {
        var validationSucceeded = false;
        Contract.Assert(validationSucceeded, $"{ErrorCode.UNAUTHORIZED}JWT validation failed ({e.Message}).");
    }

    ...
}

public class JwtValidator
{
    private const string STS_DISCOVERY_ENDPOINT_SUFFIX = ".well-known/openid-configuration";
    private const string URI_DELIMITER = "/";

    public static async Task<SecurityToken> ValidateJwtToken(string token, CancellationToken cancellationToken)
    {
        var aadInstance = "https://login.microsoftonline.com/{0}";
        var tenant = "example.com";
        var audience = "853fb202-4201-4e20-97ae-4d5840d9490f";
        var authority = string.Format(CultureInfo.InvariantCulture, aadInstance, tenant);

        // Fetch configuration
        var stsDiscoveryEndpoint = string.Concat(authority, URI_DELIMITER, STS_DISCOVERY_ENDPOINT_SUFFIX);
        ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint);
        var config = await configManager.GetConfigurationAsync(cancellationToken);

        // extract issuer and token for validation
        var issuer = config.Issuer;
        var signingTokens = config.SigningTokens.ToList();

        // validate token
        var validationParameters = CreateTokenValidationParameters(signingTokens, issuer, audience);

        var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();

        SecurityToken jwt;
        jwtSecurityTokenHandler.ValidateToken(token, validationParameters, out jwt);
        return jwt;
    }

    private static TokenValidationParameters CreateTokenValidationParameters(List<SecurityToken> signingTokens, string issuer, string audience)
    {
        Contract.Requires(null != signingTokens);
        Contract.Requires(!string.IsNullOrWhiteSpace(issuer));

        return new TokenValidationParameters()
        {
            ValidAudience = audience,
            ValidIssuer = issuer,
            IssuerSigningTokens = signingTokens,
            CertificateValidator = X509CertificateValidator.None,
            ValidateLifetime = true
        };
    }
}

我还想从 validate 方法返回我自己的令牌。

当使用 OpenIdConnectConfiguration configManager.GetConfigurationAsync(cancellationToken); 时,必须使用 await 在异步上下文中调用(暗示周围的方法必须是异步的)。

否则方法调用GetConfigurationAsync(cancellationToken) 永远不会返回。即使我尝试通过调用 .Result 或使用其他机制同步运行异步方法来同步运行异步方法,该方法也没有返回。

您可以在this blog 中查看有关针对 Azure Active Directory 进行手动 JWT 验证的更多详细信息。

【讨论】:

  • 我正在使用 dotnet 框架 4.5.2,我有最新的 System.IdentityModel.Tokens.Jwt dll(5.2.2),但我收到错误 OpenIdConnectConfiguration 不包含 SigningTokens 的定义跨度>
  • 我更改了 dll(版本 4.0.1),1.出现以下错误 ConfigurationManager 不包含构造函数,2.OpenIdConnectConfiguration 不包含 SigningTokens 的定义,3.无法从“Microsoft.IdentityModel.Tokens.TokenValidationParameters”到“System.IdentityModel.Tokens.TokenValidationParameters”,4.TokenValidationParameters 不包含“IssuerSigningTokens”的定义
  • 我们也可以用于 .net core 吗?
猜你喜欢
  • 1970-01-01
  • 2020-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-23
  • 1970-01-01
  • 1970-01-01
  • 2015-12-08
相关资源
最近更新 更多