We have below code snippet to generate a token using Azure KeyVault Key. Same method is used in .net core 6.0 and .net core 8.0.
public string GenerateJwtToken(DateTime expiryDateTime, Microsoft.IdentityModel.Tokens.SecurityKey securityKey)
{
SigningCredentials signingCredentials = new SigningCredentials(securityKey,SecurityAlgorithms.RsaSha256)
{
CryptoProviderFactory = new CryptoProviderFactory { CustomCryptoProvider = new Microsoft.IdentityModel.KeyVaultExtensions.KeyVaultCryptoProvider() } };
SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
{
IssuedAt = DateTime.UtcNow,
Expires = expiryDateTime,
SigningCredentials = signingCredentials
};
string token = new JsonWebTokenHandler().CreateToken(tokenDescriptor);
return token;
}
In .net core 6.0, it works without any error, but 8.0 it throws below error.
System.MethodAccessException: Attempt by method 'Microsoft.IdentityModel.KeyVaultExtensions.KeyVaultCryptoProvider.Create(System.String, System.Object[])' to access method 'Microsoft.IdentityModel.Tokens.CryptoProviderFactory.ShouldCacheSignatureProvider(Microsoft.IdentityModel.Tokens.SignatureProvider)' failed.
at Microsoft.IdentityModel.KeyVaultExtensions.KeyVaultCryptoProvider.Create(String algorithm, Object[] args)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateSignatureProvider(SecurityKey key, String algorithm, Boolean willCreateSignatures, Boolean cacheProvider)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForSigning(SecurityKey key, String algorithm, Boolean cacheProvider)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForSigning(SecurityKey key, String algorithm)
at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.CreateSignature(ReadOnlySpan`1 data, Span`1 destination, SigningCredentials signingCredentials, Int32& bytesWritten)
at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.CreateToken(SecurityTokenDescriptor tokenDescriptor, Boolean setdefaultTimesOnTokenCreation, Int32 tokenLifetimeInMinutes)
at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.CreateToken(SecurityTokenDescriptor tokenDescriptor)
We tried different way to generate key using JwtSecurityToken and JwtSecurityTokenHandler().WriteToken(token). Below is the result, we ended up
System.Security.Cryptography.CryptographicException: Unknown error (0xc100000d)
at System.Security.Cryptography.RSABCrypt.TrySignHash(ReadOnlySpan1 hash, Span
1 destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, Int32& bytesWritten)
at System.Security.Cryptography.RSA.SignHash(ReadOnlySpan1 hash, Span
1 destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
at System.Security.Cryptography.RSABCrypt.SignHash(Byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
at Microsoft.IdentityModel.Tokens.AsymmetricAdapter.SignRsa(Byte[] bytes)
at Microsoft.IdentityModel.Tokens.AsymmetricAdapter.Sign(Byte[] bytes)
at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider.Sign(Byte[] input)
at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.CreateEncodedSignature(String input, SigningCredentials signingCredentials)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.WriteToken(SecurityToken token)
The code snippet used is here
SigningCredentials signingCredentials = new SigningCredentials(new RsaSecurityKey(new Azure.Security.KeyVault.Keys.Key.ToRSA()), SecurityAlgorithms.RsaSha256);
JwtSecurityToken token = new JwtSecurityToken(claims: claims, signingCredentials: signingCredentials);
return new JwtSecurityTokenHandler().WriteToken(token);
I would require some help here to mitigate this version confusions.
Please let me know if any further details are required. Please note: All the required libraries are updated to latest available version.
Problem is solved. When you retrieve from Azure KeyVault, along with KeyVaultKey value, create CryptographyClient as well.
keyClient = new(vaultUri: new Uri(keyVaultUri), credential: new DefaultAzureCredential(new DefaultAzureCredentialOptions()
{
AdditionallyAllowedTenants = { tenatId }
}));
cryptoClient = new CryptographyClient(keyClient.GetKey(keyName).Value.Id, new DefaultAzureCredential(new DefaultAzureCredentialOptions()
{
AdditionallyAllowedTenants = { tenatId }
}));
Then in logic side use below
JwtSecurityToken token = new(claims: claims, notBefore: iat, expires: expiryDateTime, signingCredentials: new SigningCredentials(new RsaSecurityKey(objCryptoClient.CreateRSA()), SecurityAlgorithms.RsaSha256));
return new JwtSecurityTokenHandler().WriteToken(token);
This solved the issue. But I presume that Microsoft has to resolve library issues to go back to the previous "SecurityKey" class-based approaches.