Safari 13+ iframe blocks CORS cookies

13,205

Solution 1

I think I might have found the solution: Apple's Storage Access API: https://webkit.org/blog/8124/introducing-storage-access-api/

Solution 2

So, the workaround still kinda works, as long as the new window is storing the cookie that you want to store. The iframe still can't store it's own cookies. In my case, all I needed was the session id cookie. So, I open a small popup window when the user grants storage access. It gets and stores the session id cookie, closes, and reloads the iframe. The iframe then has access to the session id cookie and sends it in subsequent requests. I think this is just temporary though, it looks like they're going to remove storage access from popup windows sometime in the future. Maybe they'll fix the iframe not being able to store cookies by then.

Share:
13,205

Related videos on Youtube

Tom Teman
Author by

Tom Teman

Software Developer @ WatchDox SOreadytohelp

Updated on September 16, 2022

Comments

  • Tom Teman
    Tom Teman over 1 year

    Safari flat out doesn't let you set cookies in iframes of domains different than the parent domain, server-side CORS headers be damned.

    To clarify: user is on domainA.com. An iframe for domainB.com is open, and attempts to authenticate the user on domainB.com inside the iframe. Set-Cookie header is returned from the server inside the domainB.com iframe, with all the required headers, but Safari isn't sending it back in subsequent calls.

    An old workaround was doing a form submit from the iframe, and set the cookie in the response. I guess they liked the fact that the user was clicking something to submit the form. You'd have to poll for the cookie to see when the response came back, as form submits have no callbacks, and in the case of HttpOnly cookies you couldn't, but hey, it worked! Until it didn't.

    Then, a more recent workaround was redirecting the user to the iframe domain in a brand new window/tab, setting a random cookie there, and from that moment on, that subdomain was "trusted" inside the iframe. Again, it required a click to open the new window/tab, and there was even a visual indication of the new tab opening. Much security, such standards.

    And now, as of Safari 13 - No more workaround. No more secure iframe cookie setting 🤬

    Any other authentication scheme isn't good for us (e.g. Auth-X header). We need to use an HttpOnly secure cookie, as we don't want that token to be in any way accessible by javascript client-side.

    To be clear, everything works great on any other browser.

    Relevant WebKit Bugzilla

    Does anyone have any suggestions?

    Edit:

    Thanks for the link @tomschmidt, that seems like the right direction. I tried using Apple's Storage Access API, but unfortunately, although I'm making sure to request access before initializing my login logic with the API:

    requestStorageAccess = async() => {
        return new Promise(resolve => {
          //@ts-ignore
          document.requestStorageAccess().then(
            function () {
              console.log('Storage access was granted');
              resolve(true);
            },
            function () {
              console.log('Storage access was denied');
              resolve(false);
            }
          );    
        });
      }
    
    
    const storageAccessGranted = await requestStorageAccess();
    console.log(storageAccessGranted) // prints 'true'
    await login();
    

    Still, the cookies received on the /login API response are not getting sent in subsequent calls to the API :(

    Edit 2 (May 2021):

    Safari 14 has added another breaking change:

    https://webkit.org/blog/11545/updates-to-the-storage-access-api/

    Go Apple go! You're making us reminisce about IE6.

    • tomschmidt
      tomschmidt over 4 years
      Make sure this only gets triggered on explicit interaction with the iframe, like onclick.
    • Tom Teman
      Tom Teman over 4 years
      Yeah, that's how I did it. Check out the webkit bugzilla issue I linked to, I guess this is an actual bug on Safari's end :/
    • Matt Cosentino
      Matt Cosentino about 4 years
      The problem isn't that the cookies aren't sent. If you request storage access, existing cookies are sent to the server. The problem is that any new cookies are not stored at all, so they aren't there to be sent.
    • Tom Teman
      Tom Teman about 4 years
      @MattCosentino yeah, that's what I meant - "cookies received on the /login API response" are new cookies that are sent back in the Set-Cookie header response to the iframe domain, but the next call from the iframe domain does not include those cookies in the request. So yes, it's more correct to say the root of the problem is that no new cookies are being stored in the browser in this scenario.
    • Vignesh K
      Vignesh K almost 3 years
      Any ideas on how to fix this after the recent changes? I went through the link you shared but when I use document.hasStorageAccess(), my browser complains that it is not a function.
    • Tom Teman
      Tom Teman almost 3 years
      @VigneshK document.hasStorageAccess is only defined in Safari, Edge and Firefox: caniuse.com/mdn-api_document_hasstorageaccess
  • Tom Teman
    Tom Teman over 4 years
    Hey, thanks for the idea, but I'm afraid it didn't do the trick (check out my answer edit)
  • Niroshana
    Niroshana about 4 years
    I am also having the same issue with safari 13. Any workaround?
  • teamdane
    teamdane almost 4 years
    Matt, I've used a similar solution with a pop up, which works on the desktop Safari 13.1, but testing on an iPad Safari 13.4 it isn't working. Were you able to get this working on an iPad? Thnx
  • Dnyan Waychal
    Dnyan Waychal almost 4 years
    HI Matt, where you open the popup in the iframe code or the main page. also can I have some sample code of it,
  • Alorsons
    Alorsons almost 4 years
    Any Sample Code for us ?
  • Wes Gamble
    Wes Gamble over 3 years
    You can disable "Prevent cross-site tracking" in Preferences -> Privacy
  • Tom Teman
    Tom Teman almost 3 years
    That is a user-side solution. The problem is we are not tracking, but Safari is so strict, that it treats us as if we do (us and thousands of other legitimate applications which this recent change hurts).