Hello,
my app connects to a server that typically has a self signed certificate. I know that this is not perfect and I will show a warning to the user, but at least for now I need to able to accept all server certificates in my Xamarin.Forms project.
I use System.Net.Http.HttpClient and I have not found a universal solution.
ServerCertificateCustomValidationCallback and ServicePointManager.ServerCertificateValidationCallback are apparently not available for UWP.
How could I solve this issue to use Xamarin.Forms with an HttpClient that accepts all certificates?
In case anybody is having a similar problem: I solved this using DependecyService which implemented the Windows.Web.Http.Httpclient for UWP and the System.Net.Http.HttpClient version for Android/iOS. With this I was able to accept server certificates.
Hello,
I will gladly share my code. I hope you are familiar with Dependency Service, otherwise this might be complicated.
In my Xamarin.Forms app, I use this code on all platforms:
public interface IServerCommunication { Task<string> GetFromServerAsync(string URL); } //later on, when I download the data: (URL is a provided string) string result = await DependencyService.Get<IServerCommunication>().GetFromServerAsync(URL);
I implement the interface for UWP and Android different. This is for UWP:
public async Task<string> GetFromServerAsync(string URL) { HttpClient client = await PreparedClientAsync(); HttpResponseMessage response; try { response = await client.GetAsync(new Uri(URL)); IBuffer buffer = await response.Content.ReadAsBufferAsync(); DataReader reader = DataReader.FromBuffer(buffer); byte[] fileContent = new byte[reader.UnconsumedBufferLength]; reader.ReadBytes(fileContent); string result = Encoding.UTF8.GetString(fileContent, 0, fileContent.Length); return result; } catch (Exception ex) { return "error"; } } private async Task<HttpClient> PreparedClientAsync() { var filter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter(); filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired); filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted); filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName); HttpClient client = new HttpClient(filter); //I also handle other stuff here (client certificate, authentification), but the lines above should allow the Httpclient to accept all certificates return client; }
This is for Android (should also work on iOS, but I have not tried it out):
public async Task<string> GetFromServerAsync(string URL) { HttpClient client = PreparedClient(); HttpResponseMessage response = new HttpResponseMessage(); try { response = await client.GetAsync(URL); string result = await response.Content.ReadAsStringAsync(); return result; } catch (Exception ex) { return "error"; } } private HttpClient PreparedClient() { HttpClientHandler handler = new HttpClientHandler(); //not sure about this one, but I think it should work to allow all certificates: handler.ServerCertificateCustomValidationCallback += (sender, cert, chaun, ssPolicyError) => { return true; }; HttpClient client = new HttpClient(handler); return client; }
Answers
did you try calling the service using http instead of https?
I haven't tried this myself but maybe it'll help.
https://forums.xamarin.com/discussion/124695/exception-while-trying-to-connect-a-server-w-o-a-certificate
No, it requires https.
The link you provided only covers a solution using ServicePointManager.ServerCertificateValidationCallback which is (as far as I know) not available for UWP.
In case anybody is having a similar problem: I solved this using DependecyService which implemented the Windows.Web.Http.Httpclient for UWP and the System.Net.Http.HttpClient version for Android/iOS. With this I was able to accept server certificates.
@kingmathers could you please share your code with us? I am having this issue and I am having a hard time to implement the Dependency Service you were talking about.
Thanks.
Hello,
I will gladly share my code. I hope you are familiar with Dependency Service, otherwise this might be complicated.
In my Xamarin.Forms app, I use this code on all platforms:
I implement the interface for UWP and Android different. This is for UWP:
This is for Android (should also work on iOS, but I have not tried it out):