Viewed   91 times

I am having an issue that I hope you can help with. Let's say I work for a hypothetical company called "Blammo", and we have a hypothetical product called "Log". I am trying to set up a system where someone could log in to logfromblammo.com and order some of our products, and then when they are ready to purchase go to checkout.blammo.com to pay for their order. Eventually I want to allow for Blammo to launch a new hypothetical product with it's own website: rockfromblammo.com, and have that site also able to share a session with checkout.blammo.com so that users can have a single shopping cart across both product websites.

Naturally the hypothetical scenario described above is not how my company actually works, but it is a fair example of what I need to do. We have an existing user database, and we have ways to authenticate any of our users on any of our sites, but the goal I have is to allow users to cross seamlessly from one site to another without having to re-authenticate. This would also allow for us to seamlessly transfer data such as a shopping cart to the checkout site.

I have (briefly) looked at solutions such as OpenID, but I need to be able to integrate whatever solution we have with our existing authentication method, which is not terribly robust. Is there any good way to do this through PHP alone?

 Answers

4

What you could do is create "cross-over" links between the sites to carry the session over.

The simplest way is to pass the session id via the query string; e.g.

http://whateverblammo.com/?sessid=XXYYZZ

Before you start thinking that anyone can trap that information, think about how your cookies are transferred; assuming you're not using SSL, there's not much difference for someone who taps the network.

That doesn't mean it's safe; for one, users could accidentally copy/paste the address bar and thus leaking out their session. To limit this exposure, you could immediately redirect to a page without the session id after receiving it.

Note that using mcrypt() on the session id won't help much, because it's not the visibility of the value that's the problem; session hijacking doesn't care about the underlying value, only its reproducibility of the url.

You have to make sure the id can be used only once; this can be done by creating a session variable that keeps track of the use count:

$_SESSION['extids'] = array();

$ext = md5(uniqid(mt_rand(), true)); // just a semi random diddy
$_SESSION['extids'][$ext] = 1;

$link = 'http://othersite/?' . http_build_query('sessid' => session_id() . '-' . $ext);

When received:

list($sid, $ext) = explode('-', $_GET['sessid']);
session_id($sid);
session_start();
if (isset($_SESSION['extids'][$ext])) {
    // okay, make sure it can't be used again
    unset($_SESSION['extids'][$ext]);
}

You need these links every time a boundary is crossed, because the session may have gotten regenerated since the last time.

Thursday, August 11, 2022
2

Do it the other way around. Track the state of the child popup window from the main (opener) window, and you could easily know when the child window has been navigated back to you domain, so you could "talk" to it again. But don't close the child window by itself. Let the opener window obtain the result from the child window and then close it.

For example, main.html:

<!DOCTYPE html>
<head>
<title>main</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<script>
window.addEventListener("message", function(ev) {
    if (ev.data.message === "deliverResult") {
        alert("result: " + ev.data.result);
        ev.source.close();
    }
});
        
function Go() {
    var child = window.open("child.html", "_blank", "height=200,width=200");
        
    var leftDomain = false;
    var interval = setInterval(function() {
        try {
            if (child.document.domain === document.domain) {
                if (leftDomain && child.document.readyState === "complete") {
                    // we're here when the child window returned to our domain
                    clearInterval(interval);
                    alert("returned: " + child.document.URL);
                    child.postMessage({ message: "requestResult" }, "*");
                }
            }
            else {
                // this code should never be reached, 
                // as the x-site security check throws
                // but just in case
                leftDomain = true;
            }
        }
        catch(e) {
            // we're here when the child window has been navigated away or closed
            if (child.closed) {
                clearInterval(interval);
                alert("closed");
                return; 
            }
            // navigated to another domain  
            leftDomain = true;
        }
    }, 500);
}
</script>
</head>
<body>
<button onclick="Go()">Go</button>
</body>

child.html:

<!DOCTYPE html>
<head>
<title>child</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<script>
window.addEventListener("message", function(ev) {
    if (ev.data.message === "requestResult") {
        // ev.source is the opener
        ev.source.postMessage({ message: "deliverResult", result: true }, "*");
    }   
});
</script>
</head>
<body>
<a href="http://www.example.com">Go to example.com</a>
Then click the browser Back button when ready.
</body>

