question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

CORS and cookies with capacitor:// scheme and XHR requests

See original GitHub issue

After a bit of fiddling I had finally got cookies to get passed around on cross origin requests, but thus far I’ve been unable to do so on ios with capacitor:// and the latest release (1.0.0-beta.13).

Note that CORS seems to be working ok, I can do cross-origin requests to my remote server, and they work fine. What is not working is the sharing of cookies.

Note that there are several challenges with IOS and WebKit and cookie sharing. These are mentioned here: https://github.com/ionic-team/capacitor/issues/922

The first is that at some stage Apple changed the default cookie sharing policy (despite their docs saying they haven’t). They changed the default from NSHTTPCookieAcceptPolicyAlways to NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain

It seems this default setting will refuse cross domain cookies not matter what you try to do with CORS.

So you need to do this: func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. HTTPCookieStorage.shared.cookieAcceptPolicy = HTTPCookie.AcceptPolicy.always return true }

In app/AppDelegate.swift

However, that isn’t enough because there is also a webkit bug that doesn’t initialise the cookie store the first time you launch the app, so you have to close and re-launch before doing anything cookie related. An ugly hack to work around this is to prod the cookie store before webkit starts with something like this: let cookie = HTTPCookie(properties: [HTTPCookiePropertyKey.domain: “.yourdomainhere.com”, HTTPCookiePropertyKey.path: “/”, HTTPCookiePropertyKey.name: “dummy”, HTTPCookiePropertyKey.value: “dummy value”])! HTTPCookieStorage.shared.setCookie(cookie)

(placed in the same place as the the cookieAcceptPolicy setting above).

With those two bits of code, cookies worked for me in Webkit before the change to remove the server, and use capacitor://

I’m unable to make it work now, with a setup that seems to be the same cookie/cors treatment as being used in the pre-capacitor:// change situation.

I’m setting withCredentials on my XHR request (required for the cookies to be stored), but webkit is refusing to send cookies to the remove host.

Note that debugging this is a bit difficult because the same origin policy to reading cookies applies, so javascript can’t check if the cookies exist on the client, the client when working will send any cookies back to the server, that the server set on previous request responses to the origin in question (capacitor://localhost in this case). The server seems to be fine, it appears to be sending the expected cookies and cross origin allowed headers, it is the webkit client that is deciding not to send them back.

I’ve tested this by adding the following code to my index.html:


       function success2() {
           console.log("xhr response2:",this.responseText);
       }
       function success() {
           console.log("xhr response:",this.responseText);
           var xhr2 = new XMLHttpRequest();
           xhr2.onload = success2;
           xhr2.onerror = error;
           xhr2.withCredentials = true;
           xhr2.open('POST', 'https://my.remotetestinghost.com/api/get_mobile_load_data');
           xhr2.send();
       }
       
       function error(err) {
           console.log('XHR Error:', err);
       }
       
       var xhr = new XMLHttpRequest();
       xhr.onload = success;
       xhr.onerror = error;
       xhr.withCredentials = true;
       xhr.open('POST', 'https://my.remotetestinghost.com/api/get_mobile_load_data');
       xhr.send();

Both requests succeed, and the server sets cookies on both, but the second request does not send back cookies to the server that it received on the first request (verified with safari network inspector attached to the emulator device).

I can’t be sure I’m not doing something stupid somewhere, but it is unclear to me what. If this is a general problem and not something dumb at my end, I imagine this is a show stopper for a lot of people that are trying to wrap an existing web app, as remote server (cross domain) cookie session/auth is probably a very common case.

Is it possible the capacitor:// scheme method has broken cookie passing? It seems like it from my point of view. Is there anything I can do to bring it back? (other than reverting to the pre-capacitor) code.

I’m fairly sure it is a cross origin issue, because this code works ok in local dev mode where I’m going from capacitor://localhost to localhost:3000 (i.e. cookies are shared fine in that situation due to the same host name).

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:8
  • Comments:15 (1 by maintainers)

github_iconTop GitHub Comments

12reactions
rj33commented, Jan 27, 2019

Just a quick note on an easy workaround if you only need to communicate to one cross domain host, and don’t need the access rights that come from calling hostname ‘localhost’.

You can set: “server”: { “hostname”: “yourcrossdomainhost.com”, }

It will still load all files from the local device, but now requests to yourcrossdomainhost.com will happily share cookies because it is no longer a cross domain request due to the device hostname being the same as the remote.

This isn’t ideal, but it at least allows me to move forward without other hacks such as cookie injection and session id sharing across a network backchannel.

It would be nice if cross domain cookies just worked.

0reactions
dhaivat28commented, May 26, 2021

I have the same issue i have been trying to read the message event from an iframe in capacitorjs and is definitely not a CORS issue as i checked response headers from server i.e Access-Control-Allow-Origin:* . After going through numerous posts i tried the most suggested solution to change the hostname. But it seems like it doesnt work in my case.

So my iframe is hosted at “subdomain.domain.com” so i changed the hostname in my capacitor.config.json to hostname:subdomain.domain.com and also tried setting hostname:domain.com but nothing works.

I believe the code is fine as it works on android and web and just doesnt work on capacitor’s scheme. Incase you need to have a look at the code its posted here https://stackoverflow.com/questions/67464857/window-message-doesnt-work-on-capacitor-ios-after-deployment-to-testflight

if anyone can please suggest me a solution or alternative to make it work. Thanks in advance

Read more comments on GitHub >

github_iconTop Results From Across the Web

CORS Errors: Cross-Origin Resource Sharing - Ionic Framework
Cross-Origin Resource Sharing (CORS) is a mechanism that browsers and webviews — like the ones powering Capacitor and Cordova — use to restrict...
Read more >
Chapter 5. Cookies and response headers - CORS in Action
This chapter will introduce two new response headers: Access-Control-Allow-Credentials, which indicates that cookies may be included with requests, and Access- ...
Read more >
Capacitor by Ionic - Cross-platform apps with web technology
Capacitor is an open source native runtime for building Web Native apps. Create cross-platform iOS, Android, and Progressive Web Apps with JavaScript, HTML, ......
Read more >
Set cookies for cross origin requests - Stack Overflow
Cross site approach. To allow receiving & sending cookies by a CORS request successfully, do the following. Back-end (server) HTTP header settings:.
Read more >
How to make API calls in Ionic Capacitor Apps - Enappd
When we make REST API calls to a server, we often encounter CORS (Cross-Origin Resource Sharing) issues. This happens because our REST API...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found