-
Notifications
You must be signed in to change notification settings - Fork 27
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 Square.OkHttp with Android 4.2, a TLS 1.2 site and SSL self-signed certificates #1
Comments
Does this fix it? http://bit.ly/1Mn90In
Docs: http://developer.android.com/reference/javax/net/ssl/SSLSocket.html Note, you shouldn't have to adjust the thread policy: OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().Url("https://<yourserver>").Build();
// UI thread here
Response response = await client.NewCall(request).ExecuteAsync(); // run on a new thread here
// UI thread here
string body = await response.Body().StringAsync(); // read on a new thread here
// UI thread here
System.Diagnostics.Debug.WriteLine (body); |
There are several ways you can use var body = response.Body (); // no work
using (var bodyStream = body.ByteStream ())
using (var memory = new MemoryStream ()) {
await bodyStream.CopyToAsync (memory); // read work
}
var bodyBytes = await body.BytesAsync (); // read work
var bodyString = await body.StringAsync (); // read work |
Example usage of the gist in the provided example would be: OkHttpClient client = new OkHttpClient ();
// only include our custom factory for the older Androids
if (Android.OS.Build.VERSION.SdkInt < BuildVersionCodes.L) {
client.SetSslSocketFactory (new CompleteSSLSocketFactory ());
}
Request request = new Request.Builder ().Url ("https://<yourserver>").Build ();
// UI thread here
Response response = await client.NewCall (request).ExecuteAsync (); // run on a new thread here
// UI thread here
string body = await response.Body ().StringAsync (); // read on a new thread here
// UI thread here
System.Diagnostics.Debug.WriteLine (body); |
Thank you. This works well but introduced a new challenge. Prior to this solution I used the HttpClientHandler in the PCL project as the http client and all I needed to do is to add the following to the MainActivity OnCreate method to allow self-signed server certificates. ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AllwaysGoodCertificate); And provide the following method: private static bool AllwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) {
return true;
} With the new solution self-signed certificates won't work. Following the examples provided here http://stackoverflow.com/questions/1217141/self-signed-ssl-acceptance-android there seem to be two approaches: A) Provide my own host name verifier and trust manager Any thoughts? |
@mazloumi It really depends on what the self-signed certificates are used for. If it is purely for development, then you could probably safely just ignore all certificates. It is highly advisable to make sure any such code is wrapped in However, it is not too hard to provide the certificate in the Android app. I have updated the gist to demonstrate 2 ways in which we can handle self-signed certificates, or certificates from an unknown CA. The gist that has been updated: http://bit.ly/1Mn90In Here is the code that will take a // Load our certificate from resources (we created this one using OpenSSL and
// saved as a .cer using Windows' certlm console)
var certificateFactory = CertificateFactory.GetInstance ("X.509");
Certificate certificate;
using (var stream = Application.Context.Resources.OpenRawResource (Resource.Raw.selfsigned)) {
certificate = certificateFactory.GenerateCertificate (stream);
}
// Create a KeyStore containing our trusted CAs
var keyStore = KeyStore.GetInstance (KeyStore.DefaultType);
keyStore.Load (null, null);
keyStore.SetCertificateEntry ("ca", certificate);
// Create a TrustManager that trusts the CAs in our KeyStore
var trustManagerFactory = TrustManagerFactory.GetInstance (TrustManagerFactory.DefaultAlgorithm);
trustManagerFactory.Init (keyStore);
var trustManager = trustManagerFactory.GetTrustManagers () [0].JavaCast<IX509TrustManager> ();
// Create an SSLContext that uses our TrustManager
var context = SSLContext.GetInstance ("TLSv1.2");
context.Init (null, new ITrustManager[]{ trustManager }, null);
// apply the new context
var socketFactory = context.SocketFactory; Important note: use It is highly advisable to not just use a single certificate as done here:
Doing this will prevent all other SSL sites from working. You can use a wrapped trust manager that first tries the default trust manager, and then tries our custom trust manager. Depending on which requests are more common, they can be the other way around: public void CheckServerTrusted (X509Certificate[] chain, string authType)
{
try {
defaultTrustManager.CheckServerTrusted (chain, authType);
} catch (CertificateException) {
localTrustManager.CheckServerTrusted (chain, authType);
}
} Here are some docs that are a good read: http://developer.android.com/training/articles/security-ssl.html#UnknownCa |
Thank you. This was very helpful. |
Matthew, Have you seen examples out there of using self-signed client certificates? Kind regards,
|
Mazloumi |
@mazloumi, what @josephkandi suggested is probably the best option, then, there is no issues at all. However, if that is not possible, you should be able to use certificates from a trusted source - as in the example of https://certs.cac.washington.edu/CAtest. I wouldn't have my server using my self-signed certificates. Especially since I many not be the only client. Also, when using self-signed certificates, any changes to the certificate will require updates to all the clients - which cannot always be guaranteed. |
I found the square.OkHttp on Nuget and I tried to use it in Xamarin but it throws an error. Can you perhaps help?
Here is the code I am using in the MainActivity class:
And the error I get is this:
The text was updated successfully, but these errors were encountered: