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

Unable to add a Certificate in ClientCertificates from HttpClientHandler/SocketsHttpHandler #78933

Closed
taz4270 opened this issue Nov 28, 2022 · 16 comments · Fixed by dotnet/android#8961

Comments

@taz4270
Copy link

taz4270 commented Nov 28, 2022

Description

Hello,
When I try to add a credential in ClientCredentials, its throws a NullReferenceException although, the code i wrote is quite simple

try
      {
          Stream stream = await FileSystem.OpenAppPackageFileAsync("d.cer");

          using MemoryStream s = new();
          stream.CopyTo(s);
          stream.Dispose();
          
          X509Certificate2 cert = new X509Certificate2(s.ToArray(), "PASSWORD");
          
          SocketsHttpHandler shh = new()
          {
              UseCookies = true,
              AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
              SslOptions =
              {
                  EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12,
                  LocalCertificateSelectionCallback = (a,b,c,d,e) => c[0],
                  RemoteCertificateValidationCallback = (a,b,c,d) => true,
                  
              }
          };

          shh.SslOptions.ClientCertificates.Add(cert);
          
          HttpClient c = new(shh);

          var x = await c.GetAsync(new Uri("URL"));
          _ = 1;
      }
      catch (Exception e)
      {
          _ = e;
      }

Its throw on the shh.SslOptions.ClientCertificates.Add(cert);

The certificate itself has a sha256 algoritm with its public key as RSA 2048 Bits

I also tried to use the network_security_config.xml from android and it crashed when i put the CA and pin

Steps to Reproduce

  1. Run the example that i wrote on the description
  2. Put it somewhere in the code, like a button
  3. Click it 🐞

Link to public reproduction project repository

https://github.com/taz4270/ExampleCert.App

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

iOS, Android

Affected platform versions

Android 13, iOS 16

Did you find any workaround?

No response

Relevant log output

No response

@jsuarezruiz
Copy link

@jonathanpeppers Thoughts?

@jonathanpeppers
Copy link
Member

Transfer to dotnet/runtime?

@Eilon Eilon transferred this issue from dotnet/maui Nov 28, 2022
@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Nov 28, 2022
@ghost
Copy link

ghost commented Nov 29, 2022

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

Hello,
When I try to add a credential in ClientCredentials, its throws a NullReferenceException although, the code i wrote is quite simple

try
      {
          Stream stream = await FileSystem.OpenAppPackageFileAsync("d.cer");

          using MemoryStream s = new();
          stream.CopyTo(s);
          stream.Dispose();
          
          X509Certificate2 cert = new X509Certificate2(s.ToArray(), "PASSWORD");
          
          SocketsHttpHandler shh = new()
          {
              UseCookies = true,
              AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
              SslOptions =
              {
                  EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12,
                  LocalCertificateSelectionCallback = (a,b,c,d,e) => c[0],
                  RemoteCertificateValidationCallback = (a,b,c,d) => true,
                  
              }
          };

          shh.SslOptions.ClientCertificates.Add(cert);
          
          HttpClient c = new(shh);

          var x = await c.GetAsync(new Uri("URL"));
          _ = 1;
      }
      catch (Exception e)
      {
          _ = e;
      }

Its throw on the shh.SslOptions.ClientCertificates.Add(cert);

The certificate itself has a sha256 algoritm with its public key as RSA 2048 Bits

I also tried to use the network_security_config.xml from android and it crashed when i put the CA and pin

Steps to Reproduce

  1. Run the example that i wrote on the description
  2. Put it somewhere in the code, like a button
  3. Click it 🐞

Link to public reproduction project repository

https://github.com/taz4270/ExampleCert.App

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

iOS, Android

Affected platform versions

Android 13, iOS 16

Did you find any workaround?

No response

Relevant log output

No response

Author: taz4270
Assignees: -
Labels:

area-System.Net.Http, untriaged

Milestone: -

@ghost
Copy link

ghost commented Nov 29, 2022

Tagging subscribers to 'arch-android': @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

Hello,
When I try to add a credential in ClientCredentials, its throws a NullReferenceException although, the code i wrote is quite simple

try
      {
          Stream stream = await FileSystem.OpenAppPackageFileAsync("d.cer");

          using MemoryStream s = new();
          stream.CopyTo(s);
          stream.Dispose();
          
          X509Certificate2 cert = new X509Certificate2(s.ToArray(), "PASSWORD");
          
          SocketsHttpHandler shh = new()
          {
              UseCookies = true,
              AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
              SslOptions =
              {
                  EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12,
                  LocalCertificateSelectionCallback = (a,b,c,d,e) => c[0],
                  RemoteCertificateValidationCallback = (a,b,c,d) => true,
                  
              }
          };

          shh.SslOptions.ClientCertificates.Add(cert);
          
          HttpClient c = new(shh);

          var x = await c.GetAsync(new Uri("URL"));
          _ = 1;
      }
      catch (Exception e)
      {
          _ = e;
      }

