6

I have an Ionic 2 application that calls a Spring Boot API to send push notifications to other devices. The API is configured with HTTPS.

The API POST request works on everything except iOS.

My SSL certificate on the server is self signed (maybe that's it?).

Works on:

  • ionic serve
  • Android
  • Postman
  • curl

Here is the request:

public sendNotificationRequest(title: string, action: string, name: string, tokens: any, notifications: boolean) {
    // Check if user turned off notifications
    if(!notifications) {
        return;
    }

    let headers = new Headers({'Content-Type': 'application/json'});
    headers.append('Authorization', 'Basic ' + btoa(this.username_decrypted + ':' + this.password_decrypted));
    let body = this.formObj(tokens, title, action, name);
    console.log(body);

    this.http.post("https://<some-url>",
                    body, { headers: headers }
    ).subscribe((response) => {
        console.log("HTTPS RESPONSE");
        console.log(response);
    }, function(error) {
        console.log("HTTPS ERROR");
        console.log(error);
    });
}

The header responses are as follows:

response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");

And the this error is received:

{
 "_body":
    {"isTrusted":true},
    "status":0,"ok":false,
    "statusText":"",
    "headers":{},
    "type":3,
    "url":null
}

Spring Boot API:

@CrossOrigin
@RequestMapping(value="/notifications", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE, produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<NotificationParent> sendNotifications(@RequestBody NotificationParent objs) {
    ...
    return new ResponseEntity<NotificationParent>(objs, HttpStatus.OK);
}

I am assuming its an iOS security issue, but I have no idea.

theblindprophet
  • 7,767
  • 5
  • 37
  • 55
  • Try this - http://uncaughterror.com/programming/ionic3/preflight-response-issue-with-ionic3-app-on-ios-build-only-resolved/ – sijo vijayan Nov 29 '17 at 14:29

4 Answers4

4

I had a same problem too. Removing the WkWebView solves the issue.

ionic cordova plugin remove cordova-plugin-wkwebview-engine

More info:

https://forum.ionicframework.com/t/ios10-http-requests-blocked/67663/2?u=profitsventure

After this plugin removed I can make http request via iOS

  • How did that help you? Was it the same problem as mentioned in the question? – zubair1024 Oct 31 '17 at 13:23
  • @zubair1024 try this http://uncaughterror.com/programming/ionic3/preflight-response-issue-with-ionic3-app-on-ios-build-only-resolved/ – sijo vijayan Nov 29 '17 at 14:28
  • Similarly, I had to run 'ionic cordova plugin rm cordova-plugin-ionic-webview ' to get our app working again with the latest Ionic CLI. Sweet Christmas Ionic development is frustrating. – Luke Feb 07 '18 at 04:26
3

I think your assumption is correct-- an iOS security issue. In iOS there is something called App Transport Security that disallows, by default, connections over HTTP and connections with self-signed certificates.

You have to add

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

to the Info.plist of your project to allow your self-signed traffic.

See this answer as well as the below links for more info.

http://blog.ionic.io/preparing-for-ios-9/

https://gist.github.com/mlynch/284699d676fe9ed0abfa

https://developer.apple.com/library/prerelease/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33

Community
  • 1
  • 1
Daniel
  • 158
  • 1
  • 14
1

For iOS devices, the default WebViewEngine always uses CORS, to disable it temporarily, add the <preference name="CordovaWebViewEngine" value="CDVUIWebViewEngine" /> to the config.xml. However, the downgrading to UIWebViewEngine has bad performance. Solving it in the server side is the right solution.

The HTTP server should be configured to have the right response to the CORS OPTIONS preflight request. The key point is that the Access-Control-Allow-Headers can not be “*” and should include any custom headers used in your app. Below is my setting that works:

Access-Control-Allow-Origin: * Access-Control-Allow-Methods: * Access-Control-Allow-Headers: Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, MyCustomHeader

Ying
  • 2,660
  • 24
  • 23
0

For me the fix was to use @ionic-native/http instead of @angular/http.

Ionic native HTTP docs: https://ionicframework.com/docs/native/http/

Here's what lead me to that workaround https://blog.ionicframework.com/wkwebview-for-all-a-new-webview-for-ionic/

matt.mercieca
  • 853
  • 1
  • 6
  • 13
  • Where do we place the certificate file for ios? – Shraddha Shravagi Jun 21 '18 at 04:36
  • Why do you think you need a certificate? If you need one specifically for your iOS app, you'd have to place it in the Xcode project separately. But without knowing the error that led you there it's hard to know which kind of certificate it is. – matt.mercieca Jun 22 '18 at 19:13
  • I already have one for our server which is a self signed. If I place it in xcode it is giving error for pinned certificate. – Shraddha Shravagi Jun 24 '18 at 06:52
  • The problem is when trying to enable ssl pinning, the pinned certificate is not found even when included at proper location in project. – Shraddha Shravagi Jun 24 '18 at 16:19