Bug 200857 - REGRESSION (iOS 13): WKWebView does not include cookies/credentials in cross-origin-requests
Summary: REGRESSION (iOS 13): WKWebView does not include cookies/credentials in cross-...
Status: RESOLVED MOVED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: Safari Technology Preview
Hardware: iPhone / iPad Other
: P2 Major
Assignee: Nobody
URL:
Keywords: InRadar, Regression, WebExposed
Depends on:
Blocks:
 
Reported: 2019-08-17 02:09 PDT by Niklas Merz
Modified: 2019-11-20 08:31 PST (History)
27 users (show)

See Also:


Attachments
Test app to reproduce issue (41.29 KB, application/zip)
2019-08-19 06:12 PDT, Niklas Merz
no flags Details
Updated demo app (43.38 KB, application/zip)
2019-08-21 06:19 PDT, Niklas Merz
no flags Details
CORS Cookies sent back after authentication; using iOS 12 (OK) (2.59 KB, text/plain)
2019-09-25 00:30 PDT, Nicola Fankhauser
no flags Details
CORS No cookies sent back after authentication; using iOS 13 (NOK) (1.96 KB, text/plain)
2019-09-25 00:30 PDT, Nicola Fankhauser
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Niklas Merz 2019-08-17 02:09:51 PDT
Like discussed here: https://bugs.webkit.org/show_bug.cgi?id=140205 iOS 13 seems to have changed its cookie handling (/blocking).

HTTP requests to other origin done with JavaScript fetch and the option "credentials: 'include'" should send cookies like they did in iOS 12.

Some steps to reproduce:

1. Create an app which loads a webpage in WKWebView (I can add a sample later)
2. Open the console of the device running the app via Safari on Mac
3. Do a CORS-request with fetch: fetch("https://cors-test.appspot.com/test" {credentials: "include"})
4. Inspect the networks tab in developer tools
5. This request will work and contain a cookie (on cookies tab) with the "Set-Cookie test=test" HTTP header
6. Do the request again
7. The network request for the second request will not send the cookie

I could reproduce this with random pages opened in WKWebView and Safari on iOS 13. If you use Cordova your app will run on "ionic://localhost" and all HTTP requests to server will fail which means the app cannot login anywhere with cookies. If I call my test server the authentication fails and I can see in the network traffic with Wireshark that no cookie header is sent.

Disabling Cross-Site-Tracking in the Safari settings does not have an effect on iOS 13 for Safari or WKWebView. I think it did on iOS 12 for Safari in this case. Like https://bugs.webkit.org/show_bug.cgi?id=140205 said there is no API to set cookie policies on WKWebView.

Apps depending on session authentication with cookies need a fix or workaround for this to work on iOS 13. Especially Cordova Apps are in big trouble since the cannot communicate with any server at all.

