Let me combine what you requested in comments:
I have a .js file hosted on domain1 ... I want to have a single js file and I can't put PHP into that ... the whole purpose of this is for domain1 to not have any php code or php file. ... The reason is because I want it cross-domain and the session to be created from domain2.
It sounds like your issue might be related to the Safari iFrame session cookie problem, especially because you have if (!isset($_SESSION['isIFrameSessionStarted']))
in one of your code blocks. I will continue with this assumption.
Summary of the problem for other readers:
Upon embeding an IFrame from one domain into a website of a different domain, you will quickly realise that Internet Explorer and Safari are blocking the cookies (and thus the session variables) of the website inside the IFrame (ref).
Attempted solutions that didn't pan out:
My solution:
Essentially, PHP session "hijacking". It works surprisingly well where the above solutions failed. This is the essential solution. Please do any security enhancements* and URL-prettifying you like. Basically, we retrieve the PHP session ID through redirects and pass this to the iframe. Instructions are in the comments.
In your domainA.com head place this:
<script src="session.js"></script>
session.js (on domainA.com):
// Location of the domain B session starter
var sessionScriptURL = "http://domainB.com/start-session.php";
var refQSparam = "phpsessionid";
// Check if we have the phpsessionid in the query string
var phpsessionid = getParameterByName(refQSparam);
if(phpsessionid === null) {
// Not in the query string, so check if we have it in session storage
var sessionStore = sessionStorage.getItem(refQSparam);
if(sessionStore === null) {
// We have no session storage of the PHP session ID either, redirect to get it
top.location = sessionScriptURL + "?redirect=" + encodeURIComponent(self.location.href);
} else {
// phpsessionid was found in session storage. Retrive it
phpsessionid = sessionStore;
}
} else {
// Save the phpsessionid to session storage for browser refresh
sessionStorage.setItem(refQSparam, phpsessionid);
// Optional: Redirect again to remove the extra query string data
}
// Helper to get QS values
function getParameterByName(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null;
}
session-starter.php (on domainB.com):
<?php
session_start(); // create the session cookie
$redirect = rawurldecode($_GET['redirect']);
// redirect back with the php session ID
// Optional: encode this information
$href = $redirect . '?phpsessionid=' . session_id();
header('Location: ' . $href);
exit;
HTML (in the body, on domainA.com):
Append PHP session information to the iframe src.
<script>
document.write('<iframe src="http://domainB.com/embedded-script.php?phpsessionid='+phpsessionid+'"></iframe>');
</script>
embedded-script.php (on domainB.com, in an iframe):
<?php
// Use the phpsessionid passed in
$phpsessionid = rawurldecode($_GET['phpsessionid']);
// REF: http://php.net/manual/en/function.session-id.php
function session_valid_id($session_id) {
return preg_match('/^[-,a-zA-Z0-9]{1,128}$/', $session_id) > 0;
}
// Check that this is potentially a valid session ID
if(session_valid_id($phpsessionid)) {
// Set the session to the one obtained in session-start.php
session_id($phpsessionid);
}
session_start(); // Only call this after session_id()!
// Rest of your code
*Considerations:
Don't actually use document.write
, use jQuery or document selectors.
Encode the PHP session ID
Perform another redirect back to the base URL of domainA.com to remove the ?phpsessionid=
in the URL for a cleaner look.
If you decide to call session-starter.php
with AJAX instead, you will get a new PHP session ID every time for the same reason. The iframe will successfully use this session ID, but if you open a new page to domainB.com, the session will yet again be different.