Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS 14 will enable Intelligent Tracking Prevention in WKWebView by default #922

Closed
3 tasks done
NiklasMerz opened this issue Jun 26, 2020 · 41 comments · Fixed by #1030
Closed
3 tasks done

iOS 14 will enable Intelligent Tracking Prevention in WKWebView by default #922

NiklasMerz opened this issue Jun 26, 2020 · 41 comments · Fixed by #1030

Comments

@NiklasMerz
Copy link
Member

NiklasMerz commented Jun 26, 2020

Bug Report

Problem

Apple just announced that iOS 14 will enable "Intelligent Tracking Prevention" (ITP) by default in WKWebView. This issue is open for discussion around that and possible ways to fix Cordova apps that break with these changes. Please leave a 👍 if you are having issues with this change.

Possible solution -> Work in progress

  • Add preference and features to allow users to disable ITP in settings
  • Proxy HTTP(s) requests through WKUrlSchemehandler to handle cookies on the native layer.
  • Get exceptions for localhost in WebKit?

Code - Workarounds

Currently the best solution in my case seems to build some kind of HTTP proxy with an WKURLSchemeHandler. I did this in the WKWebView plugin a while ago to workaround any CORS restrictions. Would this make sense to integrate into cordova-ios?

So the app runs on cordova://localhost for example and you convert every external URL like https://myserver.com/image.png to cordova://localhost/_httpproxy/myserver.com/image.png and the WKURLSchemeHandler does the server request instead with native Code instead of letting the WebView doing it.

https://github.com/GEDYSIntraWare/cordova-plugin-ionic-webview/blob/proxyios/src/ios/IONAssetHandler.m#L38-L85

GEDYSIntraWare/cordova-plugin-ionic-webview@master...GEDYSIntraWare:proxyios

Information

WKWebView session from WWDC 2020

Webkit bug report

Environment, Platform, Device

iOS 14 beta

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above
@jlsync
Copy link

jlsync commented Aug 14, 2020

It would also be very useful for these same cookies to be sent/supported on websocket connections from cordova-ios.

@CGS38
Copy link

CGS38 commented Sep 23, 2020

On iOS14, still stuck on this ITP problem...

I tried to disable ITP controls by adding
NSCrossWebsiteTrackingUsageDescription to the app’s Info.plist but no user prompt is requested at runtime. By going manually to the app authorisations it is possible in this case to deactivate this security and restore nominal operation for xhr calls with third party cookies. Not satisfactory...

Another unsuccessfully tested solution,
addition of

<plist version="1.0">
<dict>
<key>WKAppBoundDomains</key>
<array>
     <string>localhost</string>
    <string>mydomain.com</string>
</array>
</dict>

with also :
WKWebViewConfiguration with the specific argument: webViewConfiguration.limitsNavigationsToAppBoundDomains = YES;

@simoneromano96
Copy link

iOS 14 stable is rolling out, we're having issues with our mobile app that uses an OAuth flow with the InAppBrowser

@NiklasMerz
Copy link
Member Author

NiklasMerz commented Sep 28, 2020 via email

@ardabeyazoglu
Copy link

Until cordova handles this issue, a workaround is the following plugin to sync cookies. It worked in ios 14.0.1, which means server-set cookies sent in following requests.

https://github.com/CWBudde/cordova-plugin-wkwebview-inject-cookie

@stradlin84
Copy link

On iOS14, still stuck on this ITP problem...

I tried to disable ITP controls by adding
NSCrossWebsiteTrackingUsageDescription to the app’s Info.plist but no user prompt is requested at runtime. By going manually to the app authorisations it is possible in this case to deactivate this security and restore nominal operation for xhr calls with third party cookies. Not satisfactory...

Another unsuccessfully tested solution,
addition of

<plist version="1.0">
<dict>
<key>WKAppBoundDomains</key>
<array>
     <string>localhost</string>
    <string>mydomain.com</string>
</array>
</dict>

with also :
WKWebViewConfiguration with the specific argument: webViewConfiguration.limitsNavigationsToAppBoundDomains = YES;

