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

[Bug] CryptographicException when using CNG certificate #1726

Closed
bgavrilMS opened this issue Mar 24, 2020 · 10 comments · Fixed by #1953
Closed

[Bug] CryptographicException when using CNG certificate #1726

bgavrilMS opened this issue Mar 24, 2020 · 10 comments · Fixed by #1953

Comments

@bgavrilMS
Copy link
Member

bgavrilMS commented Mar 24, 2020

Which Version of MSAL are you using ?
4.10

Platform
net45 (does not repro on netcore)

Repro

ClientCreds with a certificate generated from ADFS 2019 or any CNG certificate
Simplest is to run the integration test ClientCreds_WithCertificate_Adfs_Async which will download such a certificate...

Expected: MSAL should fetch a token
Actual: Cryptographic Exception

System.Security.Cryptography.CryptographicException: Invalid provider type specified.
X509Certificate2.get_PrivateKey()
NetDesktopCryptographyManager.GetCryptoProviderForSha256(X509Certificate2 certificate) line 92
... rest of stack trace is not important ...

Note:

  1. Wilson is able to handle this certificate!
  2. There seems to be a known issue with CNG type certs but not sure how to get around it. Wilson seems to be able to get around it just fine... The exception occurs when accessing the PrivateKey property.

How to fix this

Wilson knows how to handle these certs. We need to use the same logic in both Wilson and MSAL, but we cannot take a depdency on Wilson.

As part of fixing this issue, we need to asses the possibility of using a github submodule for the shared logic.

Workaround

  1. Create a signed assertion manually like here - using Microsoft.IdentityModel.JsonWebTokens nuget package. Just make sure the audience value is set to the token endpoint, which is:

"{authority}oauth2/v2.0/token" for AAD and B2C
"{authority}oauth2/token" for ADFS

So for example if your authority is https://login.microsoftonline.com/12345-56789 the the token endpoint is https://login.microsoftonline.com/12345-56789/oauth2/v2.0/token - this is the aud value.

  1. Instead of using .WithCertificate use .WithClientAssertion and pass in the string from previous step (example)

This is what MSAL internally should be extracting from that certificate, but it is unfortunately failing because on .net classic we need to support APIs all the way down to .net 4.5 that are very buggy. We cannot take a dependency on Microsoft.IdentityModel.JsonWebTokens as it is a breaking change.

@bgavrilMS bgavrilMS added the bug label Mar 24, 2020
@bgavrilMS
Copy link
Member Author

Quite a few bugs around certificate usage in MSAL now ... @henrik-me @trwalke Perhaps it's time to bite the bullet and upgrade to use Wilson?

@jmprieur
Copy link
Contributor

jmprieur commented Apr 6, 2020

yes, that would be a good optimization if this works for all platforms? (or would we have two code paths)?

@bgavrilMS
Copy link
Member Author

Well we would use Wilson for 2 things: Client Creds and PoP, which are really only present on .net classic and .net core;

Wilson has bindings for .net classic 4.5 and .net standard 2.0

So in the short term, we could move to use Wilson without changing our supported frameworks. In the longer term we might have to take a breaking change if we will want to support PoP on UWP for example, or if we want things to work better on pure .netstandard (for things like Unity).

@jmprieur
Copy link
Contributor

jmprieur commented Apr 6, 2020

Let's do that, then, and if we see the value, let's move to 5.0 (given that it's only about platforms)

@henrik-me henrik-me added this to the 4.13 - Crypto milestone Apr 9, 2020
@jmprieur jmprieur added the P1 label May 6, 2020
@bgavrilMS bgavrilMS removed this from the 4.15 milestone May 14, 2020
@henning-krause
Copy link

Just stumbled accross because I got this exact error when using certificates created with PowerShell New-SelfSignedCertificate cmdlet, which uses CNG to create certificates.

@bgavrilMS bgavrilMS added this to the 4.16.0 milestone May 18, 2020
@bgavrilMS
Copy link
Member Author

@henning-krause - I added a workaround, please let me know if that works.

@henning-krause
Copy link

@bgavrilMS I found another workaround. I you specify -KeySpec KeyExchange as a parameter for New-SelfSignedCertificate, it will revert to the CAPI provider and create legacy certificates. That works.

@trwalke trwalke self-assigned this Jun 23, 2020
@bgavrilMS bgavrilMS modified the milestones: 4.16.0, 4.17.0 Jul 8, 2020
@bgavrilMS
Copy link
Member Author

Also see #1937 (comment) for an example of how to create this type of cert.

@bgavrilMS
Copy link
Member Author

bgavrilMS commented Jul 20, 2020

Upon further investigation, it seems that Wilson is also not able to handle these certs on .net 45. So the way to move forward here is to add also target .net 461 and to make a simple code change. CC @GeoK

Note that .net45 is really old, but it is tied to Win Server 2008 R2, so it will only be deprecated around 2022 - thus we probably cannot remove .net 45 without a major breaking change....

CC @henrik-me @jmprieur for the go ahead.

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

Successfully merging a pull request may close this issue.

5 participants