Secure and flexible cross-domain sessions

I have a problem that I hope you can help. Let's say I work for a hypothetical company called Blammo, and we have a hypothetical product called Magazine. I am trying to create a system where someone can log in to logfromblammo.com and order some of our products, and then, when they are ready to buy, go to checkout.blammo.com to pay for their order. In the end, I want Blammo to launch a new hypothetical product with its own website: rockfromblammo.com, and this site can also share a session with checkout.blammo.com so that users can have one shopping cart for both website products.

Naturally, the hypothetical scenario described above is not how my company works, but it is a great 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 seamlessly switch from one site to another without re-authentication. It would also allow us to freely transfer data, for example, a shopping cart to the checkout site.

I (briefly) looked at solutions such as OpenID, but I need to be able to integrate any solution available in our existing authentication method that is not terribly reliable. Is there a good way to do this with PHP only?

+6
source share
5 answers

What you can do is create cross-links between sites to transfer the session.

The easiest way is to pass the session ID through the query string; eg.

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

Before you start to think that someone can lure this information, think about how your cookies are transferred; assuming you are not using SSL, there is not much difference for those who use the network.

This does not mean that it is safe; firstly, users can accidentally copy / paste the address bar and thereby test the session. To limit this impact, you can immediately redirect to a page without a session identifier after receiving it.

Please note that using mcrypt() in the session identifier will not help, because it is not the visibility of the value, which is the problem; session capture does not care about the base value, only its reproducibility of the URL.

You must ensure that the identifier can only be used once; this can be done by creating a session variable that tracks the usage score:

 $_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); 

Upon receipt:

 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 you cross the border because the session may have been restored since the last time.

+7
source

This can be done, but not with the help of simple cookies, and it is not trivial. What you need is a single sign-on (SSO) solution, similar to Google, which shares login via i.google.com, gmail.com, youtube.com, etc.

I have used OpenID to implement this in the past.

The main idea is to have a single authentication domain (Provider), when one of the sites (Consumer) wants to authenticate the user, they redirect them to the authentication domain. If they are not logged in, they can log in using any necessary information.

If they are already logged in (even from another target site), they do not need to log in again.

Then the user is sent back to the target site with the addition of a token in the URL. This token is used by the target site server to authenticate the user using the authentication server.

This is a very simple explanation. Doing this is not difficult, making it much safer . The details of creating and authenticating tokens securely is a tricky part. That is why I suggest using a well-designed system such as OpenID.

+3
source

You need to set the session cookie domain as follows:

 session_set_cookie_params($lifetime,$path,'.site.com') 

This will only work if the sites are on the same domain name, including TLD (top-level domain).

See here for more information.

Alternatively, if you are trying to access cross-domain sessions, for example, from site1.net to site2.com , this is not possible.

+1
source

If it is ok for your site to rely on Javascript to work, you could supposedly do something like the following:

Say you have a session on blammo.com and you want to access it from rockblammo.com. On rockblammo.com you can download <script> from blammo.com/get-session.js , this will (from the server side) return the session identifier. After that, you will enter a new <script> on the page, pointing to rockblammo.com/set-session.js?sessionId=XXX , where XXX is the session identifier you just received from blammo.com. Now, on the server side of rockblammo.com, the session cookie is updated and set to this session ID. In the future, both pages will have the same session identifier and, assuming that they have access to the same session repository on the server, they will be synchronized.

eg. the output from blammo.com/get-session.js will be as follows:

 var sessionId = "XXX"; var s = document.createElement("script"); s.src = "/set-session.js?sessionId=" + escape(sessionId); document.body.appendChild(s); 

The output from rockblammo.com/set-session.js will be empty, but will include the http header, for example:

 Set-Cookie: sessionId=XXX 

If you prefer not to rely on Javascript, you can probably do the same by redirecting back and forth between the two sites and passing sessionId in the query string parameter (GET parameter).

0
source

In the Ajax cross-domain, you may find that the cookie and, accordingly, the session are lost for cross-domain requests. If you make ajax calls from your example.com website to your s2.example.com subdomain, you will need to use the properties in the headers for PHP:

 header('Access-Control-Allow-Origin: https://example.com'); header('Access-Control-Allow-Credentials: true'); 

and in js you are going to add

 xhrFields: { withCredentials: true } 

Otherwise, cookies are not transmitted and you cannot use the session in your subdomain.

A full JS request for a subdomain will be without a lost session :

 $.ajax({ url: "https://s2.example.com/api.php?foo=1&bar=2", xhrFields: { withCredentials: true }, success:function(e){ jsn=$.parseJSON(e); if(jsn.status=="success") { alert('OK!'); } else { alert('Error!'); } } }) 
0
source

All Articles