and using AndroidHttpsClientHandler in Plan B, how to call the new handler in the pcl project??
Hi guy !
Is this still working currently? I tried but no luck, a side that ModernHttpClient is not kept up today, last version is 2015. I have been stuck with this same issue on Xamarin Forms/Android last few days. I have been able to resolve this issue. It is so frustrating. Very appreciate your help.
@Viplav04 - Thanks for your response.
1) So am I correct to say....unless I deploy using DEBUG build, RELEASE works just fine by using just this?
var client = new HttpClient();
In my case, I never work with either DEBUG or RELEASE. Would you mind sharing your HttpClientHandlerService & IHttpClientHandlerService classes?
2) Do you see this implementation being an issue with API server runs on TLS1.2 (TLS 1.0 disabled)
3) Below is my implementation using Thomas Bandt Plan B, What am I missing?
in portable project I added IHttpClientHandlerService.cs
using System.Net.Http;
namespace Apps.Models
{
public interface IHttpClientHandlerService
{
HttpClientHandler GetInsecureHandler();
}
}
in android project I added this HttpClientHandlerService.cs, notice I replaced my certificate file name
using System.IO;
using System.Net.Http;
using Java.Security;
using Java.Security.Cert;
using Javax.Net.Ssl;
using Xamarin.Android.Net;
using Xamarin.Forms;
using Apps.Droid;
using Apps.Models;
[assembly: Dependency(typeof(HttpClientHandlerService))]
namespace ETC.CrudeTransport.Apps.OrderUp.Droid
{
//Hai Nguyen added
public class HttpClientHandlerService : IHttpClientHandlerService
{
public HttpClientHandler GetInsecureHandler()
{
return new DroidTlsClientHandler();
}
}
//exact code from Thomas Bandt @https://thomasbandt.com/certificate-and-public-key-pinning-with-xamarin
internal class DroidTlsClientHandler : AndroidClientHandler
{
private TrustManagerFactory _trustManagerFactory;
private KeyManagerFactory _keyManagerFactory;
private KeyStore _keyStore;
protected override TrustManagerFactory ConfigureTrustManagerFactory(KeyStore keyStore)
{
if (_trustManagerFactory != null)
{
return _trustManagerFactory;
}
_trustManagerFactory = TrustManagerFactory
.GetInstance(TrustManagerFactory.DefaultAlgorithm);
_trustManagerFactory.Init(keyStore);
return _trustManagerFactory;
}
protected override KeyManagerFactory ConfigureKeyManagerFactory(KeyStore keyStore)
{
if (_keyManagerFactory != null)
{
return _keyManagerFactory;
}
_keyManagerFactory = KeyManagerFactory
.GetInstance(KeyManagerFactory.DefaultAlgorithm);
_keyManagerFactory.Init(keyStore, null);
return _keyManagerFactory;
}
protected override KeyStore ConfigureKeyStore(KeyStore keyStore)
{
if (_keyStore != null)
{
return _keyStore;
}
_keyStore = KeyStore.GetInstance(KeyStore.DefaultType);
_keyStore.Load(null, null);
CertificateFactory cff = CertificateFactory.GetInstance("X.509");
Certificate cert;
// Add your Certificate to the Assets folder and address it here by its name
using (Stream certStream = Android.App.Application.Context.Assets.Open("HaiNguyenCert.crt"))
{
cert = cff.GenerateCertificate(certStream);
}
_keyStore.SetCertificateEntry("TrustedCert", cert);
return _keyStore;
}
}
}
in portable project App.cs I added call API as follow
switch (Device.RuntimePlatform)
{
case Device.Android:
client = new HttpClient(DependencyService.Get<IHttpClientHandlerService>().GetInsecureHandler());
break;
default:
System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
client = new HttpClient(new HttpClientHandler());
break;
}
var response = await client.PostAsync(uri, new StringContent(payload, Encoding.UTF8, \"application/json\"));
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsStringAsync();
if (App.IsValidJson(data))
token = JsonConvert.DeserializeObject<TokenData>(data);
}
Then I added HaiNguyenCert.crt to Assets directory. Right-click on that file->properties and set Build Action=AndroidAsset (It took me sometimes to realize this)
The Question is why do you want to test for one single certificate? You will have to always update your app and server together when there is a change in certificate.
In debug mode I use this :
public class HttpClientHandlerService : IHttpClientHandlerService
{
public HttpClientHandler GetInsecureHandler()
{
HttpClientHandler handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
{
// if (cert.Issuer.Equals("CN=localhost"))
return true;
// return errors == System.Net.Security.SslPolicyErrors.None;
};
return handler;
}
}
In release :
new HttpClient(); works for me. I already released an app with this. Your server should have a certificate.
@Viplav04
Good question! I don't know exactly why I need this. I chased down this rabit hole because my Android app failed to make call to my https API server same app works fine on iOS devices, so I am trying everything I can get my hand on. ;-(
Goodness. Issue has been identified. it has nothing to do with any this. It was the dame my company's wifi access point. I lost so many days and energy on this. I really want to FOL
Answers
There are several blogs talking about the certificate pinning on the internet.
Refer to
https://thomasbandt.com/certificate-and-public-key-pinning-with-xamarin
https://www.c-sharpcorner.com/article/certificate-pinning-in-xamarin-forms/
Hi
Refering to https://thomasbandt.com/certificate-and-public-key-pinning-with-xamarin
and using AndroidHttpsClientHandler in Plan B, how to call the new handler in the pcl project??
Hi guy !
Is this still working currently? I tried but no luck, a side that ModernHttpClient is not kept up today, last version is 2015. I have been stuck with this same issue on Xamarin Forms/Android last few days. I have been able to resolve this issue. It is so frustrating. Very appreciate your help.
@HaiNguyen.6340
Hi, this problem went away from me. I simply use the normal HttpClient.
if DEBUG
else
endif
You can create an insecure handler in the Android and IOS project for debugging.
In Release mode, you only need a SSL certificate at the server.
@Viplav04 - Thanks for your response.
1) So am I correct to say....unless I deploy using DEBUG build, RELEASE works just fine by using just this?
var client = new HttpClient();
In my case, I never work with either DEBUG or RELEASE. Would you mind sharing your HttpClientHandlerService & IHttpClientHandlerService classes?
2) Do you see this implementation being an issue with API server runs on TLS1.2 (TLS 1.0 disabled)
3) Below is my implementation using Thomas Bandt Plan B, What am I missing?
in portable project I added IHttpClientHandlerService.cs
in android project I added this HttpClientHandlerService.cs, notice I replaced my certificate file name
in portable project App.cs I added call API as follow
Then I added HaiNguyenCert.crt to Assets directory. Right-click on that file->properties and set Build Action=AndroidAsset (It took me sometimes to realize this)
Thank you for all the helps!
@HaiNguyen.6340
The Question is why do you want to test for one single certificate? You will have to always update your app and server together when there is a change in certificate.
In debug mode I use this :
In release :
new HttpClient(); works for me. I already released an app with this. Your server should have a certificate.
@Viplav04
Good question! I don't know exactly why I need this. I chased down this rabit hole because my Android app failed to make call to my https API server same app works fine on iOS devices, so I am trying everything I can get my hand on. ;-(
Goodness. Issue has been identified. it has nothing to do with any this. It was the dame my company's wifi access point. I lost so many days and energy on this. I really want to FOL