我最终使用了 Jack Jia 的答案
var token = new JwtSecurityToken(
issuer,
appId,
claims,
signDate,
expiryDate);
var header = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(new Dictionary<string, string>()
{
{ JwtHeaderParameterNames.Alg, "RS256" },
{ JwtHeaderParameterNames.Kid, "https://myvault.vault.azure.net/keys/mykey/keyid" },
{ JwtHeaderParameterNames.Typ, "JWT" }
}));
var byteData = Encoding.UTF8.GetBytes(header + "." + token.EncodedPayload);
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var signature = await _keyVault.SignAsync("https://myvault.vault.azure.net/keys/mykey/keyid", "RS256", digest);
return $"{header}.{token.EncodedPayload}.{Base64UrlEncoder.Encode(signature.Result)}";
我找到了另一种解决方案,我不太喜欢它,但它与 JWT 库“集成”得更好。
var token = new JwtSecurityToken(
issuer,
appId,
claims,
signDate,
expiryDate,
new SigningCredentials(new KeyVaultSecurityKey("https://myvault.vault.azure.net/keys/mykey/keyid", new KeyVaultSecurityKey.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)), "RS256")
{
CryptoProviderFactory = new CryptoProviderFactory() { CustomCryptoProvider = new KeyVaultCryptoProvider() }
});
var handler = new JwtSecurityTokenHandler();
return handler.WriteToken(token);
原来有一个库 Microsoft.IdentityModel.KeyVaultExtensions 扩展为 SecurityToken 和 ICryptoProvider 支持 KeyVault。
我的问题是
- 我无法通过此解决方案重用
KeyVaultClient 的现有实例。
- 它正在阻塞(在幕后,它在
KeyVaultClient.SignAsync 上调用.GetAwaiter().GetResult()