Tested with IE10.

Wednesday, November 9, 2022
 
5

Test Results: Bad News, it appears to only work in Chrome. All other browsers (including Android Mobile) give an error like this:

Failed: DOM Exception: SECURITY_ERR (18)

Mobile Devices I tested Android (samsung galaxy kernel version 2.6.32.9), Iphone and IPAD V1 and it failed in all three.

You can test your own mobile device with this URL: http://maplarge.com/CrossOriginImageTest.html

The Test Script:

  <!DOCTYPE html>
<html>
<head>
<title>Canvas Cross Origin Image Test: Testing for Canvas Cross Domain Image CORS Support</title>
<script type="text/javascript">
    function initialize() {

        //will fail here if no canvas support
        try {
            var can = document.getElementById('mycanvas');
            var ctx = can.getContext('2d');
            var img = new Image();
            img.crossOrigin = '';
            //domain needs to be different from html page domain to test cross origin security
            img.src = 'http://lobbydata.com/Content/images/bg_price2.gif';
        } catch (ex) {
            document.getElementById("results").innerHTML = "<span style='color:Red;'>Failed: " + ex.Message + "</span>";
        }

        //will fail here if security error
        img.onload = function () {
            try {
                var start = new Date().getTime();
                can.width = img.width;
                can.height = img.height;
                ctx.drawImage(img, 0, 0, img.width, img.height);
                var url = can.toDataURL(); // if read succeeds, canvas isn't dirty.
                //get pixels
                var imgd = ctx.getImageData(0, 0, img.width, img.width);
                var pix = imgd.data;
                var len = pix.length;
                var argb = []; //pixels as int
                for (var i = 0; i < len; i += 4) {
                    argb.push((pix[i + 3] << 24) + (pix[i] << 16) + (pix[i + 1] << 8) + pix[i + 2]);
                }
                var end = new Date().getTime();
                var time = end - start;
                document.getElementById("results").innerHTML = "<span style='color:Green;'>" +
                "Success: Your browser supports CORS for cross domain images in Canvas <br>"+
                "Read " + argb.length+ " pixels in "+ time+"ms</span>";
            } catch (ex) {
                document.getElementById("results").innerHTML = "<span style='color:Red;'>Failed: " + ex + "</span>";
            }

        }

    }
</script>
</head>
<body onload="initialize()">
<h2>Canvas Cross Origin Image Test: Testing for Canvas Cross Domain Image CORS Support</h2>
<h2><a href="http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html">What is CORS Image Security?</a></h2>
<h1 id="results" style="color:Orange;">Testing...</h1>
<canvas id="mycanvas"></canvas>
<br />
<a href="/Example/List">More Examples</a>
</body>
</html>
Wednesday, November 23, 2022
 
2

This is the code I ended up using, thanks to yahelc for the help.

$('.link-btn').bind("cbox_complete", function(){
    var pageTracker = _gat._getTrackerByName();
    var href = $.colorbox.element().attr('href');
    if (href) {
        _gaq.push(function() {
          var pageTracker = _gat._getTrackerByName();
            setTimeout(function(){
                $('#cboxLoadedContent iframe').attr('src',pageTracker._getLinkerUrl(href));
            },1000);
        });
    }
});    
Monday, December 26, 2022
 
adheus
 
2

Oops I figure out the problem, I have setup wrong url for white listing.

res.setHeader('Access-Control-Allow-Origin', 'http://192.168.20.62');

I have to whitelist the source URL which was generating cross domain, this was the only change have to do to make thing running.

Also this has browser version impact, when I have posted this issue, I was checking with firefox version 24.0.* and when I upgrade 25.0 it has stopped generating cross domain error surprisingly. But still Chrome giving natural cross domain error, when I read error message of chrome carefully I come to know that I have whitelisted wrong url.

XMLHttpRequest cannot load http://192.168.20.62:9847/page. The 'Access-Control-Allow-Origin' whitelists only 'http://192.168.20.62:9847'. Origin 'http://192.168.20.62' is not in the list, and is therefore not allowed access.

Tuesday, December 20, 2022
 
cmw
 
cmw
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :