Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using an ECC certificate for signing the keys #755

Closed
binq1000 opened this issue Jul 24, 2019 · 10 comments
Closed

Using an ECC certificate for signing the keys #755

binq1000 opened this issue Jul 24, 2019 · 10 comments

Comments

@binq1000
Copy link

When adding a ECC certificate with AddSigningCertificate, it will give a NotSupportedException. Would it be possible to add support for ECC certificates and maybe add some documentation regarding this?

@kevinchalet
Copy link
Member

What's the exact exception? Are you using OpenIddict on .NET Framework? If so, what version?

@binq1000
Copy link
Author

binq1000 commented Jul 24, 2019

Using OpenIddict with .NET core 2.2

Retrieving the Certificate with:
private X509Certificate2 RetrieveCertificate()
{
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);

        var certificates = store.Certificates.Find(
            X509FindType.FindBySubjectDistinguishedName,
            "CN=subjectname",
            false);

        if (certificates.Count != 1)
        {
            throw new DoesNotExistException();
        }

        return certificates[0];
    }

And then setting it like:

options.AddSigningCertificate(this.RetrieveCertificate());

The exception is the following:

[13:51:50 Error] Microsoft.AspNetCore.Server.Kestrel
Connection id "0HLOG5L7RNQ5O", Request id "0HLOG5L7RNQ5O:00000001": An unhandled exception was thrown by the application.
System.NotSupportedException: The certificate key algorithm is not supported.
at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
at Microsoft.IdentityModel.Tokens.X509SecurityKey.get_PrivateKey() in C:\agent1_work\109\s\src\Microsoft.IdentityModel.Tokens\X509SecurityKey.cs:line 86
at Microsoft.IdentityModel.Tokens.X509SecurityKey.get_PrivateKeyStatus() in C:\agent1_work\109\s\src\Microsoft.IdentityModel.Tokens\X509SecurityKey.cs:line 146
at Microsoft.Extensions.DependencyInjection.OpenIdConnectServerExtensions.AddKey(IList1 credentials, SecurityKey key) at Microsoft.Extensions.DependencyInjection.OpenIdConnectServerExtensions.AddCertificate(IList1 credentials, X509Certificate2 certificate)
at Microsoft.Extensions.DependencyInjection.OpenIddictServerBuilder.<>c__DisplayClass14_0.b__0(OpenIddictServerOptions options)
at Microsoft.Extensions.Options.ConfigureNamedOptions1.Configure(String name, TOptions options) at Microsoft.Extensions.Options.OptionsFactory1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor1.<>c__DisplayClass10_0.<Get>b__0() at System.Lazy1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor) at System.Lazy1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache1.GetOrAdd(String name, Func1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor1.Get(String name) at Microsoft.AspNetCore.Authentication.AuthenticationHandler1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

@kevinchalet
Copy link
Member

Oh yeah, that's due to IdentityModel, that still doesn't support X.509 EC certificates.

To work around this limitation, you can do something like options.AddSigningKey(new ECDsaSecurityKey(certificate.GetECDsaPrivateKey()));, which will treat the EC key as a raw key (i.e no x5c/t will be returned by the JWKS endpojnt).

@brentschmaltz is EC certificates support on your radar?

@binq1000
Copy link
Author

binq1000 commented Jul 24, 2019

Got it working with the code you provided, first i got an exception about Keyset not found, but that was simply because Visual studio wasn't running in Administrator mode.

Still interested in the answer from brent, so if you don't mind i'll leave it open until he responded.

@binq1000
Copy link
Author

binq1000 commented Jul 25, 2019

Hey, I tried running a client (should have probably done this before) and got the following error now:

fail: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[17]
Exception occurred while processing message.
Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10501: Signature validation failed. Unable to match keys:
kid: 'GY2GC-QE6RHPHRP-3FBAIC-PAOJMQOQK--PNL7ZA',
token: '{"alg":"ES256","kid":"GY2GC-QE6RHPHRP-3FBAIC-PAOJMQOQK--PNL7ZA","typ":"JWT"}.{"name":"Tim Daniels","sub":"timdan","token_usage":"id_token","jti":"d62f63c4-cfc4-4a91-bbb3-06dc51aff01f","aud":"example-app","nonce":"636996378281041052.ZTIxMTQyNmEtYjA5Mi00YmI5LWEwMDktYzJkOWYzYmY3YmVjZjAxM2E2YmQtOGNiNi00ZWUwLTg1MGUtNzgxNWQ0M2ZmODFi","c_hash":"2EgmiZeVMqztAJgKzxDAug","azp":"example-app","nbf":1564041029,"exp":1564042229,"iat":1564041029,"iss":"https://localhost:5001/"}'.
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.ValidateToken(String idToken, AuthenticationProperties properties, TokenValidationParameters validationParameters, JwtSecurityToken& jwt)
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleRemoteAuthenticateAsync()

I've changed nothing in the client itself, should I do this now that i don't use a certificate but only set the SigningKey? I get that this error is coming from IdentityModel, but since @brentschmaltz is already tagged and this issue might also be of significance to Openiddict, i'll leave it here for now.

@binq1000
Copy link
Author

binq1000 commented Jul 29, 2019

@PinpointTownes any update?
Note: The issue reference i made was on the wrong IdentityModel.....

I think i found the problem that i had.
I had to add:
TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = new ECDsaSecurityKey(RetrieveCertificate().GetECDsaPublicKey()),
},

To the client application, this was not required with the RSA certificate i believe.

@kevinchalet
Copy link
Member

What Microsoft.IdentityModel.Tokens version do you use? EC keys resolution support in JsonWebKeySet is rather recent and you need a fairly recent version for discovery to work correctly with EC keys (IIRC, 5.5.0 or newer).

@binq1000
Copy link
Author

binq1000 commented Jul 29, 2019

It seems we're using 5.4.0, will updating it to 5.5 make it possible to leave it up to discovery to get the token?

Edit: After updating the Client to use 5.5.0 it indeed does not need to be specified explicitly again.

@brentschmaltz
Copy link

@PinpointTownes @binq1000 I guess the answer to if we support EC is yes :-).
all good now?

@kevinchalet
Copy link
Member

@brentschmaltz actually, EC support is missing in X509SecurityKey, hence my question: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs#L95

See the exception mentioned earlier: PrivateKey will throw an exception for EC certificates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants