Cannot set cookie in iframe using Storage Access API on Safari

I have an iframe on my page. As Safari blocks 3rd party cookies, I am trying to use the Storage Access API as suggested here under 'Developer Guidance': https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/ . I have copied the following code from here https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API/Using#Accessing_a_user's_cookies_in_an_embedded_cross-origin_iframe :

Browser console output:

As you can see, the grant seems to be successful but still cannot set the cookie. Does anyone have an idea what's wrong? I am using Safari Version 13.0.1.

Note: The enclosing page is a simple

safari iframe cookies not working

Safari by default discards cookies set in an iframe unless the host that's serving the iframe has set a cookie before, outside the iframe. Safari is the only browser that does this.

Instantly share code, notes, and snippets.

@iansltx

iansltx / _safari-iframe-cookie-workaround.md

  • Download ZIP
  • Star ( 101 ) 101 You must be signed in to star a gist
  • Fork ( 11 ) 11 You must be signed in to fork a gist
  • Embed Embed this gist in your website.
  • Share Copy sharable link for this gist.
  • Clone via HTTPS Clone using the web URL.
  • Learn more about clone URLs
  • Save iansltx/18caf551baaa60b79206 to your computer and use it in GitHub Desktop.

Safari iframe cookie workaround

Safari by default discards cookies set in an iframe unless the host that's serving the iframe has set a cookie before, outside the iframe. Safari is the only browser that does this.

The 10k foot view

In order to get around the issue, the parent (src) and child/iframed/remote (dest) site have to work together, if the source site only wants users to access the destination via the iframe and can't assume that the user has visited the destination host before.

Normally, a user would navigate from page A, with no external iframe, to page B, with an external iframe, by clicking a direct link between the two. To make the workaround work, the link from page A is instead a "bounce" URL on the destination site, which sets a cookie (no requirements on name, value, etc.) and redirects back to page B. The redirect can be hard-coded for security, or left more open.

The warning

The following files are a naive example of the problem/solution. You'll want to think through your solution more carefully...don't copy-paste these snippets into a production setting! I haven't thought through the security ramifications of what's shown here...which means that there are some, and they aren't good. You've been warned.

The implementation details

This gist includes an implementation of both source and destination sides of the above workaround, including a test to make sure that it actually works. To see the fix in action, place src.php on one host, dest_xxx.php on another, then edit lines 2 and 3 on src.php to reference where those files show up.

To see the Safari problem without the solution, on a new Safari browser, navigate to src.php?redirected=true on a "clean" Safari. By "clean" we mean that Safari has never had a cookie (successfully) set by the destination domain before. The easiest way to do this is to fire up a Safari-powered instance on BrowserStack or the like.

When you load the page, you'll get an iframe. Click the link inside the iframe and you'll be greeted with a "Cookie not set!" message.

To see the solution, navigate to src.php (without the query string parameter) in the same browser (since the cookie wasn't successfully set, there's no need to set up a new clean Safari instance, though you can if you like). Then click the "Bounce here..." link. The browser will hit the remote site, which will set a blank cookie and redirect back to src.php?redirected=true.

When you click the link inside the iframe this time, you'll get "Cookies match!".

Note that if you use some browser (Chrome, Firefox, IE) other than Safari, you can just hit src.php?redirected=true and get "Cookies match!" without having to first go through the redirect.

The credits

