自定义令牌验证器在 .NET 8 中不起作用

问题描述 投票:0回答:1

今天我正在检查是否可以将我的应用程序迁移到.NET 8。起初一切正常,当我尝试登录时,我在控制台中收到以下错误:

验证令牌失败。
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: IDX10506:签名验证失败。用户定义的“委托”指定于 TokenValidationParameters 未返回“Microsoft.IdentityModel.JsonWebTokens.JsonWebToken”, 但在验证令牌时返回“System.IdentityModel.Tokens.Jwt.JwtSecurityToken”

我的客户正在使用 PingID 的定制实现。使用内省来验证令牌,这就是我编写自定义令牌验证器的原因:

public class PingTokenValidator : ISecurityTokenValidator
{
    private readonly IConfiguration configuration;
    private readonly ILogger log;
    private readonly OpenIdConnectConfiguration openIdConnectConfiguration;
    private readonly JwtSecurityTokenHandler tokenHandler;

    public PingTokenValidator(OpenIdConnectConfiguration openIdConnectConfiguration,
        IConfiguration configuration)
    {
        this.tokenHandler = new();
        this.openIdConnectConfiguration = openIdConnectConfiguration;
        this.configuration = configuration;
        this.log = Log.ForContext<PingTokenValidator>();
    }

    public bool CanReadToken(string securityToken)
    {
        return true;
    }

    public ClaimsPrincipal ValidateToken(string securityToken,
        TokenValidationParameters validationParameters,
        out SecurityToken validatedToken)
    {
        try
        {
            var principal = this.tokenHandler.ValidateToken(securityToken, validationParameters, out validatedToken);

            if (tokenExistInCache && cachedToken == securityToken)
            {
                return principal;
            }

            if (!this.IsValid(securityToken))
            {
                throw new SecurityTokenValidationException("Token not authorised by PingID.");
            }

            return principal;
        }
        catch (Exception e)
        {
            this.log.Error(e, "Error validating JWT token");
            throw;
        }
    }

    public bool CanValidateToken { get; }

    public int MaximumTokenSizeInBytes { get; set; } = TokenValidationParameters.DefaultMaximumTokenSizeInBytes;

    private bool IsValid(string securityToken)
    {
        var options = new RestClientOptions
        {
            Authenticator = new HttpBasicAuthenticator(this.configuration["FDID:UserId"]!, this.configuration["FDID:Secret"]!)
        };
        var client = new RestClient(options);
        var request = new RestRequest(this.openIdConnectConfiguration.IntrospectionEndpoint, Method.Post);
        request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
        request.AddParameter("grant_type", "urn:pingidentity.com:oauth2:grant_type:validate_bearer");
        request.AddParameter("token", securityToken);
        var response = client.Execute(request);

        if (!response.IsSuccessful)
        {
            this.log.Error(response.ErrorException, "Error validating JWT token. Response message: {@TokenIntrospectionMessage}", response.Content);
            return false;
        }

        if (string.IsNullOrWhiteSpace(response.Content))
        {
            this.log.Error("Ping returned empty response: {@IntrospectionResponse}", response);
            return false;
        }

        var tokenSummary = JsonSerializer.Deserialize<PingTokenSummary>(response.Content, new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        });

        return tokenSummary is
        {
            Active: true
        };
    }
}

我一直在寻找其他可以用来代替

ISecurityTokenValidator
的接口,但没有成功。我是不是错过了什么?

asp.net-core jwt asp.net-core-webapi bearer-token .net-8.0
1个回答
0
投票

看来微软现在对从

TokenValidationParameters.SignatureValidator
返回的确切类型有更严格的要求。您正在这样的方法中进行设置

            authenticationBuilder.AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = true,
                        ValidateAudience = false,
                        ValidateIssuerSigningKey = false,
                        SignatureValidator = delegate (string token, TokenValidationParameters parameters)
                        {
                            var jwt = new JsonWebToken(token); // here was JwtSecurityToken
                            if (parameters.ValidateIssuer && parameters.ValidIssuer != jwt.Issuer)
                                return null;
                            return jwt;
                        },
                        ValidIssuer = configuration.JwtIssuer,
                        ValidAudience = configuration.JwtAudience,
                        RequireSignedTokens = false
                    };
#if DEBUG
                    options.IncludeErrorDetails = true;
#endif
                }
            );

SignatureValidator 委托中的旧代码返回

JwtSecurityToken
的实例,当我将其更改为“JsonWebToken”时,它开始工作。请注意,正如错误消息所正确表明的那样,每个都来自不同的命名空间。

希望它对你也有用。

© www.soinside.com 2019 - 2024. All rights reserved.