使用 azure keyvault 验证 JWT 签名总是 returns false
Verifying a JWT signature using azure keyvault always returns false
我正在尝试使用 Azure keyvault 客户端验证签名,但它总是返回 false。
我已经设法使用 KeyVaultClient.SignAsync 方法对其进行签名,但是当尝试使用 KeyVaultClient.VerifyAsync 时,结果总是返回 false。
// 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 总是 returns false 而不是 true 吗?
解决了。
对于任何感兴趣的人,我没有正确地对 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;
}
我正在尝试使用 Azure keyvault 客户端验证签名,但它总是返回 false。
我已经设法使用 KeyVaultClient.SignAsync 方法对其进行签名,但是当尝试使用 KeyVaultClient.VerifyAsync 时,结果总是返回 false。
// 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 总是 returns false 而不是 true 吗?
解决了。
对于任何感兴趣的人,我没有正确地对 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;
}