James Montemagno: iOS Tip: Force UIWebView to Display Mobile Sites on iPad

So this is actually a very odd tip with a very specific use case. When you embed a UIWebView into your application and feed it static content it will simply render what you tell it to. An issue may arise when you actually have to embed dynamic web content into your application. Hopefully this is a rare case and you are building native apps with Xamarin and C#, but there is one specific case where you have to use a WebView…oAuth. Yes, oAuth! You can’t get around it unless you have your own special oAuth protocol. If you need to tap into facebook, twitter, meetup.com, office, etc you are going to have to present a webview and follow the standard oAuth process. Luckily if you are building your apps with Xamarin then you can use Xamarin.Auth for both iOS and Android, which handles the heavy lifting. 

Why force a mobile site in UIWebView?

When using oAuth you are simply directing your user to a web page that has a login screen. Most oAuth login pages have a mobile view, which gives your users a nice experience, but what happens on an iPad? Well, let’s take a look at meetup.com’s oAuth page:

So…. this doesn’t look so great on the iPad and this is because the meetup.com’s oAuth page has decided to show the full website login page instead of the mobile optimized for the iPad. This makes some sense because the iPad is so large and it could handle the full site with it’s larger surface. To me this isn’t a great experience and can even break the oAuth flow to and from mobile pages. So we can fix it!

The UserAgent Fix!

Our good friend User-Agent comes to the rescue. User agent is an http header that helps with content negotiation from a device to a website. In this case the iPad is telling the meetup.com website that it is an iPad and has a large screen. The work around is to simply spoof the UserAgent header that the iPad is sending from our application. Simply add 2 lines of code into your ApplicationDelegate’s FinishedLaunching method:

Now whenever the iPad sends request to a website, the website will think it is an iPhone. I simply grabbed this user agent from whatsmyuseragent.com so if you want to use a different one go for it! Here is our new oAuth page:

Xamarin: Webinar Recording: Mobile Enterprise Success with Xamarin and Oracle

We’re excited to help our customers build better enterprise apps through our recently announced partnership with Oracle. With this partnership, developers can build native iOS and Android Xamarin apps that quickly integrate with Oracle Mobile Cloud Service (MCS) for robust backend functionality, including push notifications, mobile APIs, storage, analytics, and more. Watch the recording of […]

The post Webinar Recording: Mobile Enterprise Success with Xamarin and Oracle appeared first on Xamarin Blog.

Xamarin: Bringing Xamarin.Forms Apps to Tablets

When I was developing My Shoppe, a pre-built app template for shops, I only focused on the look and feel for the phone form factor, since I knew that I could add optimizations to the app to spruce it up for tablet owners later. Xamarin.Forms makes it simple to detect what type of device my […]

The post Bringing Xamarin.Forms Apps to Tablets appeared first on Xamarin Blog.

Xamarin: Building Apps for a Connected World

Building apps for a connected world can be tough; users expect their apps to work all the time, even with a slow (or possibly even no) mobile connection. This week on the Xamarin Podcast, Mike and I share some of our secrets for building connected apps, such as how to speed up network requests, create a […]

The post Building Apps for a Connected World appeared first on Xamarin Blog.

Matthew Leibowitz: Enabling TLS v1.2 on Android 4.2

While I was busy making self-signed certificates work on Android, I had to add support for TLS version 1.2 on Android 4.2. Although it is supported, it is disabled by default.

The SSL Socket Factory

Enabling TLS support is relatively easy in that we just wrap the DefaultSSLSocketFactory in a new SSLSocketFactory, and when a socket is created, we enable all the supported protocols:

private class CompleteSSLSocketFactory : SSLSocketFactory
{
    private readonly SSLSocketFactory innerFactory;

    public CompleteSSLSocketFactory()
    {
        this.innerFactory = HttpsURLConnection.DefaultSSLSocketFactory;
    }

    public override string[] GetDefaultCipherSuites()
    {
        return innerFactory.GetDefaultCipherSuites();
    }

    public override string[] GetSupportedCipherSuites()
    {
        return innerFactory.GetSupportedCipherSuites();
    }

    public override Socket CreateSocket()
    {
        return MakeSocketSafe(innerFactory.CreateSocket());
    }

    public override Socket CreateSocket(Socket s, string host, int port, bool autoClose)
    {
        return MakeSocketSafe(innerFactory.CreateSocket(s, host, port, autoClose));
    }

    public override Socket CreateSocket(string host, int port)
    {
        return MakeSocketSafe(innerFactory.CreateSocket(host, port));
    }

    public override Socket CreateSocket(string host, int port, InetAddress localHost, int localPort)
    {
        return MakeSocketSafe(innerFactory.CreateSocket(host, port, localHost, localPort));
    }

    public override Socket CreateSocket(InetAddress host, int port)
    {
        return MakeSocketSafe(innerFactory.CreateSocket(host, port));
    }

    public override Socket CreateSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
    {
        return MakeSocketSafe(innerFactory.CreateSocket(address, port, localAddress, localPort));
    }

    private Socket MakeSocketSafe(Socket socket)
    {
        var sslSocket = socket as SSLSocket;
        if (sslSocket != null) {
            // enable all supported protocols for this socket
            sslSocket.SetEnabledProtocols(sslSocket.GetSupportedProtocols());
            sslSocket.SetEnabledCipherSuites(sslSocket.GetSupportedCipherSuites());
        }
        return socket;
    }
}

The HTTP Client

Now, we just pass an instance of the factory to the client using SetSslSocketFactory. Although, we caould probably create a singleton for the factory:

// create a new OkHttpClinet 
var client = new OkHttpClient();
// only for the older Androids do we do this
if (Android.OS.Build.VERSION.SdkInt < BuildVersionCodes.Lollipop) {
    client.SetSslSocketFactory(new CompleteSSLSocketFactory()); 
}

Matthew Leibowitz: Self-Signed Certificates and Xamarin.Android

Recently, I had the opportunity to work with Android and self-signed certificates. This is both simple and complex at the same time. In order for Android to be able to handle self-signed certificates, those certificates have to be registered with the SSLSocketFactory.

The HTTP Client

What we will need to do is create a new SSLSocketFactory, and pass that to the HTTP client. In this case, we are using OkHttpClient to communicate over the network. OkHttp is an HTTP+SPDY client for Android applications, and can be found:

Once we have the socket factory, we pass it to the OkHttpClient using the SetSslSocketFactory method:

// get the socket factory
var socketFactory = GetSocketFactory();
// create a new OkHttpClinet 
var client = new OkHttpClient();
// add the socket factory to the client
client.SetSslSocketFactory(socketFactory);
// now we can use the client as usual
Request request = new Request.Builder().Url("https://<yourserver>").Build();
Response response = await client.NewCall(request).ExecuteAsync();
var body = await response.Body().StringAsync();

SSL The Socket Factory

In order to create the socket factory, we will need the self-signed certificate. This can be downloaded from the website, or obtained from the source. Then, we must include it in the app. In this instance, I have added it as a raw resource. Loading the certificate into the socket factory consists of a few steps:

  1. Load the certificate out of the resources/assets and into a Certificate instance
  2. Create a new KeyStore instance, and add the Certificate
  3. Create a new TrustManagerFactory instance from the KeyStore
  4. Get the IX509TrustManager from the TrustManagerFactory
  5. Create the new SSLContext, and initialize with the IX509TrustManager
  6. Get the SocketFactory from the SSLContext

Here is the code that does this:

/// <summary>
/// This method returns the configured SSLSocketFactory that contains
/// the self-signed certificate.
/// </summary>
public static SSLSocketFactory GetSocketFactory()
{
    // 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 algorithm = TrustManagerFactory.DefaultAlgorithm;
    var trustManagerFactory = TrustManagerFactory.GetInstance(algorithm);
    trustManagerFactory.Init(keyStore);
    var trustManagers = trustManagerFactory.GetTrustManagers();
    var trustManager = trustManagers[0].JavaCast<IX509TrustManager>(); 

    // Create an SSLContext that uses our TrustManager
    var context = SSLContext.GetInstance("TLSv1.2");
    context.Init(null, new ITrustManager[]{ new CompleteX509TrustManager(trustManager) }, null);    

    // return the final socket factory
    return context.SocketFactory;
}

The Trust Manager

Because we are usinmg a custom trust manager with a custom keystore that only contsins the one self-signed certificate, all other certificates will be rejected. To avoid this, we wrap the trust manager in a new trust manager that first tries the default trust manager. Only when the default trust manager fails to verify the certificate, we try the custom trust manager:

/// <summary>
/// This trust manager wraps a custom socket factory and provides a
/// fallback to the default trust manager with the system certificates.
/// This allows the app to communicate not only with a self-signed 
/// server, but also servers with certificates from a CA.
/// </summary>
public class CompleteX509TrustManager : Java.Lang.Object, IX509TrustManager
{
    private readonly IX509TrustManager defaultTrustManager;
    private readonly IX509TrustManager localTrustManager;

    public CompleteX509TrustManager(IX509TrustManager localTrustManager)
    {
        this.localTrustManager = localTrustManager;

        var algorithm = TrustManagerFactory.DefaultAlgorithm;
        var defaultTrustManagerFactory = TrustManagerFactory.GetInstance(algorithm);
        defaultTrustManagerFactory.Init((KeyStore)null);
        var trustManagers = trustManagerFactory.GetTrustManagers();
        defaultTrustManager = trustManagers[0].JavaCast<IX509TrustManager>();
    }

    public void CheckClientTrusted(X509Certificate[] chain, string authType)
    {
        // we are the client
    }

    public void CheckServerTrusted(X509Certificate[] chain, string authType)
    {
        try {
            defaultTrustManager.CheckServerTrusted(chain, authType);
        } catch (CertificateException) {
            localTrustManager.CheckServerTrusted(chain, authType);
        }
    }

    public X509Certificate[] GetAcceptedIssuers()
    {
        // we are not the server
        return null;
    }
}

Some of the namespaces used are in the Java and Javax namespaces:

using Java.Interop;
using Java.Net;
using Java.Security;
using Java.Security.Cert;
using Javax.Net.Ssl;

Xamarin: Close Out Summer with Xamarin Events in August!

Celebrate the end of summer with a bang by joining fellow Xamarin developers at an event near you! This month is jam-packed full of exciting conferences, workshops, seminars, and user group meetups from all corners of the globe! Here’s just a taste of events happening this month: Xamarin Dev Days – Birmingham Birmingham, UK: August 2nd Discover […]

The post Close Out Summer with Xamarin Events in August! appeared first on Xamarin Blog.

Xamarin: Xamarin Named Leading Visionary in the Gartner Magic Quadrant

Based on our vision and ability to execute, we’re honored to be recognized as the leading Visionary in the recently published 2015 Gartner Magic Quadrant Report for Mobile Application Development Platforms. Acknowledging the role of mobility as a cornerstone for every business development strategy, Gartner assesses the critical for mobile app development platform market by […]

The post Xamarin Named Leading Visionary in the Gartner Magic Quadrant appeared first on Xamarin Blog.