ionic-team / cordova-plugin-ionic-webview

Web View plugin for Cordova, specialized for Ionic apps.
Apache License 2.0
486 stars 393 forks source link

iOS v12 Https requests errors / Https requests don't reach backend #112

Closed peterpeterparker closed 6 years ago

peterpeterparker commented 6 years ago

Bug Report

Describe the Bug

We, I and other Ionites, noticed that https requests on iOS v12 are failing respectively never reach our backends. Some are facing preflight error or typical CORS errors but in any case, requests aren't reaching our backend.

When it comes to me, I could confirm that my app is productive and the fact that this error only occurs on iOS >= v12

Errors

In Xcode 10 Beta I get the following error:

{“headers”:{“normalizedNames”:{},“lazyUpdate”:null,“headers”:{}},“status”:0,“statusText”:“Unknown Error”,“url”:null,“ok”:false,“name”:“HttpErrorResponse”,“message”:“Http failure response for (unknown url): 0 Unknown Error”,“error”:{“isTrusted”:true}}

I added so much log I could on my backend API side, unfortunately nothing was parsed, it looks like nothin reach it

Report

I have reported my problem to Apple too. Can't tell if it's an iOS v12 bug or an improvement which should be developed in the WkWebView plugin in order to be compatible for v12, therefore I allowed my self to open this issue

Other resources

Discussion on the Ionic forum: https://forum.ionicframework.com/t/ios-12-beta-preflight-requests-fail/132177/9

Open radar about a similaire issue: https://openradar.appspot.com/radar?id=4959044250894336

Stackoverflow: https://stackoverflow.com/questions/50707146/ios-v12-https-requests-errors

Version

cordova-plugin-ionic-webview: 1.2.1 ionic-angular: 3.9.2 angular/http: 5.0.0 node: 10.2.1

Note

It fails with any https requests but if you need a repo to reproduce the problem, sure let me know, I will take the time if needed

Node / Express

I set the following headers in my backend, which like I said, works find till iOS < v12

var allowedOrigins = ["https://example.com", "http://ionic.local", "http://localhost:8080"];

 var origin = req.headers.origin;
 if(allowedOrigins.indexOf(origin) > -1){
        res.setHeader('Access-Control-Allow-Origin', origin);
 } else {
        res.setHeader("Access-Control-Allow-Origin", "https://example.com");
    }

 res.header("Access-Control-Allow-Credentials", "true") 
 res.header("Access-Control-Allow-Headers", "Origin, Authorization, Content-Type, Content-Range, Content-Disposition, Content-Description, X-Requested-With, X-ACCESS_TOKEN");
 res.header("Access-Control-Allow-Methods", "GET,PUT,POST");

Note: Even if I set res.setHeader('Access-Control-Allow-Origin', '*'); if won't work, really have the feeling the https query doesn't reach the backend, I did add some logging in that section of my backend but nothing was logged

Side note

On the same simulated device with iOS v12, I opened Safari and used my Angular web app to see if I was facing the same problem (in my web app I use angular http too the query the same backend) which actually wasn't the case, no problem there

mhartington commented 6 years ago

@peterpeterparker Thanks for the issue! We'll be tracking this and keeping an eye on things. WWDC builds of iOS tend to have quite a few bugs, so we'll need to keep checking this, as it could be a bug in this build of WKWebview

peterpeterparker commented 6 years ago

@mhartington really nice to hear that, thx for the support 👍

Craytor commented 6 years ago

Also, for the record, I can attest that this is indeed an issue. I really hope Apple is able to resolve it!

lassic commented 6 years ago

Haven't tried iOS 12 yet, but I can say that from iOS > 11.3 WKWebView fails on navigator.sendBeacon to HTTPS. The same POST with XHR is successful (also HTTP is successful, it's a TLS issue).

The client seems to break the connection right after the TLS handshake is complete. and console shows "Failed HTTP authentication" error. Interestingly, forcing the browser to preconnect with: <link href='https://...' rel='preconnect' crossorigin/> before calling sendBeacon makes it succeed (seems that preconnect creates a valid TLS session that can then be reused).

Wild guess, but perhaps XHR in iOS 12 is now reusing the same code that broke sendBeacon in > 11.3?

Pittan commented 6 years ago

I'm facing with the same issue. I'm using just a WKWebView + Angular instead of ionic + cordova. I think it is a bug for WKWebView in v12, too. No problem with Safari here.

sunderls commented 6 years ago

run into this issue as well. Same CORS settings works on iOS11

Serlight commented 6 years ago

I test HTTP work well, but HTTPS run into this issue. when post with form-data work well, if post with son-data, will run into this issue

mewehren commented 6 years ago

IOS 12 beta2 fix it?

mhartington commented 6 years ago

@peluqui2010 Beta 2 is not out yet.

@peterpeterparker Could you create a sample test project to test against? This way, as new beta's are released, we can test against some real code. We can also test this in mobile safari as well since that also uses wkwebview

peterpeterparker commented 6 years ago

@mhartington sure I'll right now

Is it ok if I send you an invite to get the test project thru a private bitbucket repo? Not to difficult to find but still I would be happy to keep my productive api backend a bit under radar you know...

mhartington commented 6 years ago

Sounds good. it's mahrtington on bitbucket as well.

peterpeterparker commented 6 years ago

@mhartington I have build the same repo and invited you, let me know if everything is alright

IMPORTANT I discovered something really interesting while developing this sample repo, actually, Https GET queries are still fine with iOS v12 but I face problems with POST requests

GET = OK

const params: HttpParams = new HttpParams();
this.httpClient.get('https://example.com/route/', {params: params}).subscribe...

POST = KO

 let headers:HttpHeaders = new HttpHeaders();
 headers.append('Content-Type', 'application/json');
 this.httpClient.post('https://example.com/route/', {}, {headers: headers}).subscribe(....

Would be happy to hear if someone could confirm that

P.S.: I didn't tried PUT and DELETE

mhartington commented 6 years ago

@peterpeterparker are you in the ionic slack? Got a few questions for you

peterpeterparker commented 6 years ago

@mhartington don't think I'm now, you could send me an invite plz

Serlight commented 6 years ago

@peterpeterparker not all post run into issue, if you post with form-data will work well

peterpeterparker commented 6 years ago

@Serlight thx for the feedback, interesting

timbru31 commented 6 years ago

I can confirm that GET requests are working fine, but POST fails, too.

joseph commented 6 years ago

My testing isn't complete on this one but here are my notes so far, with what looks like a viable (albeit kludgy) workaround.

A cross-origin XHR request will fail in WKWebView at iOS 12 b1 if:

Setup:

var corsURL = "https://your-foreign-origin/endpoint";

A preflighted CORS request fails. In this example the Content-Type header triggers preflight:

var req = new XMLHttpRequest();
req.onload = function () { console.log(req.status); }
req.open("GET", corsURL, true);
req.setRequestHeader('Content-Type', 'application/json');
req.send();
[Error] Preflight response is not successful
[Error] XMLHttpRequest cannot load <cors-url> due to access control checks.
[Error] Failed to load resource: Preflight response is not successful

The server does not even receive the preflight (OPTIONS) request. Perhaps WKWebView is unintentionally applying CORS policy to the preflight request itself?

However, a regular CORS request succeeds:

var req = new XMLHttpRequest()
req.onload = function () { console.log(req.status); }
req.open("GET", "<cors-url>", true)
req.send()
=> 200

Thereafter, your preflighted CORS requests (at least to that domain) will succeed:

var req = new XMLHttpRequest();
req.onload = function () { console.log(req.status); }
req.open("GET", corsURL, true);
req.setRequestHeader('Content-Type', 'application/json');
req.send();
=> 200
joseph commented 6 years ago

Further testing indicates that the "permission" granted by a successful unpreflighted request can disappear — apparently after requests to other services, or perhaps when other webviews are spawned. Hard to say.

Anyway you probably want to put some retry logic in your request's onerror handler. Basically:

mhartington commented 6 years ago

Awesome, thanks for all the information/updates everyone.

For now, since we know this is a confirmed issue inside of iOS12/WKWebview proper, and not an error inside the plugin or any backends being used, let's hold off until the next build of iOS 12 is released.

Thanks for all the information 💪

peterpeterparker commented 6 years ago

For the record, the issue I opened at Apple as been closed and mark as duplicate of another bug they are tracking, probably means there is effectively a bug ;)

Hello David,

Engineering has determined that your bug report (40816482) is a duplicate of 39987152 and will be closed.

...

amourfrei commented 6 years ago

It can be work with Content-Type: application/x-www-form-urlencoded; charset=UTF-8 (if your server supported). it seems only affect appliaction/json .

gregavola commented 6 years ago

@amourfrei I can confirm that we are sending Content-Type: application/x-www-form-urlencoded; (no charset) and it does not work.

maxkunitsa commented 6 years ago

@peterpeterparker @mhartington issue fixed in iOS 12 beta 2. Get it from https://developer.apple.com/download/ :)

mlynch commented 6 years ago

Fuck yea

fabledfoe commented 6 years ago

Just finished our testing on beta 2. Can confirm issue has been fixed.

mhartington commented 6 years ago

~Im still seeing the issue on my end 🤔~

EDIT

Simple tests so far seem to be working fine!

peterpeterparker commented 6 years ago

it takes me ages to download beta 2, > 1 hour left, but looking forward to test too

peterpeterparker commented 6 years ago

I could confirm Xcode 10 beta 2 respectively iOS 12 beta 2 solves my problem, therefore I close this issue I opened

Thx all for your inputs and @mhartington for the support

Craytor commented 6 years ago

Also, I can confirm it is working again as expected as well!

Jialufeng commented 6 years ago

IOS 12 WeChat public number development pre detection failure。 How do you solve it, please?

devakone commented 5 years ago

Are there any other workarounds people have found for this issue? It's definitely easier to have users upgrade but we have a set of users on 12.1.2 and 12.1.3 for which this issue is still happening pretty consistently.

GroupeBEL commented 5 years ago

Hello, I still have the problem with ios12 ... any solution please ? (Cors are already implemented side server)

Capture d’écran 2019-06-26 à 12 48 33

Capture d’écran 2019-06-26 à 15 03 41

JianhuisHuang commented 4 years ago

Hi, every body, I have the same issue, anyone has solution? Please help me, thx.

samalfaro92 commented 4 years ago

Hello guys! Yeah, I have the same problem for iOS 12.4

chaitanyagupta76 commented 4 years ago

I am also facing same issue with xcode 11

renanbandeira commented 4 years ago

I am having this problem right now as well with iOS 13.4.1 and cordova-ios 6

dhruvshah1093 commented 4 years ago

Facing similar problem with no request reaching backend specifically for iOS 12.4.6 and older versions. Works as intended on android and browser . Cordova 9.0.0 cordova-iOS 5.1.1 cordova-plugin-ionic-webview 5.0.0 latest.

AlexanderTitian commented 4 years ago

Same issue here. Not sure If I'm missing something. I know this is due to the switch to the switch WkWebview and its new strict polices.

Code:

if(typeof defSet.setName == "string"){
    if(typeof defSet.filePath == "string"){
        $.getJSON(defSet.filePath, loadData).error(getLocalFile);
    } else {
        getLocalFile();
    }
}

Errors:

Origin app://myAppName is not allowed by Access-Control-Allow-Origin.
XMLHttpRequest cannot load http://192.168.1.179/SomeJsonFileIWant.json due to access control checks.
Failed to load resource: Origin app://myAppName is not allowed by Access-Control-Allow-Origin.

Cordova CLI: 10.0.0

config.xml:

<allow-navigation href="data:*" />
<allow-navigation href="app:*" />
<platform name="ios">
        <preference name="scheme" value="app" />
        <preference name="hostname" value="myAppName" />
        <preference name="WKWebViewOnly" value="true" />
        <feature name="CDVWKWebViewEngine">
            <param name="ios-package" value="CDVWKWebViewEngine" />
        </feature>
        <preference name="CordovaWebViewEngine" value="CDVWKWebViewEngine" />
        <preference name="Allow3DTouchLinkPreview" value="false" />
        <preference name="AllowBackForwardNavigationGestures" value="false" />
    </platform>

Cordova Platforms:

  android 8.1.0
  ios 6.1.0

Plugins:

cordova-android-support-gradle-release 2.0.1 "cordova-android-support-gradle-release"
cordova-plugin-appminimize 1.0.1 "AppMinimize"
cordova-plugin-camera 4.0.3 "Camera"
cordova-plugin-device 2.0.3 "Device"
cordova-plugin-dialogs 2.0.2 "Notification"
cordova-plugin-file 6.0.2 "File"
cordova-plugin-file-opener2 2.2.1 "File Opener2"
cordova-plugin-file-transfer 1.7.1 "File Transfer"
cordova-plugin-geolocation 4.0.2 "Geolocation"
cordova-plugin-inappbrowser 4.0.0 "InAppBrowser"
cordova-plugin-media-capture 3.0.3 "Capture"
cordova-plugin-network-information 2.0.2 "Network Information"
cordova-plugin-save-image 0.3.0 "SaveImage"
cordova-plugin-splashscreen 6.0.0 "Splashscreen"
cordova-plugin-statusbar 2.4.3 "StatusBar"
cordova-plugin-whitelist 1.3.4 "Whitelist"
cordova-plugin-wkwebview-inject-cookie 1.0.2 "WKWebViewInjectCookie"
mlynch commented 4 years ago

The above issues with Access-Control-Allow-Origin are all CORS issues. If your server does not allow the origin (in your case app://myAppName), the request will not be allowed. This is NOT an issue with this plugin, but WKWebView in general.

To fix this, you have two options: 1) From the server send the correct CORS headers for the origin in the webview (you can inspect the origin at runtime using window.location.origin to verify). Here's a CORS tutorial: https://auth0.com/blog/cors-tutorial-a-guide-to-cross-origin-resource-sharing/

2) Use a native HTTP plugin like https://github.com/silkimen/cordova-plugin-advanced-http or use Capacitor and its (beta) Http community API: https://github.com/capacitor-community/http

pabloleone commented 4 years ago

Hi,

Screenshot 2020-10-15 at 10 02 27

For some reason, iOS simulator is not able to load translations. It shouldn't be a CORS issues because the file is within the app.

Any help on this?

Regards,

chiragphyllo commented 2 years ago

Is this issue fixed? I am still facing this error in ios version 12, seems to be working on all ios version > 12. Didn't the ios 12 beta 2 fix made it to the official release from Apple ?