2

My Android application is supposed to communicate with a ASP.net web api which is written in C#.Net. The data which is sent from the phone contains data that should not be exposed to the public. So I'm trying to use the https protocol. On my serverside I require all requests to be HTTPS, like this:

RequireRegisteredImei

public class RequireRegisteredImeiAttribute : AuthorizationFilterAttribute
    {
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            var request = actionContext.ControllerContext.Request;

            if (request.RequestUri.Scheme == Uri.UriSchemeHttps)
            {
               //OKAY
            }
            else 
            {
             actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
            }
        }
     }

And in the Controller:

[RequireRegisteredImei]
public string Post()
{
}

I debugged this code by sending a simple http request from my phone, and this code works quite well, it will deny me.

So, I started looking at how I could send requests over https from my android phone. I came up with something like this:

public static DefaultHttpClient getSecureHttpClient() {
        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
        schemeRegistry.register(new Scheme("http", SSLSocketFactory.getSocketFactory(), 80));
        BasicHttpParams params = new BasicHttpParams();
        SingleClientConnManager mgr = new SingleClientConnManager(params, schemeRegistry);
        return new DefaultHttpClient(mgr, params);
    }

I'm using this method this way:

HttpClient httpClient = CustomHttpClient.getSecureHttpClient();

This will only result in an IOException: No peer certificate

I've read several threads regarding this:

Problems with https (No peer certificate) in android

Android SSL - No Peer Certificate

'No peer certificate' error in Android 2.3 but NOT in 4

But there has to be a simpler way to post data over HTTPS from android?

Community
  • 1
  • 1
Tobias Moe Thorstensen
  • 8,861
  • 16
  • 75
  • 143
  • 1
    From an MVC point of view, there is already a [RequireHttpsAttribute](http://msdn.microsoft.com/en-us/library/system.web.mvc.requirehttpsattribute%28VS.100%29.aspx) which forces any `HTTP` calls onto `HTTPS`. – James Jan 21 '13 at 09:38
  • @James So what you are saying is that if I do a post to this url `http://whatever-webservice/api/Login` it will automagically force the connection to be `HTTPS`? – Tobias Moe Thorstensen Jan 21 '13 at 09:44
  • 1
    Yep. Essentially what it does is forces the request to be re-sent securely (so will refuse any non-secure requests automatically). Not sure if you explicitly want your API to return a 403 on the event of a non-secure request being sent. However, it would mean less work at your client end having to deal with that response. – James Jan 21 '13 at 09:53

2 Answers2

1

If you have a custom certificate or a certificate issued by a CA that is not included in all Android versions you can include the certificate into your app and use it directly.

To do so you have to import your server certificate (without the key of course) into a BKS key-store which then can be used as custom trust store.

A very good tutorial which describes how to do so is Using a Custom Certificate Trust Store on Android.

In difference to the standard solutions like EasyTrustManager or DummyTrustManager you find of Stackoverflow this solution doesn't disable the authentication of SSL and is therefore not insecure like the other solutions.

Robert
  • 39,162
  • 17
  • 99
  • 152
  • Thanks for your answer. I've seen that all the example regarding this topic includes certificates. How should I match this certificate on the server-side? Just install it, or? – Tobias Moe Thorstensen Jan 21 '13 at 11:08
  • 1
    If it is a custom or un-trusted certificate the best way is to include the certificate in your app (in form of an custom trust store). – Robert Jan 21 '13 at 11:09
1

You can also configure the HttpClient to accept all certificates like this :

    SSLSocketFactory sslSocketFactory=SSLSocketFactory.getSocketFactory();
    HostnameVerifier hostnameVerifier=org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
    sslSocketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);

    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(
            new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    schemeRegistry.register(
            new Scheme("https", sslSocketFactory, 443));

if you think that this may be a solution for you.

Ovidiu Latcu
  • 71,607
  • 15
  • 76
  • 84