【发布时间】:2021-11-06 01:36:17
【问题描述】:
我正在使用私钥签署 JWT 令牌,它按预期工作。但是,我想利用 Azure Key Vault 为我进行签名,这样私钥就不会离开 KeyVault。我正在努力让它工作,但不知道为什么。
这是不使用 KeyVault 并且确实工作的代码...
var handler = new JwtSecurityTokenHandler();
var expiryTime = DateTimeOffset.UtcNow.AddMinutes(10).ToUnixTimeSeconds();
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Iss, clientId),
new Claim(JwtRegisteredClaimNames.Sub, integrationUser),
new Claim(JwtRegisteredClaimNames.Aud, "https://test.example.com"),
new Claim(JwtRegisteredClaimNames.Exp, expiryTime.ToString()),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) // Add JTI for additional security against replay attacks
};
var privateKey = File.ReadAllText(@"selfsigned.key")
.Replace("-----BEGIN PRIVATE KEY-----", "")
.Replace("-----END PRIVATE KEY-----", "");
var privateKeyRaw = Convert.FromBase64String(privateKey);
var provider = new RSACryptoServiceProvider();
provider.ImportPkcs8PrivateKey(new ReadOnlySpan<byte>(privateKeyRaw), out _);
var rsaSecurityKey = new RsaSecurityKey(provider);
var token = new JwtSecurityToken
(
new JwtHeader(new SigningCredentials(rsaSecurityKey, SecurityAlgorithms.RsaSha256)),
new JwtPayload(claims)
);
var token = handler.WriteToken(token);
这可行,如果我将 JWT 复制到 jwt.io,并粘贴公钥 - 它表示签名已验证...
令牌也适用于我正在调用的 API。
但是,如果使用 KeyVault 签名...
var handler = new JwtSecurityTokenHandler();
var expiryTime = DateTimeOffset.UtcNow.AddMinutes(10).ToUnixTimeSeconds();
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Iss, clientId),
new Claim(JwtRegisteredClaimNames.Sub, integrationUser),
new Claim(JwtRegisteredClaimNames.Aud, "https://test.example.com"),
new Claim(JwtRegisteredClaimNames.Exp, expiryTime.ToString()),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) // Add JTI for additional security against replay attacks
};
var header = @"{""alg"":""RS256"",""typ"":""JWT""}";
var payload = JsonConvert.SerializeObject(new JwtPayload(claims));
var headerAndPayload = $"{Base64UrlEncoder.Encode(header)}.{Base64UrlEncoder.Encode(payload)}";
// Sign token
var credential = new InteractiveBrowserCredential();
var client = new KeyClient(vaultUri: new Uri(kvUri), credential);
var key = (KeyVaultKey)client.GetKey("dan-test");
var cryptoClient = new CryptographyClient(keyId: key.Id, credential);
var digest = new SHA256CryptoServiceProvider().ComputeHash(Encoding.Unicode.GetBytes(headerAndPayload));
var signature = await cryptoClient.SignAsync(SignatureAlgorithm.RS256, digest);
var token = $"{headerAndPayload}.{Base64UrlEncoder.Encode(signature.Signature)}";
(使用 Azure.Security.KeyVault.Keys 和 Azure.Identity nuget 包)
这不起作用。令牌的前两部分 - 即。标头和有效负载与有效的 JWT 相同。唯一不同的是最后的签名。
我没有想法!请注意,这与this * question 密切相关,其中的答案似乎表明我正在做的事情应该是正确的。
【问题讨论】:
-
这里有几件事可能是问题,我建议你在github上问这个,你将直接访问团队并获得权威答案
-
谢谢。我已经在那里发布并链接到这个问题。 github.com/Azure/azure-sdk-for-net/issues/23919
标签: c# .net azure jwt azure-keyvault