Проверьте токен JWT в C#, используя JWK

У меня есть JsonWebKeys(JWK) для id_token и access_token. Затем я получил свой id_token с URL-адреса / токена. Как проверить этот JWT id_token с помощью JWK в C#.

Излишне говорить, что я пробовал почти все, кроме (IdenityModels.Jwt и т. Д.), Но JwtSecurityTokenHandler не принимает JsonWebKey. Я использую RS512 в качестве алгоритма подписи.

1 ответ

Я только что сам реализовал это для проверки Google IdToken как:

var parameters = new TokenValidationParameters
{
    ...
    IssuerSigningKeyResolver = await keyProvider.GetIssuerSigningKeyResolverAsync(cancellationToken),
};

SecurityToken token;
var handler = new JwtSecurityTokenHandler();
var principal = handler.ValidateToken(source, parameters, out token);

куда keyProvider это:

public class GoogleOAuth2KeyProvider
{
    private readonly IGoogleAuthConfiguration configuration;
    private Jwk lastCertResponse;
    private DateTimeOffset lastCertExpires;

    public GoogleOAuth2KeyProvider(IGoogleAuthConfiguration configuration)
    {
        this.configuration = configuration;
    }

    public async Task<IssuerSigningKeyResolver> GetIssuerSigningKeyResolverAsync(CancellationToken cancellationToken)
    {
        await UpdateCert(cancellationToken);

        var keys = lastCertResponse.Keys
            .Where(key => key.Kty == "RSA" && key.Use == "sig")
            .ToDictionary(key => key.Kid, StringComparer.InvariantCultureIgnoreCase);
        return new IssuerSigningKeyResolver((token, securityToken, keyIdentifier, tokenValidationParameters) =>
        {
            foreach (var keyIdentifierClause in keyIdentifier)
            {
                Jwk.KeysData key;
                if (!keys.TryGetValue(keyIdentifierClause.Id, out key))
                {
                    continue;
                }
                var rsa = RSA.Create();
                rsa.ImportParameters(new RSAParameters
                {
                    Exponent = Base64UrlEncoder.DecodeBytes(key.E),
                    Modulus = Base64UrlEncoder.DecodeBytes(key.N),
                });
                return new RsaSecurityKey(rsa);
            }
            return null;
        });
    }

    private async Task UpdateCert(CancellationToken cancellationToken)
    {
        if (lastCertResponse != null && DateTimeOffset.UtcNow < lastCertExpires)
        {
            return;
        }
        var initializer = new BaseClientService.Initializer
        {
            ApiKey = configuration.ServerApiKey,
        };
        using (var service = new Oauth2Service(initializer))
        {
            lastCertResponse = await service.GetCertForOpenIdConnect().ExecuteAsync(cancellationToken);
            lastCertExpires = DateTimeOffset.UtcNow.AddHours(12);
        }
    }
}

RSA и т. д. просто System.Security.Cryptography, в то время как Base64UrlEncoder из System.IdentityModel (но достаточно легко сделать самому)

К сожалению, это не похоже на другие kty / alg значения так же легко поддерживать, например, нет ECDsa.ImportParameters() Хочет общий CngKey от byte[] так что кто-то делает общую библиотеку.NET JWK должен будет упаковать x, y Сами параметры, предположительно.

Другие вопросы по тегам