Hi,

how is the value for NSCrossWebsiteTrackingUsageDescription key? A descriptive string or specific value?
Thanks

@toddtarsi
Copy link

Until cordova handles this issue, a workaround is the following plugin to sync cookies. It worked in ios 14.0.1, which means server-set cookies sent in following requests.

https://github.com/CWBudde/cordova-plugin-wkwebview-inject-cookie

That repo does not work for iOS 14.

@ardabeyazoglu
Copy link

@toddtarsi it worked on my project without problem. However i then found an easier way and used https://github.com/oracle/cordova-plugin-wkwebview-file-xhr instead. It worked lika a charm and apple approved the build.

@toddtarsi
Copy link

@ardabeyazoglu - I'm glad you've found a solution for your needs. I just want to make clear that the repo you referenced doesn't resolve this issue in all cases. We've used that repo to resolve cookie issues since iOS 10 I think, and it doesn't do it here.

@ardabeyazoglu
Copy link

@toddtarsi have you tried xhr plugin i mentioned ?

@toddtarsi
Copy link

@ardabeyazoglu - I have not. Thanks for the recommendation. I don't think it will work for our use case however since we have a mix of secure, httpOnly cookies as well as non-secure cookies that we read from the JS layer. It seems like that solution doesn't allow for the latter use case.

@danielsotopino
Copy link

danielsotopino commented Oct 6, 2020

@ardabeyazoglu i've used https://github.com/CWBudde/cordova-plugin-wkwebview-inject-cookie for a long time.
Now i'm checking on IOS 14 and is not working.

I'm going to check https://github.com/oracle/cordova-plugin-wkwebview-file-xhr if it helps.

EDIT: Installed https://github.com/oracle/cordova-plugin-wkwebview-file-xhr and started working again.

@toddtarsi
Copy link

@ardabeyazoglu - I've started using the file xhr plugin, and it helps a lot. Thanks for the recommendation! Unfortunately, I'm still seeing authentication fail on websocket connect requests, but I'll try and figure out what I can do about that.

@ardabeyazoglu
Copy link

@toddtarsi since websocket does not use fetch/xmlhttprequest, it has probably no use for that. There are 2 possible workarounds i think:

  1. Override websocket like others natively, and create a shim in client layer, although i dont think it is trivial.
  2. After first login/auth, pass the session id to the client in addition to cookie, just to set it as websocket param/header.

@NiklasMerz
Copy link
Member Author

It could help if everyone here could comment here https://bugs.webkit.org/show_bug.cgi?id=213510 how they use Cordova and how ITP affects their apps. If Apple gets a better view about the apps out there and how they use the Webview, there is a small chance we can make Cordova better some day.

@tajindersinghnamdhari
Copy link

Thanks to all for discussing the issue and also sharing your findings on the go.
Was looking for a fix to 403 error for content fetch from server after a login via REST API.
Our app involved downloading a file using cordova-plugin-file-transfer plugin, it started failing on iOS 14.
So, commenting here in case anyone else is searching.
Using cordova-plugin-wkwebview-file-xhr along cordova-plugin-wkwebview-inject-cookie helped and downloads working again.
Thanks again! 👍

@toddtarsi
Copy link

toddtarsi commented Oct 7, 2020

@tajindersinghnamdhari - These work very well if you're using the XHR / fetch APIs. The way cordova-plugin-wkwebview-file-xhr works is by directly polyfilling the XMLHttpRequest, FormData, and fetch APIs. If you're using any other networking components (in my case window.WebSocket), this will not resolve all issues.

@manelds
Copy link

manelds commented Oct 9, 2020

I have the same problem. The app have the plugin "cordova-plugin-wkwebview-inject-cookie" and no save the cookies, but only on iOS 14. In my case, I compiled with an old Xcode versión (v11.3.1 - 11c504) and cookies works again (temporal solution).

@lovetoast
Copy link

Hi Everyone,

