0

我正在尝试使用 Azure keyvault 客户端验证签名,但它总是返回 false。

我已经设法使用 KeyVaultClient.SignAsync 方法对其进行签名,但是在尝试使用 KeyVaultClient.VerifyAsync 时,结果总是返回错误。

// Added for completeness, this method seems to be working correctly
private static async Task<string> SignJwt(KeyVaultClient client)
{
    var claimsToSign = new[]
    {
        new Claim("sub", "UserId123"),
        new Claim("custom", "MyValue")
    };

    var token = new JwtSecurityToken(
        issuer: "AuthApp",
        audience: "Consumer",
        claims: claimsToSign
    );

    var header = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(new Dictionary<string, string>()
    {
        {JwtHeaderParameterNames.Alg, JsonWebKeySignatureAlgorithm.ES256},
        {JwtHeaderParameterNames.Typ, "JWT"}
    }));

    var byteData = Encoding.UTF8.GetBytes(header + "." + token.EncodedPayload);
    var hasher = new SHA256CryptoServiceProvider();
    var digest = hasher.ComputeHash(byteData);

    var signature = await client.SignAsync(KeyVaultBaseUrl, KeyName, KeyVersion, JsonWebKeySignatureAlgorithm.ES256, digest);

    var fullJwt = $"{header}.{token.EncodedPayload}.{Base64UrlEncoder.Encode(signature.Result)}";

    return fullJwt;
}

// This always returns a false result
private static async Task<KeyVerifyResult> ValidateJwt()
{
    // Example of a JWT produced by the SignJwt method
    var jwt = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJVc2VySWQxMjMiLCJjdXN0b20iOiJNeVZhbHVlIiwiaXNzIjoiQXV0aEFwcCIsImF1ZCI6IkNvbnN1bWVyIn0.6tYkBcoFojJVJBhdNST49v4A3VWC1Rqizx_FzmSRICQubDEfXVopfP7Rs9tOBi9YzTCbod9o3hmHzIxANoIh7A";

    var client = new KeyVaultClient(GetAccessTokenAsync, new HttpClient());

    var jwtParts = jwt.Split('.');
    var header = jwtParts[0];
    var body = jwtParts[1];
    var signature = Encoding.UTF8.GetBytes(Base64UrlEncoder.Decode(jwtParts[2]));

    var byteData = Encoding.UTF8.GetBytes($"{header}.{body}");
    var hasher = new SHA256CryptoServiceProvider();
    var digest = hasher.ComputeHash(byteData);

    var verified = await client.VerifyAsync(KeyVaultBaseUrl, KeyName, KeyVersion, JsonWebKeySignatureAlgorithm.ES256, digest, signature);
    return verified;
}


private static async Task<string> GetAccessTokenAsync(string authority, string resource, string scope)
{
    var appCredentials = new ClientCredential(ClientId, ClientSecret);
    var context = new AuthenticationContext(authority, TokenCache.DefaultShared);

    var result = await context.AcquireTokenAsync(resource, appCredentials);

    return result.AccessToken;
}

任何想法为什么 ValidateJwt 总是返回 false 而不是 true?

4

1 回答 1

1

解决了。

对于任何有兴趣的人,我都没有正确地在 SignJwt 方法中对签名进行 base 64 编码:

而不是使用Base64UrlEncoder.Encode/Decode,使用Convert.ToBase64String/FromBase64String


为了使问题中的代码片段正常工作,我需要将 SignJwt 和 ValidateJwt 方法更新为:

private static async Task<string> SignJwt(KeyVaultClient client)
{
    var claimsToSign = new[]
    {
        new Claim("sub", "UserId123"),
        new Claim("custom", "MyValue")
    };

    var token = new JwtSecurityToken(
        issuer: "AuthApp",
        audience: "Consumer",
        claims: claimsToSign
    );

    var header = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, string>()
    {
        {JwtHeaderParameterNames.Alg, JsonWebKeySignatureAlgorithm.ES256},
        {JwtHeaderParameterNames.Typ, "JWT"}
    })));

    var byteData = Encoding.UTF8.GetBytes(header + "." + token.EncodedPayload);
    var hasher = new SHA256CryptoServiceProvider();
    var digest = hasher.ComputeHash(byteData);

    var signature = await client.SignAsync(KeyVaultBaseUrl, KeyName, KeyVersion, JsonWebKeySignatureAlgorithm.ES256, digest);

    var fullJwt = $"{header}.{token.EncodedPayload}.{Base64UrlEncoder.Encode(signature.Result)}";

    return fullJwt;
}

private static async Task<KeyVerifyResult> ValidateJwt()
{
    // Example of a JWT produced by the SignJwt method
    var jwt = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJVc2VySWQxMjMiLCJjdXN0b20iOiJNeVZhbHVlIiwiaXNzIjoiQXV0aEFwcCIsImF1ZCI6IkNvbnN1bWVyIn0.6tYkBcoFojJVJBhdNST49v4A3VWC1Rqizx_FzmSRICQubDEfXVopfP7Rs9tOBi9YzTCbod9o3hmHzIxANoIh7A";

    var client = new KeyVaultClient(GetAccessTokenAsync, new HttpClient());

    var jwtParts = jwt.Split('.');
    var header = jwtParts[0];
    var body = jwtParts[1];
    var signature = Encoding.UTF8.GetBytes(Convert.FromBase64String(jwtParts[2]));

    var byteData = Encoding.UTF8.GetBytes($"{header}.{body}");
    var hasher = new SHA256CryptoServiceProvider();
    var digest = hasher.ComputeHash(byteData);

    var verified = await client.VerifyAsync(KeyVaultBaseUrl, KeyName, KeyVersion, JsonWebKeySignatureAlgorithm.ES256, digest, signature);
    return verified;
}
于 2019-07-19T13:37:21.070 回答