Its throw on the shh.SslOptions.ClientCertificates.Add(cert);

The certificate itself has a sha256 algoritm with its public key as RSA 2048 Bits

I also tried to use the network_security_config.xml from android and it crashed when i put the CA and pin

Steps to Reproduce

  1. Run the example that i wrote on the description
  2. Put it somewhere in the code, like a button
  3. Click it 🐞

Link to public reproduction project repository

https://github.com/taz4270/ExampleCert.App

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

iOS, Android

Affected platform versions

Android 13, iOS 16

Did you find any workaround?

No response

Relevant log output

No response

Author: taz4270
Assignees: -
Labels:

area-System.Net.Http, os-android, untriaged

Milestone: -

@wfurt
Copy link
Member

wfurt commented Nov 29, 2022

ClientCertificates is nullable so dereferencing will throw as far as I can tell.
https://learn.microsoft.com/en-us/dotnet/api/system.net.security.sslclientauthenticationoptions.clientcertificates?view=net-7.0
You should create collection like the sample in #26708

any additional thoughts @simonrozsival

@taz4270
Copy link
Author

taz4270 commented Nov 29, 2022

ClientCertificates is nullable so dereferencing will throw as far as I can tell. https://learn.microsoft.com/en-us/dotnet/api/system.net.security.sslclientauthenticationoptions.clientcertificates?view=net-7.0 You should create collection like the sample in #26708

any additional thoughts @simonrozsival

Indeed, but only on SocketsHttpHandler because if you are using HttpClientHandler ClientCertificates is readonly resulting in the same problem

I already initialized ClientCredentials on SocketsHttpHandler thanks 👍
But i will leave it open so HttpClientHandler could be fixed, I have to update the sample when I have time 😅

@simonrozsival
Copy link
Member

simonrozsival commented Nov 29, 2022

@taz4270 You're right. Unfortunately, the native handler currently doesn't implement ClientCertificates (see dotnet/android#7274).

@wfurt
Copy link
Member

wfurt commented Nov 29, 2022

I'm wondering if we should throw PlatformNotSupportedException to make it more obvious @simonrozsival
NRE are annoying IMHO. I don't have Android setup to test.

@taz4270
Copy link
Author

taz4270 commented Nov 29, 2022

I'm wondering if we should throw PlatformNotSupportedException to make it more obvious @simonrozsival NRE are annoying IMHO. I don't have Android setup to test.

I agree with you, but i would go further, making the message to reference a guide "how to use" for android, something like that, or even deprecate only for android with the same message of the guide.

@ManickaP
Copy link
Member

@simonrozsival would it be possible to triage this issue?

@simonrozsival
Copy link
Member

Triage: unless we implement dotnet/android#7274 in time for .NET 8, we should change the exception to PNSE. We should do the same in the iOS implementation to make sure these two platforms behave the same way (https://github.com/xamarin/xamarin-macios/blob/d3af5724f25b58bf0c1134e5c5f736a0866bbcfd/src/Foundation/NSUrlSessionHandler.cs#L573).

@simonrozsival simonrozsival added this to the 8.0.0 milestone Jan 23, 2023
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Jan 23, 2023
@wfurt
Copy link
Member

wfurt commented Jan 23, 2023

throwing better exception would be good IMHO @simonrozsival. We can improve the functional if we find the time. It may by worth of documentation for 6&7....

@ComptonAlvaro
Copy link

@taz4270 could you share the code how did you add the credentials to the Socket?

Thanks.

@steveisok steveisok modified the milestones: 8.0.0, 9.0.0 Aug 8, 2023
@steveoshima
Copy link

steveoshima commented Oct 1, 2023

What happened to the fix for this issue?
MAUI dotnet 8 rc1 still does not allow ClientCertificates to be added to the HttpClientHandler.
I would have thought supporting mutual TLS is a high priority for an SDK, especially the creation of mobile apps. Connecting to secure APIs and not being able to use mTLS and certificate pinning is a security concern.

@dotMorten
Copy link

dotMorten commented Mar 17, 2024

Is this still an issue? I'm using client certificates for PKI authentication in both iOS and Android using the SocketsHttpHandler. Just note it only currently works with X509Certificates that have full access to the private key so they rather limited since you can't use the installed certificates.
There is still an issue with using certificates with iOS' NSUrlSessionHandler, and using key-chain based certificates on Android

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.