I have had the same issue, and used the file-xhr plugin to resolve this. Not sure if there is another solution to this?

@wlp2s0
Copy link

wlp2s0 commented Nov 19, 2020

Hello @NiklasMerz , I've got an hybrid app with cookie based authentication in production on the app store.
It looks like the app is working even on ios 14.x but not if I use an ios 14.x emulator / physical developer device.
I think that the app has been released before the 14.x stable OS release so it is currently unaffected by the ITP update but will be once I'll update the app.
I'm currently switching to a stateless authentication but I've got other issues because we're also relying on third party services (like a payment service) that uses cookies too.
I enabled the cross website tracking option and everything works so I'm sure that the issue is ITP. What do you think about?

@NiklasMerz NiklasMerz linked a pull request Nov 25, 2020 that will close this issue
8 tasks
@tudordumitriu
Copy link

Hi guys
We are in the same situation.
We are using cookie based authentication (multiple subdomains actually), and since updating to latest iOS version 14.2, and upgrading the build machine to Big Sur and XCode 12 the login stopped working (cordova ios 6.1.1 and cordova 10).
After few days of trying all sorts of things (including the above mentioned plugins - which we are actually using for years) they only thing that worked was adding the NSCrossWebsiteTrackingUsageDescription key and then after installing the app going in Settings and enabling 'Allow Cross-Website Tracking'.
Adding WKAppBoundDomains empty or with our apis just stops the app from loading (it remains in splashscreen - no errors in logs)
So, as far as I can say @NiklasMerz all hopes on your PR and we should expect this to be fixed in like 6.1.2?
Has anyone else managed to fix it by using WKAppBoundDomains?

@NiklasMerz
Copy link
Member Author

As far as my PR goes I think this could go into a minor release like 6.2.0. But we would need to wait for more reviews and feedback. As an interim solution you could use a fork of the iOS platform until this get's merged and test it if you know what you are doing.

As far as WKAppBoundDomains goes I think it would be good if we get more information on how to get this implemented properly. This is not a solution for my personal use-case but it would be great if we can offer this for most apps where this is the right way to do it.

If anyone has experience with WKAppBoundDomains please share.

@tudordumitriu
Copy link

@NiklasMerz thanks for all the effort!
Yea, indeed a minor fix and hopefully asap, yes, forking is an option ofc, we've forked quite a few plugins, but at some point or you PR your stuff or get back to the main branch because otherwise it just a mess. But agree, temporarily should be ok.
Other than forking it and getting your PR do we need to do anything else when running it?
Thanks again mate!

@NiklasMerz
Copy link
Member Author

@tudordumitriu That's exactly how I work as well. When I fix changes I contribute them as PRs and run of forks until they get released. You need to clean up occassionally and push PRs forward of course.

To get this feature running you need to use the branch/fork of my PR and add the webview proxy plugin linked there. You then rewrite the url with the plugins JS helper functions and now your requests go through the proxy and your cookie issues are hopefully gone. If you need more help please contact me or better comment on the PR or the plugins issues/discussions to.

@tudordumitriu
Copy link

Thanks, since we're not under live pressure (the live version still working - so I suspect the XCode 12 changed the game) we'll wait for a while to see how that goes, if it takes more than couple of weeks will use your fork.
Much appreciated!

@newuser44
Copy link

Same here -
Trying to update to WKWebKit. After some backend server changes to handle cors, cookies had some problems.
Fixed that with this plugin
lucky3491/cordova-plugin-wkwebview-inject-cookie#1 (comment)

Hadn't been using ios 14 so apple caught the problem when trying to get them approved.
Might still have the cookie problem -- (after login cookies are not set for next request to use).
So what has people had the best success with?

Option 1 - I will be try this plugin
https://github.com/oracle/cordova-plugin-wkwebview-file-xhr

A little confused on how to use this for my case.
Can I use this only for my login request and login cookies would be set? Then any angular http/webkit request would start to work?
Login for android wouldn't be effective?

Option 2 - Is there another option, anything else that has worked?

@NiklasMerz
Copy link
Member Author

@newuser44 Sorry your comment is more a question and therefore off-topic. Please go to our slack to get support from other uses. http://slack.cordova.io

@tudordumitriu
Copy link

Hi @NiklasMerz
I've seen you have closed this issues due to working on the other related issues.
Since we're getting some pressure to get it working I have tried integrating your proposed solution (using cordova ios platform strait from github and using the proxy plugin and converting the urls) but it doesn't seem to be working.
We might have a specific case because we are using PouchDB which manages in it's own way the HTTP communication but we have even tried hacking the libraries just to see if is working.
Now I know this might not be the most appropriate place to discuss this, but eventually could you give us a status update and eventually a link with all the steps that need to be done to go this route. I don't even know if I'm using the right code (in XCode I see in webproxy that is looking for prefix @'https_proxy' but all may urls once calling the WebViewProxy.converProxyUrl start with app://_)
An just as a matter of personal curiosity, the proxy (and I think that's the whole purpose) once we call the _session that will return the set-cookie header will remember for the rest of the calls the cookie, right?
Sorry, but things are not that clear and I don't see Apple doing anything yet to allow disabling the Intelligent Tracking

@adamdport
Copy link

FWIW I managed to get my Cordova app to use authentication cookies set by the response of an XHR request to my remote without needing any plugins or hacks. There are some gotchas though and wanted to try to outline them here:

  • Add CORS headers to your remote that allow the origin defined by your scheme and hostname in config.xml (eg. foo://mydomain.com), allow CORS headers, and make sure you're returning 200 for OPTIONS requests even though they won't have authentication cookies
  • Set withCredentials: true on your XHR requests
  • Add your remote to WKAppBoundDomains in your app's plist file
  • Opt into limitsNavigationsToAppBoundDomains = YES in CDVWebViewEngine.m

The last two aren't ideal, and I've created a feature request for cordova-ios to handle AppBoundDomains out of the box. If you're up against a deadline however, it's not too painful to add it yourself

@markovchainmontecarlo
Copy link

@adamdport Are the cookies only from mydomain.com in your setup or are you trying to access cross site cookies with that approach?

@adamdport
Copy link

@jeremyspatrick in my case, I'm making a login request to mydomain.com, the response of that request sets a cookie, and every subsequent request to mydomain.com includes that cookie until I log out. I don't have any other domains in my setup, but I could try to do some more testing in a few days if you have something specific you want me to test

@Aston13
Copy link

Aston13 commented Mar 8, 2021

FWIW I managed to get my Cordova app to use authentication cookies set by the response of an XHR request to my remote without needing any plugins or hacks. There are some gotchas though and wanted to try to outline them here:

  • Add CORS headers to your remote that allow the origin defined by your scheme and hostname in config.xml (eg. foo://mydomain.com), allow CORS headers, and make sure you're returning 200 for OPTIONS requests even though they won't have authentication cookies
  • Set withCredentials: true on your XHR requests
  • Add your remote to WKAppBoundDomains in your app's plist file
  • Opt into limitsNavigationsToAppBoundDomains = YES in CDVWebViewEngine.m

The last two aren't ideal, and I've created a feature request for cordova-ios to handle AppBoundDomains out of the box. If you're up against a deadline however, it's not too painful to add it yourself

I have just taken over development of an app this week (with little app experience) as the previous developer left. Since he left, iOS login authentication fails - I believe this stems from when the previous dev updated XCode from 11 -> 12 two weeks ago. I have been following the posts here and on webkit for the past few days and still haven't found a solution, not even with the AppBoundDomains.

Login works fine on browser and Android. Only on iOS devices and on the simulator/emulator it fails due to cookies. The only successful login I have managed to achieve on iOS is by adding this to the config.xml:

<preference name="scheme" value="https" />
<preference name="hostname" value="domain.com" />

However, this only works for a single domain, and I need to support multiple.

feelsbadman.jpg

@breautek
Copy link
Contributor

breautek commented Mar 8, 2021

This doesn't do what you probably think this does. https is a reserved protocol. If a scheme protocol is not usable, cordova will default to app.

@Aston13
Copy link

Aston13 commented Mar 8, 2021

This doesn't do what you probably think this does. https is a reserved protocol. If a scheme protocol is not usable, cordova will default to app.

Yes correct, that line didn't affect anything - just the hostname. I guess I'm just clutching at straws at this point lol

@NiklasMerz
Copy link
Member Author

You are right the Xcode update changed the behavior. You need to figure out a way to work around this or better get rid of cookies for authentication.

This was my journey. Maybe you get something out of it. https://blog.merzlabs.com/posts/webview-history/

@Aston13
Copy link

Aston13 commented Mar 8, 2021

Thanks, it is nice to have some confirmation that it was indeed the Xcode update, it has been an interesting takeover of the app so far. I think we will have to go without cookies as you say - I will checkout your blog also.

I wonder if it is possible to build in an old Xcode version to get one final version released for now

@victorvhpg
Copy link

please fix these bugs.
ios 14 cordova ios 6+ dont store/send cookies
we use aws load balance that only use cookies for "sticky session feature"
we need cookies to bind a user's session to a specific instance (aws load balance) "sticky session feature"

@markovchainmontecarlo
Copy link

Cordova cannot fix these bugs. Apple (and eventually google) is deliberately blocking all third party cookies.

The options are

  1. Third parties need to avoid cookies and use a header to pass a session key
  2. Route all traffic through a proxy that you own and use the origin preference in cordova's config.xml
  3. Use the NSCrossWebsiteTrackingUsageDescription and have your users navigate to settings manually to enable
  4. Pop out third parties into the safari web view controller (there's a cordova plugin to do this)
  5. Build with xcode 11.7 (soon to be phased out)

@ardabeyazoglu
Copy link

ardabeyazoglu commented Apr 13, 2021

@jeremyspatrick @victorvhpg
6. Use another http request plugin, either cordova-plugin-wkwebview-file-xhr *** or cordova-plugin-advanced-http.

I have been using the first one for a year without any problem, for multiple domains. xmlhttprequest and fetch api both work, except that you can't get cookie from native layer, it must be a httpOnly cookie, -which must be- when used for authentication to be more secure.

I don't understand why this problem is still so annoying except few specific use cases such as websocket, as @toddtarsi mentioned. Even websocket issue can be solved by a few changes in the app, giving cookie back in body instead of header after authentication, and send it manually in websocket handshake.

@markovchainmontecarlo
Copy link

When i realized i couldn't get the cookie back into the wkview i didn't consider that a viable option. Yes you can route all traffic through a native layer but that doesn't help much for users that are relying on iframes. unless there's a way to sync cookies this way. not sure.

unrelated to ios i just noticed #2 doesn't appear to work for android. I cannot set the origin by modifying config.xml. the origin is always file://

@t-knapp
Copy link

t-knapp commented May 14, 2024

I face a similar problem with cookies on iOS (cordova-ios v7.1.0).

Here is my config.xml

<platform name="ios">
        <preference name="scheme" value="app" />
        <preference name="hostname" value="localhost" />
        [...]
        <config-file target="*-Info.plist" parent="WKAppBoundDomains">
            <array>
                <string>localhost</string>
                <string>api.myapp.cloud</string>
                <string>db.myapp.cloud</string>
            </array>
        </config-file>
        <preference name="LimitsNavigationsToAppBoundDomains" value="true" />
       [...]

There is no SSO or InApp Browser mechanism enabled to set an authentication cookie. Authentication is done by sending an initial http request to the endpoint api.myapp.cloud. The server sets the Set-Cookie-Header of the response with a token cookie for authentication. This cookie is somehow not stored in the WebView (Dev-Tools -> Storage -> Cookies is empty)

I also set the hostname preference to the same domain api.myapp.cloud but it does not work.

Does iOS treat cookies as "third-party" when the hostname preference is not equal to the actual hostname of the request?

Any ideas?

Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.