azure-activedirectory-identitymodel-extensions-for-dotnet
azure-activedirectory-identitymodel-extensions-for-dotnet copied to clipboard
X.509 Certificates with ECDSA based keys supported?
I have a x509 cert with an ECDsa based key - here's the metadata:
{
"keys": [
{
"kty": "EC",
"use": "sig",
"kid": "68D797916CE7509DBC9CE7F601708CA16E367303",
"x5t": "aNeXkWznUJ28nOf2AXCMoW42cwM",
"x5c": [
"MIIDyjCCAjKgAwIBAgIQb62fi1RDUoKp8kStYW5uYDANBgkqhkiG9w0BAQsFADCBjTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTEwLwYDVQQLDChET01JTklDS0JBSUFFODBcZG9taW5pY2tARE9NSU5JQ0tCQUlBRTgwMTgwNgYDVQQDDC9ta2NlcnQgRE9NSU5JQ0tCQUlBRTgwXGRvbWluaWNrQERPTUlOSUNLQkFJQUU4MDAeFw0xOTA2MDEwMDAwMDBaFw0yOTExMDExMDQ0NTVaMIGAMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUxMTAvBgNVBAsMKERPTUlOSUNLQkFJQUU4MFxkb21pbmlja0BET01JTklDS0JBSUFFODAxIjAgBgNVBAMTGWlkZW50aXR5c2VydmVyLmVjZHNhLnRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARYOEwgVXiaCl/Sj9GZDjOItFsTFRZ2B9VlBdYxzwgr52oyn1xMBlJbPMIu2nXptsy8Qssz34ODuEcUHOZ4PVCho3wwejAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRJVNNoaS/qJG2yyA1U5ZHxrnh5/TAkBgNVHREEHTAbghlpZGVudGl0eXNlcnZlci5lY2RzYS50ZXN0MA0GCSqGSIb3DQEBCwUAA4IBgQBWVwsGedFAgPNNWrm+kW31Kss1q2iQVxKDuupoGmRAUfmGSjtVMZgU56vaIbKo33wWIVkuEfh+prwv8/5CjMbY7TjUSpN710vIFEN13oPEcaSdyeanopkOyUxC/cRNH2WlSK2qpTeyluxpFU0sXCgJWZS149eNxqxb7jKjf3TN2R7KDdfkdU3wg6tqSycMhYaX4IefI2gyeOmhcV79jSJIVhoqePrSGHr0oQWgwOeQQ+o6rFU69kOT3juxtRm7fbbh1GQEzcMdWxc56m+WYhaZmAxKRLM8ydCILwJQktCblusR1EOov9fnstYe9Y6RO4s2IwjooWItkF4csFlkO5ps2ui8XXFewAUWJEJtML8pbev3K7Et6NpArItn7bOlUpno0e3h49PNF4UvkSRwT7uQ0hlvbnkxjTP6zpnD4NZeK1mgiMycH3WGi4K/tfNZyzsP2hubunLSy3AbykATK2nYoHxWRfoApt/guqQhZYMG6M478pwbt2lZFliP+9JN6cU="
],
"alg": "ES256",
"x": "WDhMIFV4mgpf0o_RmQ4ziLRbExUWdgfVZQXWMc8IK-c",
"y": "ajKfXEwGUls8wi7adem2zLxCyzPfg4O4RxQc5ng9UKE",
"crv": "P-256"
}
]
}
I can't access the e.g. PublicKey
property of the X509SecurityKey but worked around that using Certificate.GetECDsaPublicKey()
- but the JWT handler also throws on singing:
An unhandled exception has occurred while executing the request.
System.NotSupportedException: The certificate key algorithm is not supported.
at System.Security.Cryptography.X509Certificates.PublicKey.get_Key()
at Microsoft.IdentityModel.Tokens.X509SecurityKey.get_PublicKey()
at Microsoft.IdentityModel.Tokens.SupportedAlgorithms.IsSupportedAlgorithm(String algorithm, SecurityKey key)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.IsSupportedAlgorithm(String algorithm, SecurityKey key)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateSignatureProvider(SecurityKey key, String algorithm, Boolean willCreateSignatures)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForSigning(SecurityKey key, String algorithm)
at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.CreateEncodedSignature(String input, SigningCredentials signingCredentials)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.WriteToken(SecurityToken token)
Are these keys supported?
@leastprivilege this is a case I don't think we have considered. EC keys are supported, but we have never tested this scenario. It seems reasonable, are you exploring a new scenario OR blocked?
I am not blocked right now. But this is a very reasonable scenario. So I was surprised.
@brentschmaltz I noticed one of your colleagues saying that the PublicKey.Key
and PrivateKey
properties are "unofficially deprecated" and that's why X509's with ECC keys throw a NotSupportedException
on those properties. Is that true?
In the FIDO component that I've built, I basically ended up calling GetECDsaPublicKey
and checking for null. Is that expected? If so, it looks like SupportedAlgorithms
needs an update to fix Dom's issue: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/src/Microsoft.IdentityModel.Tokens/SupportedAlgorithms.cs#L50
I see no reason not to support the ECDSA as an X509SecurityKey, as it is supported by using the ECDSASecurityKey.
Because you can actually do something like this:
var cert= new X509Certificate2("somedsa.pfx","somepassword");
var key = new ECDsaSecurityKey(cert.GetECDsaPrivateKey());
var signingCredentials = new SigningCredentials(key,"ES256");
var header = new JwtHeader(signingCredentials);
var jwtToken = new JwtSecurityToken(header, somePayload);
var securityTokenHandler = new JwtSecurityTokenHandler();
securityTokenHandler.WriteToken(jwtToken);
However than you need to set the x5t and kid manually on the JWT, if using that. So kind of a mess.
@jaanclaeys @scottbrady91 @leastprivilege I agree with you folks, we should make this work. ECD is preferred by many people. We can't fit this into our SignedHttpRequest effort (our next release), but will get it in the next one.
any update?
@leastprivilege we will be setting a date for our next release on Monday 27th.
@leastprivilege we are working on pushing our 6.x release. We would like to make sure we don't break IdentityServer. The main issues we are:
- removal of Newtonsoft from public API's, we will be switching to the new System.Text.Json in the future.
- switching from JsonWebToken from JwtSecurityToken {claim mapping, speed, API}
There are some small breaking changes, but we feel they are corner cases. These PR's are related to that work.
- https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/pull/1320
- https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/pull/1127
- https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/pull/1243
- https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/pull/1331
1131 has been pushed, if you build against a 6.4.2 preview you we can get a sense if we have broken you. Please let us know of any issues.
If there are breaking changes, then you will probably break us. But that's the way it is.
More importantly is that there a not features missing that we rely on.
See this separate issue: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/1341
When is 6.8.1 planned?
Is this still being worked on? We have common customers that need this feature, @brentschmaltz
According to this issue, seems this is for the 6.9.1 milestone - oh wait...
We are working on ECDH-ES and will deliver that in April.
@ciaozhang to check how far Cesar got in this work. thanks.
Done by: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/pull/1866
@brentschmaltz, @ciaozhang, I must be missing something, but the following does not work for me:
var cert = FindSingnigECDsaCertificate();
var now = DateTime.UtcNow;
var desc = new SecurityTokenDescriptor
{
Audience = "audience",
Issuer = "issuer",
NotBefore = now,
Expires = now + TimeSpan.FromHours(1),
Subject = new ClaimsIdentity(),
SigningCredentials = new X509SigningCredentials(cert)
};
var handler = new JsonWebTokenHandler();
var token = handler.CreateToken(desc);
In effect, this actually is not solved.
Problem is that X509SecurityKey only still looks at RSA as a means of finding the private and public key, and extracting x5t out of it.
The actual issue is that we want to sign with an X509Certificate2 backed with an ECDSA key. This would leverage certificates and the reference for validating them (and on the validation side then also check if the certificate is still ok).
This can be done now with custom code, changing the x5t itself, but it is actually harder to do know with JsonWebToken than it was with previous JWTSecurityToken
Should this issue be reopened or a new one created?
Should this issue be reopened or a new one created?
There seems another issue reported #2377 that already has a pr.