Details will follow. Contact me for any questions.
Comment 1 John Wilander 2019-08-17 05:38:30 PDT
Cc’ing Youenn since this seems to be specific to Fetch.
Comment 2 Niklas Merz 2019-08-17 05:46:06 PDT
I should test XMLHttpRequest, too. I will report back!
Comment 3 Radar WebKit Bug Importer 2019-08-18 11:14:44 PDT
<rdar://problem/54445945>
Comment 4 Niklas Merz 2019-08-19 06:10:32 PDT
(In reply to Niklas Merz from comment #2)
> I should test XMLHttpRequest, too. I will report back!

fetch and XMLHttpRequest have this problem on iOS 13 beta.

> Details will follow. Contact me for any questions.

I created a small app which loads my testpage on Github (https://niklas.merz.dev/corstest) in WKWebView. The test app is attached to this bug report.

This page works with cookies in Safari and WKWebView on iOS 12. On iOS 13 beta in Safari and WKWebView the cookie is not sent after recieving it for the first time.

Steps to test:

Safari:
1. Open https://niklas.merz.dev/corstest in Safari on iOS/iPadOS 13
2. Open the console of this device via Mac Safari
3. Switch to the network tab
4. Click one of the buttons
5. Inspect the request -> No cookie should be sent, one cookie should be recieved, visibile on the cookies tab and the Set-Cookie header
6. Click the button again
7. On iOS 12 the cookie will be sent (Cookie header), on iOS 13 NOT!

NativeWebView - Testapp from attachments
1. Launche the app via Xcode on iOs 13 device
2. Inspect the webpage via Mac Safari
3. Just like iOS Safari the cookie will not be sent on iOS 13
Comment 5 Niklas Merz 2019-08-19 06:12:57 PDT
Created attachment 376682 [details]
Test app to reproduce issue

I can reproduce this issue in WKWebView with this minimal test app. The test page on https://niklas.merz.dev/corstest is also included.

This page does a cross origin request to https://cors-test.appspot.com/test which returns a cookie called test. This API echos the origin so this is a valid cors request.
Comment 6 Niklas Merz 2019-08-19 07:05:19 PDT
Another finding from testing this on Safari for Mac and the Safari cross-site-tracking

I used the testpage in Safari 12.1.2 and Safari 13 (Technology Preview). Both browser version don't send the cookie if the preference cross-site-tracking is enabled.

If cross site tracking is disabled the cookie works in Safari 12 and 13 on macOS.

In iOS 12 Safari the cross-site-tracking also blocks the cookie on the test page if enabled. I think this is ok and expected behavior. The cookie works if it is disabled.

Disabling cross-site-tracking on iOS 13 does not work. Cookies are blocked in Safari anyways.
Comment 7 youenn fablet 2019-08-19 12:07:09 PDT
> Disabling cross-site-tracking on iOS 13 does not work. Cookies are blocked
> in Safari anyways.

AIUI, the bug seems to be that cross-site tracking stays enabled even though it was disabled from Safari preferences.
Is that right? Is there anything specific related to WKWebView?
Comment 8 John Wilander 2019-08-19 12:18:23 PDT
(In reply to youenn fablet from comment #7)
> > Disabling cross-site-tracking on iOS 13 does not work. Cookies are blocked
> > in Safari anyways.
> 
> AIUI, the bug seems to be that cross-site tracking stays enabled even though
> it was disabled from Safari preferences.
> Is that right? Is there anything specific related to WKWebView?

I believe, ITP is a red herring here, Youenn. It has never been on outside Safari as far as I know. My hunch is that something in the rules around Fetch credentials has changed for the protocol or host they’re using, i.e. non-http(s) scheme and/or a host without TLD such as localhost.
Comment 9 Niklas Merz 2019-08-19 12:20:13 PDT
(In reply to youenn fablet from comment #7)
> > Disabling cross-site-tracking on iOS 13 does not work. Cookies are blocked
> > in Safari anyways.
> 
> AIUI, the bug seems to be that cross-site tracking stays enabled even though
> it was disabled from Safari preferences.

I was comparing WKWebView to Safari and iOS 12 to iOS 13. Safari seems to have the same bug as WKWebView that now cookies are always ignored.

> Is that right? Is there anything specific related to WKWebView?

The bug is about WKWebview dropping cookies from request on iOS 13 with no option to enable it. 

I am in trouble because our whole app runs in WKWebView and relies on cookies for authentication. WKWebView now does not handle cookies correctly, on contrast to iOS 12 where it did.
Comment 10 Niklas Merz 2019-08-19 12:57:23 PDT
(In reply to John Wilander from comment #8)
> (In reply to youenn fablet from comment #7)
> I believe, ITP is a red herring here, Youenn. It has never been on outside
> Safari as far as I know. 

You are probably right. Since iOS 13 Safari is not working as expected regardless of the ITP setting.

> My hunch is that something in the rules around
> Fetch credentials has changed for the protocol or host they’re using, i.e.
> non-http(s) scheme and/or a host without TLD such as localhost.

I can add that XMLHttpRequest is doing the same. I tested it on various origins like custom protocol localhost, IP and normal subdomains with HTTPS. As far as I know it happens regardless of the origin.

Did anyone try me test, yet? Would be good to know its not my fault and somebody else has the same issue.
Comment 11 Niklas Merz 2019-08-19 13:41:51 PDT
(In reply to Niklas Merz from comment #10)
To many typos here. Sorry for that. Let's try again:

> Did anyone try me test, yet? Would be good to know its not my fault and
> somebody else has the same issue.

Did anyone try my test page and project, yet? Would be good to know if it's not my fault and somebody else has the same issue.


(In reply to  youenn fablet from comment #7)
> AIUI, the bug seems to be that cross-site tracking stays enabled even though it was disabled from Safari preferences.
>Is that right? Is there anything specific related to WKWebView?

My comparison with Safari may let to confusion. Safari on iOS 13 is another topic. 
This report is only about the issue that cookies are not handled in WKWebView on iOS 13 beta. This looks like a regression.


(In reply to  John Wilander from comment #8)
>My hunch is that something in the rules around Fetch credentials has changed

This sounds very likely. I will start looking at the Webkit sources for changes, but navigating the codebase is hard from the outside.
Comment 12 Niklas Merz 2019-08-21 06:19:44 PDT
Created attachment 376870 [details]
Updated demo app

I've got new information from futher testing with my example. Please consider this while reproducing and fixing this bug.

The "cookies are not handled on first launch" bug still exists. This means you have to put the app in background and open it again before testing this after installing it via Xcode to get cookies working on iOS 12. This is a known bug on the Cordova community (https://github.com/imransilvake/Cordova-Plugin-Sync-Cookies https://github.com/Telerik-Verified-Plugins/WKWebView/issues/247 etc.), but I cannot find a Webkit bug. Is this worth a new one?

While testing a new device, I found that you have to set the cookie accept policy on the shared HTTPCookieStorage to make cookies work on iOS 12 aswell.
According to the docs this should be default: https://developer.apple.com/documentation/foundation/httpcookie/acceptpolicy/always . Is this a new bug?

I updated the project in the attachment accordingly. I need to set it once like this to get cookies working on iOS 12: 

```
let cookieStorage = HTTPCookieStorage.shared
cookieStorage.cookieAcceptPolicy = HTTPCookie.AcceptPolicy.always
```

iOS 13 is unaffected from these "workarounds" and does not send cookies at all. Is there another cookie setting that could have changed the default?
Comment 13 Benjamin Tietze 2019-08-21 23:53:57 PDT
Could the problem already be reproduced and will it be fixed in version 13?
If not, our customers can not update to version 13, as our software would no longer be able to run.
Comment 14 Dmitry Perlroizen 2019-08-22 07:59:57 PDT
iOS 13 beta 7 breaks our application because cookies are not being returned to the server. We rely on cookies for session management. Hopefully it doesn't get released in current form because it will create massive issues for us.
Comment 15 youenn fablet 2019-08-23 03:58:12 PDT
I can repro the issue. This indeed seems like a regression.

One workaround is to load the request that triggers setting cookies as a main document.
Taking Niklas example:
1. load https://cors-test.appspot.com/test as main document. Cookies will be set.
2. load https://niklas.merz.dev/corstest
3. Do a cross-origin XHR/fetch, cookies should be included in the requests but response cookies will be discarded.

Not sure how practical this workaround is though.
Comment 16 Niklas Merz 2019-08-23 06:31:15 PDT
(In reply to youenn fablet from comment #15)
> I can repro the issue. This indeed seems like a regression.

Thank you very much for testing this. I'm really glad that this issue is confirmed.
 
> One workaround is to load the request that triggers setting cookies as a
> main document.
> Taking Niklas example:
> 1. load https://cors-test.appspot.com/test as main document. Cookies will be
> set.
> 2. load https://niklas.merz.dev/corstest
> 3. Do a cross-origin XHR/fetch, cookies should be included in the requests
> but response cookies will be discarded.
> 
> Not sure how practical this workaround is though.

This works indeed in the test app. For our app this is not practical. We trying  a couple of workarounds but a timely fix for this bug would be ideal.
Comment 17 Stephane 2019-09-06 02:50:42 PDT
I had the same problem with my ionic 3 app and ios 13.
I found workarounds using :

https://github.com/sneas/ionic-native-http-connection-backend

https://ionicframework.com/docs/native/http/#installation

By replacing the API calls from rxjs with the native objective C http call, the cookie persist well from the http response of the backend.
Comment 18 Niklas Merz 2019-09-06 03:04:14 PDT
(In reply to lordsteph84 from comment #17)
> I had the same problem with my ionic 3 app and ios 13.
> I found workarounds using :
> 
> https://github.com/sneas/ionic-native-http-connection-backend
> 
> https://ionicframework.com/docs/native/http/#installation
> 
> By replacing the API calls from rxjs with the native objective C http call,
> the cookie persist well from the http response of the backend.

Thank you for pointing that out for Cordova/Ionic developers.

Regardless this is still a workaround and doing HTTP in the browser should work as expected. I would be happy to remove any workarounds, when this issues gets fixed.
Comment 19 Alexey Proskuryakov 2019-09-09 15:57:23 PDT
Could you please elaborate on end user impact of this problem? What are the popular apps that have important functionality broken because of this regression?

Please feel free to e-mail me directly if you would prefer not to mention those publicly.
Comment 20 Dmitry Perlroizen 2019-09-10 00:08:51 PDT
(In reply to Alexey Proskuryakov from comment #19)
> Could you please elaborate on end user impact of this problem? What are the
> popular apps that have important functionality broken because of this
> regression?

Whatsapp, Twitter, FaceBook, Goldman Sacks App..?

What difference doesn't it make the popularity or importance of the app?
It breaks our mobile app because we rely on session cookies. It will break any other app which does the same. If server complies with request and provides all necessary headers according to the spec the client must fulfill it's part. Or reject the response and raise the error.

The impact of not doing this is that the developer will have to replace the entire mechanism of session management on the server side or fork and fix this bug themselves.
Comment 21 Alexey Proskuryakov 2019-09-10 09:29:32 PDT
> Whatsapp, Twitter, FaceBook, Goldman Sacks App..?

Please provide steps to reproduce with these apps, or any shipping apps at all. Please be very precise, as I haven't seen related reports of broken functionality in these particular apps.

> What difference doesn't it make the popularity or importance of the app?

User impact is one of the most important factors for prioritization. The question is not whether this issue needs to be investigated and fixed, but whether users are so severely impacted that this issue needs to be prioritized. Typically, broken functionality in popular apps is the easiest way to demonstrate the impact. Breaking  many non-top apps is also not OK, but please realize that we know of exactly zero specific impacted apps at the moment.

It is doubly important to clearly state the user impact because even after a bug like this is fixed, all companies that use WebKit will need to decide whether to expedite shipping the fix to customers as part of their products.
Comment 22 Yordan Bonev 2019-09-11 03:28:57 PDT
We have exactly same issue with our app and cookie authentication. Not working only on iOS 13
Comment 23 Niklas Merz 2019-09-19 00:54:00 PDT
(In reply to dima from comment #20)
> What difference doesn't it make the popularity or importance of the app?
> It breaks our mobile app because we rely on session cookies. It will break
> any other app which does the same. If server complies with request and
> provides all necessary headers according to the spec the client must fulfill
> it's part. Or reject the response and raise the error.
> 
> The impact of not doing this is that the developer will have to replace the
> entire mechanism of session management on the server side or fork and fix
> this bug themselves.

I somehow agree with this statement. This is clearly a regression because iOS 12 has the correct behavior. Regardless of affects on popular apps this does not follow standard browser spec and potentially breaks many apps and more importantly websites that are embedded. Web site developers / app developers / hybrid app developers should be confident that browsers / webviews work similiar on different platforms and across versions. Additionally there seems to be no reason this change is introduced in iOS 13 and it seems to be by accident.

(In reply to Alexey Proskuryakov from comment #21)
> It is doubly important to clearly state the user impact because even after a
> bug like this is fixed, all companies that use WebKit will need to decide
> whether to expedite shipping the fix to customers as part of their products.

As cookies are often used for authentication the impact for many apps could be that they cannot communicate with the server anymore. For our app that means it gets stuck at launch because it authenticates and relies on cookies for further requests.

> Please provide steps to reproduce with these apps, or any shipping apps at
> all. Please be very precise, as I haven't seen related reports of broken
> functionality in these particular apps.

I sent an e-mail with details about the app I am talking about.I suggest everybody who experiences this issue doing the same to make the user impact clear.
Comment 24 Mike Senn 2019-09-20 12:32:08 PDT
This issue is affecting the Salesforce iOS app, which has over 1 million monthly users. The issue is affecting every user that has upgraded to iOS 13, because the Salesforce app uses cross-origin requests to control security of trusted-user-generated content. Those domains can no longer authenticate.

Salesforce is tracking this issue internally with W-6521658.
Comment 25 fortinmike 2019-09-23 11:28:47 PDT
This issue also breaks our hybrid apps here at Simbioz. Cookie-based login worked perfectly prior to the release of iOS 13. For the record, our app runs inside Cordova with the WKWebView plugin and logs in to a server that's on a different domain (the app itself runs on file://).
Comment 26 Nicola Fankhauser 2019-09-24 07:29:54 PDT
This regression breaks our Cordova hybrid app relying on cookies for session handling with a backend system via CORS.
Comment 27 Nicola Fankhauser 2019-09-25 00:30:04 PDT
Created attachment 379529 [details]
CORS Cookies sent back after authentication; using iOS 12 (OK)
Comment 28 Nicola Fankhauser 2019-09-25 00:30:34 PDT
Created attachment 379530 [details]
CORS No cookies sent back after authentication; using iOS 13 (NOK)
Comment 29 Nicola Fankhauser 2019-09-25 00:34:11 PDT
I added two text files to show the issue. Each file consists of two request/response pairs, the first authenticates via POST to a CORS server, which sends back session cookies. The second request then tries to GET data via a RESTful service, which requires these session cookies to be presented. Under iOS 13 the lack of cookies in the GET request provokes a 401 Unauthorized response.

What are the next steps here? iOS 13.1 has not fixed this.
Comment 30 Nicola Fankhauser 2019-09-25 00:39:38 PDT
(In reply to Alexey Proskuryakov from comment #21)
> Please provide steps to reproduce with these apps, or any shipping apps at
> all. Please be very precise, as I haven't seen related reports of broken
> functionality in these particular apps.

Please see the attached files for details how CORS on iOS 13 behaves vs. iOS 12.

> Breaking  many non-top apps is also not OK,
> but please realize that we know of exactly zero specific impacted apps at
> the moment.

This is our app - currently broken because of this iOS 13 bug - called "KSD IES" on Apple Store: https://apps.apple.com/us/app/ies/id1465568824
Comment 31 Dmitry Perlroizen 2019-09-25 01:19:01 PDT
I confirm identical behavior described by Nicola Fankhauser in our hybrid Cordova application using WebKit and iOS 13. The application named "Dream Spot" in Apple store is broken for iOS 13 users and we are working frantically to patch the server side so that our customers don't kill us as they upgrade to iOS 13. What we do is sending the session id as request parameter, making the server to strip that and convert it into a missing cookie and then send down the chain of http request processing.
Comment 32 Nicola Fankhauser 2019-09-25 02:09:18 PDT
To clarify we are running UIWebView (and not WKWebView) and have the issue, so this seems to apply to both WKWebView and UIWebView.
Comment 33 Nicola Fankhauser 2019-09-26 07:20:28 PDT
(In reply to Stephane from comment #17)
> I had the same problem with my ionic 3 app and ios 13.
> I found workarounds using :
> 
> https://github.com/sneas/ionic-native-http-connection-backend
> 
> https://ionicframework.com/docs/native/http/#installation
> 
> By replacing the API calls from rxjs with the native objective C http call,
> the cookie persist well from the http response of the backend.

For our vanilla Cordova app we used the following plugin, diverting all CORS calls to work around the broken WebKit XHR API:

https://github.com/silkimen/cordova-plugin-advanced-http
Comment 34 Dmitry Perlroizen 2019-09-30 10:05:33 PDT
We have found a workaround by using this plugin:
https://github.com/oracle/cordova-plugin-wkwebview-file-xhr

I don't think it's a good idea to fix bugs with plugins but that is the only solution we could find so far.
Comment 35 xaxab 2019-10-07 12:04:36 PDT
Just chiming in to say that this bug also breaks our cordova app and we've been forced to use a third party plugin (https://github.com/silkimen/cordova-plugin-advanced-http) for all our API requests as a workaround.

I'm kind of floored that this issue isn't being treated more urgently given that it undoubtedly breaks login functionality for thousands (if not tens of thousands) of hybrid apps. But I guess we just have to cross our fingers and hope this breaks something for Twitter or Facebook soon
Comment 36 John Wilander 2019-10-07 12:12:56 PDT
All, thanks for your reports. We've found the root cause of this issue (tracked in rdar://problem/54445945). It's not related to ITP or a problem in WebKit. Please test in the next iOS 13.2 beta.
Comment 37 Niklas Merz 2019-10-07 23:10:32 PDT
Thank you everyone for helping with this issue.

Just FYI I downloaded iOS 13.2 Developer Beta and it looks like this is not yet fixed in the current version. Looking forward to the next update.
Comment 38 youenn fablet 2019-10-07 23:30:26 PDT
Marking bug as Resolved.
Do not hesitate to reopen/post any related testing result.
Comment 39 Niklas Merz 2019-10-10 23:58:42 PDT
I just did a quick test with the new iOS 13.2 Developer beta 2 and this issue is fixed!
Comment 40 fábio_k 2019-10-11 09:43:36 PDT
I can also confirm that the problem is now fixed in iOS 13.2 Developer beta 2
Comment 41 tajinder.pal 2019-10-23 03:24:22 PDT
what can we do for lower ios versions for cookies support
Comment 42 fábio_k 2019-10-23 11:47:36 PDT
(In reply to tajinder.pal from comment #41)
> what can we do for lower ios versions for cookies support

https://github.com/GEDYSIntraWare/cordova-plugin-webview-switch

You can use this plugin to reload the webview(In reply to tajinder.pal from comment #41)
> what can we do for lower ios versions for cookies support

https://github.com/GEDYSIntraWare/cordova-plugin-webview-switch

WebviewSwitch.setHostname('<ip_')(In reply to tajinder.pal from comment #41)
> what can we do for lower ios versions for cookies support

https://github.com/GEDYSIntraWare/cordova-plugin-webview-switch
WebviewSwitch.setHostname('_your_server_ip')
Comment 43 Niklas Merz 2019-10-23 12:49:12 PDT
If you use Cordova and the Ionic Webview you can use some workarounds, that are not ideal.

(In reply to fábio_k from comment #42)
> https://github.com/GEDYSIntraWare/cordova-plugin-webview-switch
> WebviewSwitch.setHostname('_your_server_ip')

This makes your request not cross-origin and solves this issue. But you don't need that plugin if you can set your servers hostname at buildtime: https://github.com/ionic-team/cordova-plugin-ionic-webview#hostname

Another workaround is to make your HTTP request through native layers instead of using fetch and XHR.

Plugin for native HTTP
https://www.npmjs.com/package/cordova-plugin-advanced-http

There is an attempt for Ionic Webview to use schemehandlers for native requests, which you could try.
Comment 44 tajinder.pal 2019-10-24 02:42:49 PDT
(In reply to Niklas Merz from comment #43)
> If you use Cordova and the Ionic Webview you can use some workarounds, that
> are not ideal.
> 
> (In reply to fábio_k from comment #42)
> > https://github.com/GEDYSIntraWare/cordova-plugin-webview-switch
> > WebviewSwitch.setHostname('_your_server_ip')
> 
> This makes your request not cross-origin and solves this issue. But you
> don't need that plugin if you can set your servers hostname at buildtime:
> https://github.com/ionic-team/cordova-plugin-ionic-webview#hostname
> 
> Another workaround is to make your HTTP request through native layers
> instead of using fetch and XHR.
> 
> Plugin for native HTTP
> https://www.npmjs.com/package/cordova-plugin-advanced-http
> 
> There is an attempt for Ionic Webview to use schemehandlers for native
> requests, which you could try.

how can i set cookies headers that came from api. I need these headers for all requests. its working fine in uiwebview but not working in wkwebview for all ios os  versions and i am working on ionic-1 app
Comment 45 David M 2019-11-20 07:38:58 PST
Has anyone tested this in iOS 13.3 beta 2?  This seems to be re-broken again...
Comment 46 David M 2019-11-20 07:58:12 PST
Also in 13.3, we set the cookie via configuration.websiteDataStore.httpCookieStore so we didn't run into the original problem in 13.0-13.2 but now with that cookie set WKWebView does not send the cookie to the cross origin xhr request...
Comment 47 John Wilander 2019-11-20 08:31:24 PST
(In reply to David M from comment #45)
> Has anyone tested this in iOS 13.3 beta 2?  This seems to be re-broken
> again...

It’s a different bug: https://bugs.webkit.org/show_bug.cgi?id=204109