This issue was discovered, and its solution devised, while working on Parking Mobility ( https://parkingmobility.com ).

@WebSpectrum

WebSpectrum commented Mar 16, 2020

Hi All - what is the best solution to date if you don't have control or ability to deploy code on site B ? ....

Sorry, something went wrong.

@xk4r00t

xk4r00t commented Mar 16, 2020 • edited

I used a popup to do the trick (by temporary passing the cookie as parameter to a third party API). If you have full control on site B (code + DNS) I advice you to declare a subdomain in you site B which forward silently to your wished website/API (add a new AAAA entry with your service IP) :

@russau

russau commented Mar 31, 2020

It looks like all of these approaches have gone away with Safari 13.1 :(

https://community.shopify.com/c/Shopify-APIs-SDKs/Safari-13-1-and-embedded-apps/td-p/688416 https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/

@mwleinad

mwleinad commented Apr 7, 2020

Any idea if there's a workaround with safari 13.1?

@antstorm

antstorm commented Apr 12, 2020

Looks like requesting storage access via their APIs is the way to do it — https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/

@Arcolye

Arcolye commented Apr 29, 2020 • edited

What a fantastic time to put this extra hurdle on struggling and furloughed development teams. Thanks Apple, Safari, and specifically John Wilander!

With brick-and-mortar businesses struggling and software companies doing what they can to help out, NOW was the time to release this huge software-breaking change? Not 2022 like Chrome has roadmapped? Now? During the Covid recession? And with "Storage Access API" still in a poorly-documented and experimental phase? Now?

Badly done, Safari. Badly done indeed. Shame on you, John Wilander.

@asecondwill

asecondwill commented May 1, 2020

The workarounds seem to work, but not in webkit view in eg facebook/twitter/instagram webviewer. And clues on what to do would be ace.

@stevenlawrance

stevenlawrance commented May 5, 2020

From https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/ , it appears that a workaround that uses OAuth2 may exist, though it's not exactly clear how to invoke this (and using Secure+HttpOnly cookies isn't sufficient to make it work). I'll have to poke around the WebKit source code..

Option 1: OAuth 2.0 Authorization with which the authenticating domain (in your case, the third-party that expects cookies) forwards an authorization token to your website which you consume and use to establish a first-party login session with a server-set Secure and HttpOnly cookie.

@github-xuser

github-xuser commented May 19, 2020

I have a workaround based on an interface to sagepay. We tell sagepay where to return to after CC entry in an iframe, Once the user submits the CC form to sagepay, they redirect the iframe to us and we take over control of the iframe and close it. Unless its the latest safari. Then the iframe redirect happens, but with no session cookie so our software has no continuity and terminates because it thinks the session has timedout. Not very good when someone is trying to buy something in your shop. I already implemented a change so that the iframe was created with a page from our domain which then redirects to sagepay, so i know that safari has the correct session cookie in the iframe. This did actually fix quite a lot of the problems but not all. My thought for fixing them all was that safari doesnt like sending the correct session cookie when sagepay redirects back to our domain, but i wonder what will happen if i make the redirect from sagepay simply do another redirect from us, to us. It worked, on the second redirect from our domain to our domain the session cookie is correct. That has to be a bug in safari. So if i am dom1.com and sagepay is dom2.com the fix is: Create an iframe with src = dom1.com/redirect1 this simply contains html or javascript to do the correct redirect to your dom2.com page. Tell dom2.com to return to dom1.com/dummyredirect. dummyredirect copies all the querystring or post data and returns a page that redirects back to dom1.com/theproperreturnaddress. Its passed all our tests so far. I hope it helps someone else, I can't see safari getting fixed or even acknowledging the bug anytime soon.

@xabier98

xabier98 commented May 20, 2020

Please ¿can you explain or write an small example with your solution?

Best Regards

@engelmav

engelmav commented May 26, 2020

What a fantastic time to put this extra hurdle on struggling and furloughed development teams. Thanks Apple, Safari, and specifically John Wilander! With brick-and-mortar businesses struggling and software companies doing what they can to help out, NOW was the time to release this huge software-breaking change? Not 2022 like Chrome has roadmapped? Now? During the Covid recession? And with "Storage Access API" still in a poorly-documented and experimental phase? Now? Badly done, Safari. Badly done indeed. Shame on you, John Wilander.

Fascinating. The economic impact of code changes... should be factored in with behemoth applications and firms like Safari/Apple.

@jhud

jhud commented May 30, 2020 • edited

Hi everyone, commiserations to those of you who also got blindsided by this during all the other Covid-19 IT dramas. Anyway, here is my quick fix for this.

Note that you cannot nest the document.hasStorageAccess, otherwise it misses the user interaction, so I don't bother checking - I run the code every time. I dropped this code inside my iframe. It needs to be triggered from an onClick, ie:

But instead I call this directly from my login form:

The first login fails because Safari pops up a non-blocking "do you want to allow..." popup, but it'll suffice until there's a fix that won't pollute the UI with some "click this if you are on Safari" button.

Apologies for the messiness - it's Saturday night and I just need to rush this out now so my customers can start making money again.

@mpirog-hw

mpirog-hw commented Jun 5, 2020 • edited

The economic impact of code changes... should be factored in with behemoth applications and firms like Safari/Apple.

Not just economic, but very real health impact. My company delivers healthcare related information to patients, including COVID-19 content. We act as a third party to health plans and it's an all too common practice for this industry to integrate within iframes.

As it stands, patients using Safari can't access our content due to this security change. Content like ours has been shown to improve health outcomes. If you use Safari you might suffer a worse outcome in the event of a health crisis.

looks like requesting storage access via their APIs is the way to do it

The storage access API in Safari will flat out reject requestStorageAccess() if the client hasn't visited the third-party in first-party context AND has interacted with the site — https://stackoverflow.com/questions/52173595/how-to-debug-safari-itp-2-0-requeststorageaccess-failure

Interestingly, Firefox's implementation doesn't appear to enforce this same requirement, only adding to the confusion.

The majority of our users don't know who we are and have never visited our domain directly. The Storage Access API is clearly designed to accommodate social media network workflows. The rest of us are getting steamrolled.

@lenusch

lenusch commented Jul 5, 2020

Does it work now? Is there a functional workarround? I didn't get this to work until now :-(

@sarayaz

sarayaz commented Jul 8, 2020

Does anybody have solution for this in safari 13+ ?

@joostfaassen

joostfaassen commented Aug 18, 2020

None of these solutions worked for us. And the same issue started showing up in Google Chrome and other browsers (especially in incognito / private modes).

What we did is add an upstream location on the vhost of the site that embeds the other site. I.e. this adds https://mainsite/my-embedded-site/ * that forwards requests to https://my-embedded-site/

This way both sites get served to the end user from the main domain (mainsite) making all cookies "first party" cookies.

This solves the problem for us on all combinations of platforms, browsers and incognito vs normal modes.

Additionally, make sure your "secure" and "samesite" cookie options are set correctly, and make sure the cookie names on the main + embedded sites differ (otherwise they keep thrashing eachother's sessions 😄 )

It does require that you control the embedding app's server, so this won't solve the situation for everybody.. but I hope it'll help some people in this thread!

jhud commented Aug 18, 2020

Note that Apple seems to keep closing off iFrame cookies with every Safari update and breaking my workarounds. I gave up and am moving to a JS library. It might be possible to pass cookies with postMessage, but in the end it'll be less screwing around to just do an API integration with the host sites.

@luxio

luxio commented Aug 20, 2020

@joostfaassen Thank you for sharing your solution.

Could you share your server configuration to create the upstream location?

@JamesMcMurrin

JamesMcMurrin commented Aug 20, 2020

I tried a similar script to this, and IE 11 died just from having the document.requestStorageAccess in the script. Never mind that it'll never reach it (or that I put it in a try catch), it throws a syntax error just seeing it.

The first login fails because Safari pops up a non-blocking "do you want to allow..." popup, but it'll suffice until there's a fix that won't pollute the UI with some "click this if you are on Safari" button. <script> // Safari now suddenly blocks iframe cookie access, so we need to call this during some user interaction function safariFix() { if (navigator.userAgent.search("Safari") >= 0 && navigator.userAgent.search("Chrome") < 0) { document.requestStorageAccess().then(() => { // Now we have first-party storage access! console.log("Got cookie access for Safari workaround"); // Let's access some items from the first-party cookie jar document.cookie = "foo=bar"; // drop a test cookie }, () => { console.log('access denied') }).catch((error) => { // error obtaining storage access. console.log("Could not get access for Safari workaround: " + error); }); } } </script>

@benross

benross commented Sep 9, 2020

Thanks for the many ideas in this thread!

Wanted to share we've been using a service to get around this issue and so far it has been working well for us: cloudcookie.io . We host content in 3rd party iframes and often don't have access to the parent (host) page. It's a commercial solution so might not be appropriate for all but pretty inexpensive (and has a free tier).

lenusch commented Sep 10, 2020

Thanks for the many ideas in this thread! Wanted to share we've been using a service to get around this issue and so far it has been working well for us: cloudcookie.io . We host content in 3rd party iframes and often don't have access to the parent (host) page. It's a commercial solution so might not be appropriate for all but pretty inexpensive (and has a free tier).

Hi, i double checked everything but we have a PHP App and need a Session Cookie and this Javascript "CloudCookie" will not be able to pass Session Cookie to PHP, or am i mistaken? My Mate told me this would be not fit my needs. :-S

jhud commented Sep 10, 2020 • edited

I looked at some existing solutions, and big companies which rely on iframes appear to be passing the session tokens through PostMessage between the host page and the iframe.

But I am sick of doing these increasingly ugly hacks. IMO, iframes and 3rd party cookies are dead - Apple has just killed them a year or so earlier.

So I have converted my old iframe integrations to use my existing app REST API + JavaScript + local storage. My customers love this JS client-side integration compared to iframes, and it gives me a unified interface for my apps and web. It's a much more solid solution which will last for the ages.

I know you don't want to hear this if you are looking for a quick fix, but I suggest that you already start planning to ditch iframes + 3rd party cookies in the medium to long term.

@code2infiniteE

code2infiniteE commented Sep 12, 2020

I also tried cloudcookie.io and have it working on a project. It's a front-end (javascript) cookie framework, so if you need the cookies on the server-side (eg PHP), you just need to add an ajax call or page redirect once you get the cookies from the front-end. ( @lenusch )

@Benamin

Benamin commented Sep 17, 2020 • edited

this solution is works; https://github.com/vitr/safari-cookie-in-iframe/blob/master/index-fixed.html

@sparkdoo

sparkdoo commented Oct 19, 2020

@jhud how are you dealing with the security implications of providing a client side javascript approach vs iframe? We considered both options but found the risk of running our javascript next to potentially malicious javascript too much of a concern to proceed, but of course as you say the new concern is that our existing solution will be completely blocked in the not so distant future

@Tofandel

Tofandel commented Aug 31, 2021

The joys of tech giants imposing their wishes to everybody because they are trying to block third party tracking, except third party tracking can find tons of workaround other than cookies usually, but for authenticating a user in a secure way you need cookies, so effectively they screw you, force you to use a thousand times less secure approach for the sake of user privacy and don't give you an alternative

Iframes are not just used for third party tracking and sadly they don't understand that.

jhud commented Aug 31, 2021

I trust all the host websites. I would love to have better integration to avoid CSRF/XSS attacks, but it is sufficient for my customers' purposes, and it is the situation the tech vendors have left us in.

The approach is basically to write a Single Page Application. After having done React and Vue.js development since making this decision, it has just cemented my opinion that client-side JS is the way to go for anything other than a basic CRUD website.

@gbenchanoch

gbenchanoch commented Sep 10, 2021

Are you still using CloudCookie? Has the solution been stable for you across all browsers, as well as mobile? I am having stability issues loading a specific 3rd party provider via iframe, particularly on Safari.

@pini85

pini85 commented Oct 14, 2021 • edited

I would also be interested to know if this is still valid

code2infiniteE commented Oct 15, 2021

@pini85 && @gbenchanoch yes cloudcookie.io has been working for us so far! :)

Third-Party Cookie Restrictions for Iframes in Safari

Photo by pine watt on Unsplash

Third-Party Cookie Restrictions for Iframes in Safari

Malav Shah's photo

Table of contents

What do you need to know before, introduction, storage access apis, we are hiring.

What is an iframe ?

What are cookies?

What is a third-party cookie?

Have you ever wondered why some websites ask for storage permissions or why some features don't work in certain browsers? Let's dive into the intricacies of third-party cookie restrictions in Safari and how we tackled them!

Safari , Apple's flagship browser, has always been a pioneer in the quest for user privacy and security . In recent years, it has made significant strides in protecting its users from the prying eyes of online trackers by restricting third-party cookies .

In the following discussion, we will delve into a specific challenge encountered within this privacy-focused paradigm. This blog aims to unravel the complexities of seeking storage permission in Safari, particularly when our content is loaded within an iframe and relies on third-party cookies.

The predicament arose as we endeavored to integrate our React-based web app into an iframe hosted on a different domain. This intersection of domains posed a unique challenge, prompting us to explore innovative solutions to seamlessly navigate the intricacies of Safari's third-party cookie restrictions.

Our application uses cookies for authentication. In one of the use cases, it was being rendered inside an iframe. The parent HTML document that was rendering the iframe was being hosted on an entirely different domain.

In other browsers, our application within the iframe was able to access the cookies but not in Safari. Safari uses Intelligent Tracking Prevention(ITP ) to control the access of third-party cookies.

ITP aims to prevent third-party cookies, making them inaccessible in iframes unless certain conditions are met. These conditions can be found in the Webkit's official announcement .

"Third-party cookie access can only be granted through the Storage Access API."

Let's look at parts of this API that concern our problem:

document.hasStorageAccess API Doc

This API is used to check cookie storage access. This will return false for third-party cookies in the case of the Safari browser.

document.requestStorageAccess API Doc

This API is used to ask for third-party storage(cookie) access explicitly from the user.

Both of the above APIs are available in Safari as well as in other browsers .

Webkit's official documentation explains the steps to use these APIs & the rest of the user flow(which is the basis for the following solution). We recommend giving it a read before moving ahead with this post.

The solution described below is not the only one but will help you in designing solutions for your use cases. You can also design a solution as per your needs by following the guide mentioned here .

We are using react so the above-mentioned solution is written in the concepts of react.

We have created separate utility functions in the helper file.

The above code is to make the browser API abstract from the actual implementation. These functions are what we are going to call.

Then after, we created a new file named useStoragePermissions.tsx and added the below-mentioned code.

Using the above hook we have exposed below three states:

needPermission : This will be true when the browser is Safari and it has support for hasStorageAccess and requestStroageAccess

Hint: Use this boolean while consuming this hook to decide when to call askForPermission and haveCheckedPermission .

askForPermission : This is the function that the consumer could call to request the user to give storage access permission

haveCheckedPermission : This is a boolean which will be true after calling askForPermission in the case of needPermission is true initially.

To consume the above hook, we have followed the below-mentioned steps:

We have mounted and created a hook in #2 at the initialization part of the app. Use the needPermission state from it and proceed ahead as normal when needPermission is false .

We created some other routes user-access-flow that show a button with some text like Set Cookie . And onClick of it, we set the cookie.

This is where we are actually calling authentication-related APIs and then the server is setting up cookies.

Once this cookie is set, close this tab using window.close()

Now when, needPermission is true

We show the user some text like, " Click here and click on the Set-Cookie button on the newly opened tab " and on click of it, redirect the user to the route created in above step 2.

Now, when a user comes back from that route, call askForPermission on click of some button. Which should ask the user to give storage permission.

Storage access permission ask popup in safari

Once the user clicks on Allow the button, your website is authorized to store and access third-party cookies and now you can continue with business logic.

We have also kept this thing in mind that this consent will be revoked if the user cleans up the browser history and does not visit that domain for 7 days. These constraints are already mentioned here

If you have faced such issues while developing or browsing such issues, please share those in the comments. We will be more than happy to read and comment more on those.

If solving challenging problems at scale in a fully remote team interests you, head to our careers page and apply for the position of your liking!

Advanced iFrame

Home of advanced iframe and tinywebgallery, 3rd party cookie in iframe workaround.

The problem that is solved here is that Safari on iMac blocks 3rd party cookies by default. Also on ipad (Prevent Cross-Site Tracking) and Firefox (Accept only cookies from visited pages) the browser can be configured that you need this workaround! So if your page in the iframe needs cookies you should continue reading.

Also cookies in iframes need to be secure and have the attribute SameSite=None set! Please see here: https://www.tinywebgallery.com/blog/advanced-iframe/advanced-iframe-pro-demo/how-to-use-the-samesite-cookie-fix

Advanced iFrame Pro does now support the “Safari 3rd party cookie in iframe workaround” described at http://vitr.github.io/safari-cookie-in-iframe/ . I have integrated this workaround and also enhanced it that you also can apply this for all browsers! So please read the page from vitr first. All the credit for this solution goes to vitr! Unfortunately the example there does not work anymore!

If the page in the iframe does require cookies to work properly you should try to apply this fix.

This is how it works:

  • The solution does a redirect once to a page on the domain where the iframe is located.
  • This does set a cookie and
  • redirects back to the original page which is then properly loaded.

So you have one additional reload for the browsers you configure.

The configuration for this fix can be done in 2 ways depending on the access rights you have on the remote server. This can all be configured in the administration on the “Advanced Settings” tab -> “Advanced features” at “Safari cookie fix” or with the short code parameter safari_fix_url:

  • Copy a file to the remote server. This is the preferred way. The provided  wp-content/plugins/advanced-iframe/includes/_safari_fix.html has only a few bytes and is loaded really fast. Copy this file to the same domain as the iframe. Set safari_fix_url=”<path to _safari_fix.html>”. Only the url without /_safari_fix.html has to be set..
  • Usage of the external workaround . For this the whole iframe page with all assets has to be loaded. The overhead is most likely really huge compared to the _safari_fix.html. But sometimes this is the only option! As this is only done once per user this often is also acceptable. You need to apply the external workaround and set safari_fix_url=”src”.
  • You don’t have access at all to the other server: The fix cannot be applied .

What else does this solution offer?

  • Support for all browsers: Most browsers you can configure that 3rd party cookies are accepted, blocked or to accept 3rd party cookies from visited sites only. Currently Safari is the browser that has the default the 3rd party cookies from visited sites are accepted. But you never know how the user does configure his browser! Also browsers behave differently if you are on a sub domain or a remote domain. This can be activated by adding all: to the safari_fix_url. e.g. safari_fix_url=”all:src”
  • Show a message in case of a problem: The offered solution can be configured that a configurable message (default: This website requires that third-party cookies are accepted. Please change your browser settings that at least “from visited” cookies are allowed.) is displayed to the user if even after the fix no cookie can be used. If your page does depend on cookies this is the best you can do. Normally this should only appear for users that have changed their settings manually. This can be activated by adding message: to the safari_fix_url. e.g. safari_fix_url=”message:http://www.mdempfle.de/fix”. It can also be combined with the setting above: safari_fix_url=”all:message:http://www.mdempfle.de/fix”.

The next demo’s show both ways how to do the setup in detail. If the workaround is applied once you need to delete the cookies “aifixed” and “aichecked” from www.tinywebgallery.com and the cookies “safari_cookie_fix” and “the_cookie” from www.mdempfle.de to try it again. Otherwise also the example without a fix is now working. The solutions are configured to show the message and to work on all browsers. Only the Safari one only applies the fix for Safari. On the example pages are explained how to only apply the fix for Safari and without a message.

Example without a fix

Example with safari_fix.html

Example with safari_fix.html – Safari only

Example with external workaround (ai_external.js)

PS: If you want to test this whole feature here and you don’t have a MAC I recommend to test with Firefox because there you can set all 3 possible values for the 3rd party cookies!

INTERNET EXPLORER:

Like always IE is behaving differently! To allow cookies inside a iframe p3p header needs to be set. You can google a lot about this issue but the best solution I have found is to set:

header(‘P3P: CP=”ALL DSP NID CURa ADMa DEVa HISa OTPa OUR NOR NAV DEM”‘);

To the page in the iframe. This header is set in the plugin already for the parent. But the already set header only works if you share your content like shown in “ Add ai_external.js local “. For any other setup you have to include the header manually. If the page in the iframe is also WordPress you can also use a plugin like HTTP Headers and set the p3p header there.

The following cookies are set with the feature. Please add this to your privacy policy page if you use this fix:

  • aifixed: This cookie is used on the parent domain to check if the fix was applied already.
  • aichecked: This cookie is used on the parent domain to check if the fix works. This is only used if you show a message in case of a problem
  • safari_cookie_fix: This cookie is used on the iframe domain and needed to tell the browser that you have already visited the domain directly and allow therefore 3rd party cookies
  • ai_test_cookie: This session cookie is used on the iframe domain to check if the warning message is needed. It is deleted right after the check again.
  • the_cookie: Is the test cookie of the page in the iframe. You have your own cookies here!

safari iframe cookies not working

  • Latest Articles
  • Top Articles
  • Posting/Update Guidelines
  • Article Help Forum

safari iframe cookies not working

  • View Unanswered Questions
  • View All Questions
  • View C# questions
  • View C++ questions
  • View Javascript questions
  • View Visual Basic questions
  • View Python questions
  • CodeProject.AI Server
  • All Message Boards...
  • Running a Business
  • Sales / Marketing
  • Collaboration / Beta Testing
  • Work Issues
  • Design and Architecture
  • Artificial Intelligence
  • Internet of Things
  • ATL / WTL / STL
  • Managed C++/CLI
  • Objective-C and Swift
  • System Admin
  • Hosting and Servers
  • Linux Programming
  • .NET (Core and Framework)
  • Visual Basic
  • Web Development
  • Site Bugs / Suggestions
  • Spam and Abuse Watch
  • Competitions
  • The Insider Newsletter
  • The Daily Build Newsletter
  • Newsletter archive
  • CodeProject Stuff
  • Most Valuable Professionals
  • The Lounge  
  • The CodeProject Blog
  • Where I Am: Member Photos
  • The Insider News
  • The Weird & The Wonderful
  • What is 'CodeProject'?
  • General FAQ
  • Ask a Question
  • Bugs and Suggestions

safari iframe cookies not working

Cross-Domain Embedding: Making Third-Party Cookies Work Again

safari iframe cookies not working

  • Download source code - 16.6 KB

Introduction

Back in February of 2020, Google began rolling out their change to how third-party cookies are handled . This move was to help stop embedded cross-domain sites, often social media sites, from tracking your movement around the web without you knowing. There were two basic changes made:

  • The cookie SameSite value now defaults to Lax instead of None
  • If a value of None was explicitly set, then Secure must also be set

This caused most cross-domain embedded websites to no longer be able to use cookies, even those which are not malicious, as the browser began to block them.

The good news is it’s still possible to use third-party cookies from an embedded cross-domain website inside of an iframe. The bad news is it’s more difficult now, and Safari / iOS have additional steps using experimental APIs to make this work.

This article will go through the basics of getting this scenario working using an example node.js web host. The technology stack isn’t important though – any web host and language can accomplish the same.

The Old Way

The first thing we’re going to do is create a basic example that has 2 websites on different domains, with one embedded in the other in an iframe. To do this, we’re going to take advantage of the fact that localhost is treated as a different domain from 127.0.0.1 which means we can do all of this testing on our local machine. Hurrah.

To start, install node.js on your machine and some sort of IDE if you don’t already have them. In addition to node.js, we’ll also need express , a quick and easy web host package on top of node.js. It can be installed with npm install express when run from your working project directory.

First, we’ll make app.js which is the entry point for our two websites:

In addition, we’ll create two folders in the same directory, one named www for the top-level application, and another named www2 for the embedded application. In both directories, we’ll create an index.html as follows:

www/index.html

Www2/index.html.

And lastly, we’ll create some JavaScript to try and get the cookie, in this case, put in www2/scripts/index.js :

Finally, we’re ready to run this. It can be run using the command line: node app.js .

Once running, we can browse to http://localhost:3000/ which will show us:

Image 1

Notice the text that the cookie cannot be found. This means our JavaScript could not find the cookie.

This is because we’re emitting the "old style" cookie with no SameSite and no Secure values. This can be seen if the Developer Tools are opened and the Document request is inspected:

Image 2

The cookie is highlighted in yellow by the browser as it is being actively rejected. So how do we fix this?

The New Way – SameSite, Secure and HTTPS

In order to make this work, we must modify the cookie we’re sending to include SameSite=None to avoid the new default of Lax :

But this isn’t enough, and if you load the page like this, you’ll see the same problem – Developer Tools will show the SameSite=None , but still reject it:

Image 3

This is because we also need to set the Secure value as per Google’s second change. The Secure value indicates the cookie should only be accepted over a secure HTTPS connection.

In order to get this to work, we must move the web application to HTTPS. To get HTTPS working locally, we can use self-signed certificates (this is just for development, after all). To do that, I followed this guide which helped immensely.

The first step is to generate self-signed SSL keys, which can be done with the openssl commands:

To make this easier, I’ve included generated self-signed keys already made inside of the project which are valid for one year.

Now we can modify the cookie to include both Secure and SameSite=None :

We’ll also need to modify our app.js file to support HTTPS instead of HTTP. The completed modified file looks like this:

And we’ll need to update the URL on the iframe in www/index.html :

Running this will create two HTTPS websites instead of HTTP ones.

However, if you browse to the outer website, https://localhost:3000/ , it will show a big scary red error with the text NET::ERR_CERT_INVALID because the certificate is not trusted:

Image 4

To bypass this, both the inner and outer websites ( https://localhost:3000 and https://127.0.0.1:3001 ) must be opened at the top-level (in a tab), and " thisisunsafe " must be typed. After typing this magical phrase, the website will show:

Image 5

It works! We can now send a cookie from our embedded website on a different domain to the client.

But there’s still a problem with Apple …

Safari on macOS and iOS

If you open this exact same website in Safari on macOS or iOS, you’ll see the following:

Image 6

That’s right, it’s back to not working. This is because Safari won’t accept third-party cookies at all even with the new SameSite and Secure values set on the cookie. To make matters more frustrating, if you open the Developer Tools and inspect the response, there’s no cookie listed (and no reason for rejection):

Image 7

Fortunately, this too can be solved using Safari’s experimental storage access API . The process is outlined in this webkit article , and it can be summed up as follows:

  • In the embedded site, use the experimental document.hasStorageAccess() to determine if access is available to the cookie.
  • If access is not available, have a button that, when pressed, will call document.requestStorageAccess() . This method will only work from a UI event (and will consume it).
  • If the request fails, then the user either denied the request or has never opened the embedded website as a first-party website (and we must help them do that).

To implement this, we’re first going to add a button to www2/index.html :

Then we’re going to modify the JavaScript in www2/index.js to use the new experimental API by adding the following:

The process is simple: first check if the experimental API exists at all (it won’t outside of Safari), and if it does check for access, and if access isn’t there, then request it when the user clicks the button by opening a new page called requeststorageaccess.html .

The last step is to create this new page, requeststorageaccess.html :

With the following JavaScript to handle the button click inside requeststorageaccess.js :

We’re going back in the history here since we know we’d be re-directed from our main page. Now if we restart node and render this in Safari, we’ll see the following:

Image 8

Clicking the ‘ Request ’ button will forward the user to the new page we created on the embedded domain:

Image 9

Note the URL is our embedded URL, https://127.0.0.1:3001/ . This is important and the user would normally want to know what company exists on this URL. Once they know, they would (ideally) click the button to go back to where they came from, which will once again show the same page as above.

After returning, the user must click one more time on the ‘request’ button where they’ll finally receive a prompt from Safari:

Image 10

Clicking ‘ Don’t Allow ’ will reject the Promise from requestStorageAccess() and ultimately lead us back to opening a page (because we don’t know why we got a rejection), while clicking ‘ Allow ’ will execute our code to reload the page and finally work:

Image 11

And the cookie will also finally show up in Safari’s Development Tools:

Image 12

As a developer note, once you accept the browser prompt to ‘ Allow ’, the only way to undo it is to clear the website data from Safari -> Preferences… -> Privacy -> Manage Website Data…

Image 13

If you want to re-try this process, remove the data for the embedded URL and start the process again.

While it can be quite a bit of work, it’s still possible to have third-party cookies work in an embedded cross-domain website that’s inside of an iframe.

Even with Safari’s new restrictions, it can still be accomplished through their new experimental API.

The full source to run the completed project is available attached to this article and also in my github repository . The source includes packages.json which means you can run npm install in the directory to get the required packages followed by node app.js to run the application.

  • 21 st April, 2022: Initial version

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Comments and Discussions

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

safari iframe cookies not working

.css-qdkd1s{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;} .css-awisqz{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;contain:paint;overflow-y:clip;overflow-clip-margin:10px;} How .css-1i82ydo{display:block;}   to   set   cookies   from   an   embedded   iframe

In   this   guide,   you   can   learn   how   to   set   cookies   from   a   site   embedded   into   an   iframe   using   postMessage   handlers.  

By Sebastijan Dumančić

Our app is written in React so your use case may differ syntactically, but the idea is the same. First up, let's assume you have an existing and working Cookie popup ready. When a user clicks on I accept to accept the cookies, fire the postMessage to the parent element:

This exposes the message to the eventual containers your site is loaded with iframe into.

Note the * wildcard which allows any domain to read this message. Change this to the URL of the site you're embedding the site into to allow only that URL.

Next up, in the parent site , you should load the following snippet:

This snippet adds an event listener that keeps track of the message event. Also, note the wildcard operator (*) which should be replaced with the target origin to control which parent sites you send the message to. Once a message event is fired, we check if it's the same one as we've sent:

If the condition above resolves to true, set your cookies in the parent site.

Once the cookies are successfully set in the parent site, repeat the previous step, but the other way around. Send the message using postMessage method on the   iframe element which you get by assigning a unique ID to the element itself.

Back in our app that's now rendering inside an iframe, listen for the message event. Message event here tells us that the cookie has been successfully set in the parent site. When the message is received, fire up your actions to close the popup.

After this, you're done! It's three fairly simple steps that are unnecessarily complicated explanations on the internet.

There are a couple of things to keep in mind:

  • If you're testing this using a plain old HTML document to create an iframe, document.cookie won't work, at least with Chrome. Setting cookies in a local environment doesn't work for some reason.
  • Use serve package from NPM for testing the site(s) on a local machine ( https://www.npmjs.com/package/serve ).
  • Make sure to update the * (wildcard) to the specific URL you're transmitting the message to.

Thank you for taking the time to read this post, and feel free to share your thoughts and drop us an email at [email protected] . 😄

Related Articles Technology x Design

  • 02 Mastering the Parallax Effect: A Guide to Using the React-scroll-parallax Library Development
  • 03 How to Send Valid & Trusted Automated E-mails Development

.css-migc8w{position:relative;display:block;}.css-migc8w::before{content:'';position:absolute;width:0;height:4px;border-radius:4px;background-color:var(--color-light);bottom:-16px;right:0;-webkit-transition:width 1s cubic-bezier(0.23, 1, 0.32, 1);transition:width 1s cubic-bezier(0.23, 1, 0.32, 1);}.css-migc8w:hover:before,.css-migc8w:focus-visible:before{width:100%;left:0;}.css-migc8w::before{background-color:var(--color-night);} Start   a   Project

  • Linkedin Linkedin ↗ ↗
  • Dribbble Dribbble ↗ ↗
  • Twitter Twitter ↗ ↗

Code that Counts

Code that does good

safari iframe cookies not working

Setting cookie in iframe that is in different domain

To set a cookie in an iframe that is in a different domain than the parent site, you can use SameSite=None . These are called third- party cookies .

Here is a site where you can test this https://www.beski.in/demo/test-parent.html .

This works on:

  • Chrome (normal)
  • Firefox (normal and incognito)
  • Edge (normal and incognito)
  • Safari (incognito apparently)

This does not work on :

  • Chrome (incognito)
  • Safari (normal)

This is due to the blockage of third party cookies

This is toggle on Chrome incognito that if it’s disabled, the cookies will work.

safari iframe cookies not working

For other settings on how to disable this, you can go here https://medium.com/@akohubteam/how-to-enable-third-party-cookies-on-your-browsers-f9a8143b8cc5

Webkit also announced that third-party cookies are disabled by default from 24th of March 2020 and this will roll out eventually on every browser that uses webkit.

I also expect this to be reflected by other browsers in the near future.

If you think you can use localStorage , think again. That is also blocked when third-party cookies are blocked.

This is great news for security but what about the sites that still need this to work properly? What should iframes use to remember data when they are embedded in other domains? A friend of mine said that iframe are becoming deprecated and embedded widgets are the future.

What do you think?

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Safari Websocket Connection Problems in iframe - endless reload

I have an app where we allow parts of the app to be embedded into other pages. This all works in Chrome, Firefox but not in Safari. In Safari we see an endless reload of the iframe. In the console we don’t get any error or warning. We’ve set CSP policies frame-ancestors and connect-src for both the app itself and the embedding frame.

The websocket connection join request fails with

The app itself works properly in Safari (and all other browsers) only embedded in Safari causes this error.

we got the exact same problem. Everything works as expected until we embed the app via an iframe. Every browser works except safari. We get also the response

{response: {reason: "stale"}, status: "error"}

Did you solve it?

We set the frame-ancestors, the connect-src. We also set the session cookie option same_site: “None“ and set the secure attribute by setting same_site: "None", secure: true .

Hi, No, unfortunately not. Still looking for a solution… It’s not the highest priority therefore I could put it aside for a while but need to solve it. Let me know if you make progress.

The reason is the default behaviour of safari, iframes and cookies. It blocks third-party-cookies in iframes. (Prevent Cross-Site Tracking)

You can test it by visiting your site, where the broken iframe is included. Then go to safari preferences → privacy and uncheck the “Website-Tracking“ checkbox. Your app will work fine afterwards.

Thats no solution, just for verifying the reason.

Found this with fast googling Safari iframe cookie workaround · GitHub

Thanks for pointing out the problem and links to the solution. Have to say that all is not really good for our solution where we don’t have much influence on the embedding site…

I’m not sure if this has any help to you. But how our company’s software uses cookies is by only having one cookie that contains JWT token with unique client id. Then we tie everything to that client id, like authorization when user is logged in. So instead of using multiple cookies as such we only have one cookie that identifies the browser. Instead of cookie you could also use local storage then send that in LiveSocket params on connect. Of course that is not as secure as http only cookie.

:wink:

thanks for the additional thought. actually if that is only cookie related I think I just need to remove all cookies in our pipes that are not needed in our case.

Win an ebook

Our Sponsors

safari iframe cookies not working

  • Back to top

© Copyright Elixir Forum | Terms | Privacy & Cookies

Elixir Forum

Apple’s Worldwide Developers Conference to kick off June 10 at 10 a.m. PDT with Keynote address

The Keynote will be available to stream on  apple.com , the Apple Developer app, the Apple TV app, and the Apple YouTube channel. On-demand playback will be available after the conclusion of the stream.

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

LocalStorage not properly work in Iframes

LocalStorage is not properly work in Iframes (SAFARI)

When i'm try to use the LocalStorage in Iframes , it not work fine

Browser( SAFARI ) not able identify the domains . so, it create false instance of LocalStorage for same Domain

Example (tab has an iframe of same domain):

Safari need to address this Issue

Posted on Jul 23, 2019 4:22 AM

Eric Root

Posted on Jul 23, 2019 9:49 AM

If you want to, you can send Apple feedback. They won't answer, but at least will know there is a problem or a suggestion for change. If enough people send feedback, it may get the problem/suggested change solved sooner.

Safari Feedback

Similar questions

  • [Safari 14][SameSite]Cookie is blocked when SameSite is set to Lax Reproduce Steps: Use window.open to open a new tab in Safari 14 In the original tab, using JS to create a FORM in the new opened tab and submit to redirect to a specified URL The cookie info which's SameSite is set to Lax is lost in the new tab. The reason should be, Safari 14 consider this scenario is carrying over cookie info from one tab to another tab and then block the cookies with SameSite set to Lax. However, actually the FORM is created and submitted in the new tab, there is no CORS happens, Safari should not block the cookie. Safari with old version and other browsers all will not block the cookie in this scenarios, so we consider this as an issue of Safari 14, please help verify. Thanks. 1257 1
  • Separate tab pop ups in safari and t he page is directing to some unusual search site and lands into Amazon deal page How to resolve this problem? In my safari home page, every time I try to open a new tab or window, and type in the website address I intend to visit, a separate tab pops up in safari and the page is directing to some unusual search site and lands into Amazon deal page. Sometime it automatically opens several others tabs and automatically types in some website address and tries to open other sites. 590 1
  • Safari asks if I want to "allow" pages Each time I go to another page, safari asks me if I want to allow this page, and I have to make an extra click to open the page. It is annoying. How do I get rid of this? 316 1

Loading page content

Page content loaded

Jul 23, 2019 9:49 AM in response to RVM007

Jul 24, 2019 5:29 AM in response to RVM007

Just the general Apple Support as far as I know.

Apple Support Contact

Work through the screens to get an email or chat option.

Apple Support by e-mail or chat

Jul 23, 2019 11:20 PM in response to Eric Root

is there any support team for safari ?

IMAGES

  1. Clear the history and cookies from Safari on your iPhone, iPad or iPod

    safari iframe cookies not working

  2. How to Enable and Disable Cookies on Safari (2023)

    safari iframe cookies not working

  3. How to Enable and Disable Cookies on Safari

    safari iframe cookies not working

  4. How to Block Cookies in Safari

    safari iframe cookies not working

  5. Cookies are not working

    safari iframe cookies not working

  6. How To Clear Cookies & Cache In Safari : Information Technology

    safari iframe cookies not working

VIDEO

  1. Working with iFrame, First-Party and Third-Party Cookies

  2. Safari not saving cookies in iPhone : Fix

  3. Same Site Cookie Issue

  4. How to clear Browsing History & Cookies in Safari on Mac OS

  5. How to Manage Cookies in Safari

  6. iFrame Injection Tutorials

COMMENTS

  1. Safari 13+ iframe blocks CORS cookies

    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 ...

  2. javascript

    4. The only workaround that worked for me is redirecting through the iframed domain once. So, if you have abc.com and xyz.com is an iframe under abc.com, while landing to the abc.com, there needs to be an intermediate redirect through xyz.com only for the purpose of setting a blank cookie. Then Safari will allow setting a cookie from iframe for ...

  3. Cannot set cookie in iframe using …

    I did find out that if i set the cookie in first party context first, once storage access is granted i was able to see that cookie and modify it. So probably what would help for you is to first set this cookie in first party context (for example a pop-up, or just the top document), then in third party context (iframe) you will be able to change ...

  4. Safari iframe cookie workaround · GitHub

    Click the link inside the iframe and you'll be greeted with a "Cookie not set!" message. To see the solution, navigate to src.php (without the query string parameter) in the same browser (since the cookie wasn't successfully set, there's no need to set up a new clean Safari instance, though you can if you like).

  5. Third-Party Cookie Restrictions for Iframes in Safari

    This will return false for third-party cookies in the case of the Safari browser. This API is used to ask for third-party storage (cookie) access explicitly from the user. Both of the above APIs are available in Safari as well as in other browsers. Webkit's official documentation explains the steps to use these APIs & the rest of the user flow ...

  6. Cookies and Iframes. If your application runs inside an ...

    Solution. When I bump into this kind of problem I usually appreciate finding a post that offers a solution as fast as possible so here it goes: Set-Cookie: session=your_session; SameSite=None ...

  7. crossdomain

    Send data from one domain to another via an explicit request. In your case, b.com can send a request to a.com, and a.com can do whatever it needs, e.g. set these data to cookies for a.com. Send needed data via Window.postMessage (). Using this method, the IFrame of b.com can send any data to the window of a.com.

  8. iframe not working with safari

    iframe not working with safari. I am using cross domain implementation for which on page of Site A, I load iframe with Site B. Page inside iFrame calls rest apis of Site B and loads other pages from Site B depending upon responses. Although while loading these responses I am getting errror as "Cookies are not turned on in your browser".

  9. 3rd party cookie in iframe workaround

    The configuration for this fix can be done in 2 ways depending on the access rights you have on the remote server. This can all be configured in the administration on the "Advanced Settings" tab -> "Advanced features" at "Safari cookie fix" or with the short code parameter safari_fix_url: Copy a file to the remote server.

  10. Cross-Domain Embedding: Making Third-Party Cookies Work Again

    Basics of making third party cookies work again using an example node.js web host. Even though it can be a bit of work, it's still possible to have third-party cookies work in an embedded cross-domain website that's inside of an iframe. Even with Safari's new restrictions, it can still be accomplished through their new experimental API.

  11. Blog

    First up, let's assume you have an existing and working Cookie popup ready. When a user clicks on I accept to accept the cookies, fire the postMessage to the parent element: window.parent.postMessage( { msg: 'message-content', }, '*', ); This exposes the message to the eventual containers your site is loaded with iframe into.

  12. Setting cookie in iframe that is in different domain

    To set a cookie in an iframe that is in a different domain than the parent site, you can use SameSite=None. ... Safari (incognito apparently) This does not work on: Chrome (incognito) Safari (normal) This is due to the blockage of third party cookies. This is toggle on Chrome incognito that if it's disabled, the cookies will work. ...

  13. Iframe problem on Safari : r/software

    I want to make a cross-domain so I did make an iframe on my index page. Everything is good until I open the website on my iPhone. I did send the link to some friends with safari and they said that they can't open the page on any apple device. I know that safari had a problem and block some cookies from the main domain...

  14. Safari Websocket Connection Problems in iframe

    The reason is the default behaviour of safari, iframes and cookies. It blocks third-party-cookies in iframes. (Prevent Cross-Site Tracking) You can test it by visiting your site, where the broken iframe is included. Then go to safari preferences → privacy and uncheck the "Website-Tracking" checkbox. Your app will work fine afterwards.

  15. How to set server-side cookie to iframe on iphone or ipad?

    This is a well known restriction imposed by Safari's ITP.Namely, you can't just set third party cookies (the cookies of your game). If you want to continue using cookies rather than other storage methods like local storage, you need to ask the user for permission to store the cookies, using the Storage Access API. This blog post gives a nice summary and provides React-based code snippets for ...

  16. ios

    Click on the link and if you see the iframe working, then clear the Safari cache and give it another try. It should theoretically stop working after you flushed the cache. ... The reason for this is because by default Safari does now allow Cross Domain Cookie to be written so if the iFrame src page requires some kind of session or cookie to be ...

  17. LocalStorage not properly work in Iframes

    LocalStorage is not properly work in Iframes (SAFARI) When i'm try to use the LocalStorage in Iframes , it not work fine. Browser (SAFARI) not able identify the domains . so, it create false instance of LocalStorage for same Domain. Example (tab has an iframe of same domain): tab1 - localStorage has some values.

  18. iframe not reading cookies in Chrome

    Visiting the child page in its own window and performing the operation works in all browsers, including Chrome. I've tried both of these options in all permutations: Set secure:false or secure:true for the cookie. Set sandbox="allow-same-origin allow-scripts" for the iframe, or remove the sandbox attribute. What is Chrome doing differently, and ...