Using Ajax to GET and POST data is general choice when we are developing hybrid applications. In my latest project, I am using cordova (phonegap) to build an iOS app with HTML5, javascript and css. In this app, all conmunication in this app will use AJAX. This approach will extremely increase the project development speed. To enhence the safety, we are using HTTPs when we are using Ajax to get and post data in our mobile apps. With AJAX, we can develop the HTML project in HTMl browsers like Chrome, Safari or Firefox. After we finish the project, we can easily deploy the whole project in iOS and Android with cordova (phonegap).
When working in this approach, I met with several problems when I develop the project with AJAX and HTTPS. Here I will share my experience with you and all solutions are found on internet and tested in my project.
AJAX Cross Domain Problem in Hybrid Problem
When working with AJAX, cross-domain problem is the most common issue we could meet with. Before developing mobile app in UIWebView, the problem already exists when a website A is trying Ajax call to a website B, especially when we are testing on localhost. It is called cross-domain ajax calling, also called cross-origin HTTP request. For security reasons, browsers doesn’t allow Ajax cross domain HTTP requests. So, AJAX can only make HTTP requests to its own domain. To overcome this constrain, here are several ways.
AJAX Call on The Same Domain
This is the simplest way to go around the problem. But usually, it is just because we cannot put them on the same server and we have to face the cross-domain problem.
JSONP
Using JSONP will enable you to do cross domain JSON requests. But it doesn’t support HTTP POST, PUT and DELETE. So I will not go deep in this method.
Proxy
If you host your website on domain-a.com, and you want to get resource from domain-b.com by AJAX. You can implement a proxy on your website backend. You can make the request to your website backend proxy and the proxy can do a request to retrieve resource from domain-b.com, then return to your website.
HTTP Access Control
The best way to solve the problem is using cross-origin resource sharing (CORS). The approach is very simple, adding following option in the HTTP header:
Access-Control-Allow-Origin: *
For more information, you can check Cross-Origin Resource Sharing (CORS) on MDN. Here is another good article to explain the CORS.
Allow Unverified SSL Certificate in UIWebview
Another problem is making HTTPS Request by AJAX. When we visit a website with https, the browser will verify the given certificate automatically. If the certificate is self-signed certificate, the browser will popup a window to let you choose if you want to accept this invalid. However, when we make HTTPS request by AJAX, there is no way for us to manually accept the certificate. Therefore, the AJAX HTTPS calling will result in fail.
One solution for that is purchasing a valid certificate from authentication organization. But in the most of cases, we are using self-signed certificate (invalid certificate). So we need to find a way to solve the problem.
In iOS 9, SSL connections will fail for all invalid or self-signed certificates. This is the default behavior of the new App Transport Security feature in iOS 9.0 or later, and on OS X 10.11 and later. We can override this option in Info.plist. In the NSAppTransportSecurity dictionary, set NSAllowsArbitraryLoads to YES.
If we are using NSURLSession to connect HTTPS webservice or API, we can implement delegate method:
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { if([challenge.protectionSpace.host isEqualToString:@"mydomain.com"]){ NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential,credential); } } }