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.
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 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.
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.
This issue was discovered, and its solution devised, while working on Parking Mobility (https://parkingmobility.com).
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.