Bug 140205

Summary: WKWebView does not provide a way to set cookie accept policy
Product: WebKit Reporter: Eugene But <eugenebut>
Component: WebKit2Assignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: ajuma, anuja.sharma, ap, beidson, bfulgham, cpugh, dieter, elitree, eryen, jgsp, lordsteph84, loreboa84, m.goleb+bugzilla, mitz, mjs, mkwst, niklasmerz, stefan, stuartmorgan, tim.brust, wilander
Priority: P2 Keywords: InRadar
Version: 528+ (Nightly build)   
Hardware: iPhone / iPad   
OS: All   
See Also: https://bugs.webkit.org/show_bug.cgi?id=140191
https://bugs.chromium.org/p/chromium/issues/detail?id=760780

Description Eugene But 2015-01-07 14:05:45 PST
Summary:
With UIWebView, it’s possible to set the the cookie accept policy using -[NSHTTPCookieStorage setCookieAcceptPolicy:]. WKWebView does not appear to interoperate with NSHTTPCookieStorage. This makes it impossible to let users decide if they want to accept cookies or not.

Steps to Reproduce:
N/A, but for example:
- Create a trivial WKWebView app
- set [[NSHTTPCookieStorage sharedCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyNever]
- Browse around and see that cookies are still accepted

Expected Results:
Either NSHTTPCookieStorage working as expected (as it did with UIWebView), or WK* APIs for setting the cookie accept policy


Exposing -[WKProcessPool _setCookieAcceptPolicy:] as a public API will be perfect solution:
https://bugs.webkit.org/show_bug.cgi?id=130251
Comment 1 Eugene But 2015-01-07 16:06:28 PST
Radar ID: 19145620
Comment 2 Stuart Morgan 2015-06-15 15:18:17 PDT
This is now rdar://21391448 per devrel request.
Comment 3 Brady Eidson 2016-06-17 22:19:07 PDT
Have a patch that does this, but I'm not quite done with it, as I should make it handle the request in https://bugs.webkit.org/show_bug.cgi?id=140205 as well.
Comment 4 Brady Eidson 2016-06-17 22:19:49 PDT
(In reply to comment #3)
> Have a patch that does this, but I'm not quite done with it, as I should
> make it handle the request in https://bugs.webkit.org/show_bug.cgi?id=140205
> as well.

That comment was meant for Have a patch that does this, but I'm not quite done with it, as I should make it handle the request in https://bugs.webkit.org/show_bug.cgi?id=140191
Comment 5 Brady Eidson 2016-06-17 22:20:02 PDT
And that comment was not meant to have another copy of the comment in it.
Comment 6 Mike West 2018-09-20 14:28:29 PDT
CCing some folks.

Chrome on iOS has migrated to WKWebView, and in doing so has lost the ability to let users block third-party cookies. It would be lovely if WKWebView could provide us with that mechanism, perhaps in the way Eugene suggested in the initial comment.

Would y'all mind helping us get this request triaged?

Thanks!
Comment 7 Stefan Arentz 2018-09-20 15:48:58 PDT
Speaking for Firefox, we second this request.
Comment 8 Maciej Stachowiak 2018-09-24 14:27:18 PDT
Apple's WebKit team is discussing whether we can prioritize this higher.
Comment 9 David Kilzer (:ddkilzer) 2018-10-01 16:18:55 PDT
<rdar://problem/21391448>
Comment 10 anuja.sharma 2018-10-23 06:59:20 PDT
Hi Apple Team,

Our users are not able to access any third party applications in chrome on iOS because of default behavior for third party cookies got changed.
I would like to know when this issue will get resolved and since when the default behavior of third party cookies becomes blocked on iOS?
Comment 11 Eric Yen 2018-10-23 17:40:21 PDT
Hi team,
As mentioned by in c#10, could you share with us when did the Webkit start to block third party cookies as default behavior? 
Thanks.
Comment 12 John Wilander 2018-10-23 17:50:06 PDT
(In reply to Eric Yen from comment #11)
> Hi team,
> As mentioned by in c#10, could you share with us when did the Webkit start
> to block third party cookies as default behavior? 
> Thanks.

The default policy in WebKit on Cocoa platforms has been to block cookies from third-parties without pre-existing cookies since 2003. I’m not aware of any other default setting in WebViews.
Comment 13 Niklas Merz 2018-11-19 08:49:03 PST
For hybrid apps which rely solely on a webview (Cordova etc.) this can be a huge problem, because every request made to remote servers is a cross-origin request by design.

The default policy basically blocks those kind of apps from using cookie-based authentication at all.
Comment 14 John Wilander 2018-11-19 09:02:51 PST
(In reply to Niklas Merz from comment #13)
> For hybrid apps which rely solely on a webview (Cordova etc.) this can be a
> huge problem, because every request made to remote servers is a cross-origin
> request by design.

I what way are they cross-origin by design? What is the top frame origin? Do these requests differ from regular cross-origin ones? Who made the decision to make all these requests cross-origin by design? Thanks!

> The default policy basically blocks those kind of apps from using
> cookie-based authentication at all.
Comment 15 Niklas Merz 2018-11-19 09:45:08 PST
(In reply to John Wilander from comment #14)
> (In reply to Niklas Merz from comment #13)
> > For hybrid apps which rely solely on a webview (Cordova etc.) this can be a
> > huge problem, because every request made to remote servers is a cross-origin
> > request by design.
> 
> I what way are they cross-origin by design? What is the top frame origin? Do
> these requests differ from regular cross-origin ones?

I am starting to use the WKWebview plugin for Cordova made by the Ionic. 
(https://github.com/ionic-team/cordova-plugin-ionic-webview)

Because CORS does not work from files served via the file:// protocol this plugin is using a local webserver. These the requests are from the origin http://localhost:8080. Calling any origin within the Cordova app is now a cross-origin request. Because of this, authentication with cookies is not possible. Cookies just get ignored.

> Who made the decision
> to make all these requests cross-origin by design? Thanks!

The authors of the plugin made the decission because the file:// protocol is not usable in Cordova like it used to be with UIWebView. Ionic and others tried many different approaches and the local webserver was the best solution. WebKit serves local files with the origin header of "null" which does not allow any CORS requests.

Thanks for the quick response!
Comment 16 Niklas Merz 2018-11-20 00:39:07 PST
Aside from hybrid apps (Cordova etc.) this is a serious problem for pages with CORS requests and cookie authetication, if they are loaded in a webview or Browsers like Firefox or Chrome.

The default policy does not allow cookies for cross origin requests, too. Because of that we need a public API to change the policy.

Steps to reproduce the cross origin cookie behavior:
- Create a trivial WKWebView app
- WkWebView opens page on domain A
- Page on domain A sends request to domain B
- Domain A recieves cookie from Domain B via "Set-Cookie" header.
- Cookie does not show up in developer tools or "document.cookie"
- Domain A sends second request to domain B which requires cookie
- Domain B returns unauthorized response because request header contains no cookies

The default policy is great for blocking unwanted tracking cookies but breaks apps or webpages which need to send request to user-configured origins for authentication.
Comment 17 Lorenzo Boaro 2018-12-13 08:35:26 PST
Hi all! Any workaround so far?

Thanks,
Lorenzo
Comment 18 Lorenzo Boaro 2018-12-13 08:37:22 PST
(In reply to Niklas Merz from comment #16)
> Aside from hybrid apps (Cordova etc.) this is a serious problem for pages
> with CORS requests and cookie authetication, if they are loaded in a webview
> or Browsers like Firefox or Chrome.
> 
> The default policy does not allow cookies for cross origin requests, too.
> Because of that we need a public API to change the policy.
> 
> Steps to reproduce the cross origin cookie behavior:
> - Create a trivial WKWebView app
> - WkWebView opens page on domain A
> - Page on domain A sends request to domain B
> - Domain A recieves cookie from Domain B via "Set-Cookie" header.
> - Cookie does not show up in developer tools or "document.cookie"
> - Domain A sends second request to domain B which requires cookie
> - Domain B returns unauthorized response because request header contains no
> cookies
> 
> The default policy is great for blocking unwanted tracking cookies but
> breaks apps or webpages which need to send request to user-configured
> origins for authentication.

Before iOS 12 I was able to fix this following this approach:
https://medium.com/@flexaddicted/how-to-set-wkwebview-cookie-accept-policy-d8a2d3b77420

Now, I cannot do it anymore and for our goals is a big problem.
Comment 19 Tim 2019-08-13 11:24:36 PDT
Any news on this issue? It seems iOS 13 got even more aggressive than before and we are unable to set our auth cookie (using a hybrid app, too)
Comment 20 John Wilander 2019-08-13 11:29:25 PDT
Doing CORS with credentials for a page served from http://localhost[port] is a different ask than being able to change the cookie policy. It would be useful to know if a carveout for CORS from localhost pages is enough for the various reporters here.
Comment 21 John Wilander 2019-08-13 11:30:03 PDT
(In reply to Tim from comment #19)
> Any news on this issue? It seems iOS 13 got even more aggressive than before
> and we are unable to set our auth cookie (using a hybrid app, too)

Hi! Can you explain how iOS 13 got more "aggressive?" Thanks.
Comment 22 Tim 2019-08-14 01:11:43 PDT
(In reply to John Wilander from comment #20)
> Doing CORS with credentials for a page served from http://localhost[port] is
> a different ask than being able to change the cookie policy. It would be
> useful to know if a carveout for CORS from localhost pages is enough for the
> various reporters here.

No an exception for http://localhost[port] won't be enough, since e.g. with the Ionic's WebView plugin for Cordova apps one can change the protocol and host, e.g to bugs://webkit.org
Comment 23 Tim 2019-08-14 01:13:49 PDT
(In reply to John Wilander from comment #21)
> (In reply to Tim from comment #19)
> > Any news on this issue? It seems iOS 13 got even more aggressive than before
> > and we are unable to set our auth cookie (using a hybrid app, too)
> 
> Hi! Can you explain how iOS 13 got more "aggressive?" Thanks.

It seems the default cookie policy for programmatic WebViews changed? Our app works with iOS 12 but the login fails due to iOS 13. I assume the default changed from something like "allow" to "only allow first party cookies".
Comment 24 Niklas Merz 2019-08-15 01:07:18 PDT
(In reply to Tim from comment #23)
> (In reply to John Wilander from comment #21)
> > (In reply to Tim from comment #19)
> > > Any news on this issue? It seems iOS 13 got even more aggressive than before
> > > and we are unable to set our auth cookie (using a hybrid app, too)
> > 
> > Hi! Can you explain how iOS 13 got more "aggressive?" Thanks.
> 
> It seems the default cookie policy for programmatic WebViews changed? Our
> app works with iOS 12 but the login fails due to iOS 13. I assume the
> default changed from something like "allow" to "only allow first party
> cookies".

It looks like that. Our app is doing a request which contains cookies in the response. On iOS 12 these cookies are used for the redirect and following requests. On iOS 13 none of the following requests contain any cookies.

The app is running on the custom origin "ionic://localhost" and calling a server which allows this origin.
Comment 25 Tim 2019-08-15 04:47:16 PDT
(In reply to Niklas Merz from comment #24)
> (In reply to Tim from comment #23)
> > (In reply to John Wilander from comment #21)
> > > (In reply to Tim from comment #19)
> > > > Any news on this issue? It seems iOS 13 got even more aggressive than before
> > > > and we are unable to set our auth cookie (using a hybrid app, too)
> > > 
> > > Hi! Can you explain how iOS 13 got more "aggressive?" Thanks.
> > 
> > It seems the default cookie policy for programmatic WebViews changed? Our
> > app works with iOS 12 but the login fails due to iOS 13. I assume the
> > default changed from something like "allow" to "only allow first party
> > cookies".
> 
> It looks like that. Our app is doing a request which contains cookies in the
> response. On iOS 12 these cookies are used for the redirect and following
> requests. On iOS 13 none of the following requests contain any cookies.
> 
> The app is running on the custom origin "ionic://localhost" and calling a
> server which allows this origin.

As a workaround (or hack?) when using the cordova-plugin-ionic-webview: Set the "Hostname" preference to the domain of your backend. E.g. if your backend is hosted at https://mycool.backend.com set the Hostname to "mycool.backend.com" - this tricks the Cookie policy to accept the Set-Cookie header since you are a first party domain now... (it seems the protocol does not matter as long as the domain is the same). Quite creative but it works for us.
Comment 26 Niklas Merz 2019-08-15 04:58:40 PDT
> As a workaround (or hack?) when using the cordova-plugin-ionic-webview: Set
> the "Hostname" preference to the domain of your backend. E.g. if your
> backend is hosted at https://mycool.backend.com set the Hostname to
> "mycool.backend.com" - this tricks the Cookie policy to accept the
> Set-Cookie header since you are a first party domain now... (it seems the
> protocol does not matter as long as the domain is the same). Quite creative
> but it works for us.

Thanks for the workaround. Unfortunately this won't work for us. The app can be  connected to different servers. We absolutely need to do CORS-requests from "ionic://localhost".

What does Webkit do differently in iOS 13 than in iOS12? I built a minimal app that works on iOS 12 and does not work on iOS 13.
Comment 27 Niklas Merz 2019-08-15 05:13:21 PDT
Safari on iOS 13 does this for CORS-requests, too. Disabling Cross-Site-Tracking in System settings does not help either.

My fetch request on page from domain A to API on domain B gets a new cookie via the "Set-Cookie" header. The second request does not contain this cookie.

It works, if this happens on the same origin, but there should be many apps and websites that need to use CORS requests with cookies.
Comment 28 Tim 2019-08-15 05:15:24 PDT
To add some more information to this: our cookies are already marked as Secure and HttpOnly with a relative short TTL (Expires in 1 week) - AFAIK the tracking protection should allow those cookies?
Comment 29 Niklas Merz 2019-08-17 02:13:34 PDT
The problem with iOS 13 changing its behaviour over iOS 12 is probably a different bug.

I created a new one: https://bugs.webkit.org/show_bug.cgi?id=200857

If you have this issue please comment there to help.
Comment 30 Stephane 2019-09-06 02:50:06 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.