Trying to write a token using JwtSecurityTokenHandler.WriteToken()
Get error: Invalid algorithm specified
Invalid algorithm specified
Operation=ReflectedHttpActionDescriptor.ExecuteAsync, Exception=System.Security.Cryptography.CryptographicException: Invalid algorithm specified.
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte hash, Int32 cbHash, ObjectHandleOnStack retSignature)
at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte hash)
at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte rgbHash, Int32 calgHash)
at System.Security.Cryptography.RSAPKCS1SignatureFormatter.CreateSignature(Byte rgbHash)
at System.IdentityModel.Tokens.AsymmetricSignatureProvider.Sign(Byte input)
at System.IdentityModel.Tokens.JwtSecurityTokenHandler.CreateSignature(String inputString, SecurityKey key, String algorithm, SignatureProvider signatureProvider)
at System.IdentityModel.Tokens.JwtSecurityTokenHandler.WriteToken(SecurityToken token)
Found out the problem is when I add this line to my project in order to verify some xml signatures.
So right now I can either validate xml or create tokens. Except I can't create the token until i've validated the xml...
I don't know why the cert doesn't work, but after I created a new cert and specified Microsoft Enhanced RSA and AES Cryptographic Provider as the CSP, it worked. If anyone else has this problem, please note that on the cert request either from the MMC or IIS will not let you chose the CSP (the option should be there but it will be hidden AND disabled). You will need to generate the request via certreq.exe. Its a PITA but that's the only work around that I know of right now.
Microsoft Enhanced RSA and AES Cryptographic Provider
the reason is the default CSP doesn't support SHA2, when you created the cert with 'enhanced', you triggered a different CSP to be instantiated that supports SHA2. It is a bit quirky to be sure.
@brentschmaltz Is there a way to specify which one I need to use? if I don't add RSAPKCS1SHA256SignatureDescription to the cryptoconfig, signing works fine. I looked for away to remove description but there wasn't anything public I could call.
Have you considered a custom AsymmetricSignatureProvider and pass that as a parameter to CreateToken?
I'm not sure what you mean by that.
Do you mean what's in the test here? https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/e6d903b4f8d3c6d7697dc70cd54ae905b18b65fe/tests/Microsoft.IdentityModel.Protocol.Extensions.Tests/Saml2SecurityTokenHandlerTests.cs#L227
or do you mean the place where I provide the keying material https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/e6d903b4f8d3c6d7697dc70cd54ae905b18b65fe/tests/Shared/KeyingMaterial.cs?
@tonyeung now I see why you are confused. Which version are you using?
do you mean nuget version?
@tonyeung yes the nuget package version
@tonyeung did you find the package version?
sorry i got side tracked: 22.214.171.124221351, here's the package config. https://github.com/IdentityServer/IdentityServer3/blob/master/source/Core/packages.config
Any word with this one? I've got the same problem (validating XML and Creating JWT tokens in same application). I can't change the JwtSecurityTokenHandler code, so presume I need to change my XML validation code but not sure how). Please help!!! :)
Finally have had some time to look into this from the Kentor.AuthServices end. It's a SAML2 OWIN middleware that's often used together with IdentityServer3, which relies on System.IdentityModel.Tokens.Jwt. So the combination of enabling SHA256 xml signatures for SAML2 in Kentor.AuthServices and using the JWT token handler should be fairly common.
The reason for all of this is actually in the .NET framework where X509AsymmetricSecurityKey.GetSignatureFormatter contains some black magic to copy the key to a new RsaCryptoServiceProvider with type = 24, instead of the default one with type=1 that doesn't support SHA256. This can be handled by having a certificate that specifies a CSP with type 24 (with 24 meaning Microsoft Enhanced RSA and AES Cryptographic Provider, so that's the solution that @tonyeung suggests above).
For now I've added the same black magic to the SignatureDesription being used by Kentor.AuthServices (see KentorIT/authservices#303) which should solve this particular conflict.
I'm not sure however if the SignatureDescription is the right place to replace to replicate the logic from X509AsymmetricSecurityKey.GetSignatureFormatter. I think it would be better if X509AsymmetricSecurityKey.GetSignatureFormatter did the magic both when the algorithm is registered and in the fallback.
I wrote a blog post with some in depth analysis: https://coding.abel.nu/2016/06/why-enabling-sha256-support-for-xml-signatures-breaks-jwt-signing/
Fixed in 4.6.2.