7

On our websites we want to make it possible to share sessions accros multiple domains. All these websites are on the same server but some of them have a different IP address.

The possible solution I found was to set the session ID myself:

<?php
session_id($someUniqueHash);
?>

And this works, if I make the hash like md5('test'). On a other domain on te same server we have the session again.

The problem is generating the ID. I see some solutions on the internet with microtime etc, but when I use that approach I can't predict the session ID on the other domain / PHP page.

Does anyone have an idea? Or shouldn't we implement this? Are there other options to share session over multiple domains? (NOT subdomains!)

hakre
  • 193,403
  • 52
  • 435
  • 836
Kees Schepers
  • 2,248
  • 1
  • 20
  • 31
  • 1
    Why don't you let PHP generate the session ID for you? You can share session IDs across domains BTW. That's either a matter of the cookie *or* passing a query parameter. – hakre Jun 22 '12 at 11:37
  • The query param is not prefered, it's insecure and not url friendly. As far as I know you only allow cookies accros the same domain (subdomains as well) not multidomains. – Kees Schepers Jun 22 '12 at 11:41
  • It's just a cookie you pass. And you can make cookies for third-party domains, so called third-party-cookies. You might need to also check the legal side for doing this (next to the technical side which is solved). Btw all technical details you might want to learn about: [HTTP State Management Mechanism RFC6265](http://tools.ietf.org/html/rfc6265) – hakre Jun 22 '12 at 11:43
  • Tnx, Hakre. Didn't knew that yet. I will investigate your options and will respond here. – Kees Schepers Jun 22 '12 at 11:48

5 Answers5

5

I've achieved this system by using an OAuth type flow but we replaced the Consumer with the User.

So each domain would have the authenticated Access_Token in its own session. You would then use that Access_Token to get information about user from an api.

I also solved the session problem using session_set_save_handler and storing sessions in a database table... This table would have the Access_Token also, making it really easy to find the session with a DB Query.

Hope this helps with ideas.

Lex
  • 468
  • 7
  • 14
  • I've been thinking of doing this lately. I wonder if there is any case study or simple discussion on the storage and retrieval performance by adding the access token into a db table and querying it every request. – Tom Pace Feb 01 '13 at 09:57
0

Hmm this is a difficult one.

As everyone knows PHP uses cookies to understand session_ids when a user comes back to your site and there is no way of cross domain cookies: Cross domain cookies (edit: there is but the method is complicated).

This is probably why I have never seen a site implement this even though they have different domains.

You could, via a link on your page from one domain pass the session id to the next domain through $_GET or $_POST. This will not work if the user directly enters your other site.

The only partially (no reliable) method I can come up with is to keep a record of the users comptuer in the DB and use that to understand what session is attached it to. So you house the computers IP address and maybe some other details and that backs onto a session.

The IP and other details of a persons computer would log them into the other domain.

Community
  • 1
  • 1
Sammaye
  • 43,242
  • 7
  • 104
  • 146
  • Tnx. There is a website who does it: http://www.laptopshop.nl for example. I know their website is developed in PHP, so it's possible. But I was afraid is was hard. – Kees Schepers Jun 22 '12 at 11:44
  • I do correct my answer cross domain cookies are possible but solid as mentined in that post, but yea cross domain sessions are really unreliable... – Sammaye Jun 22 '12 at 11:51
0

Maybe this is not an option for you, but you could try this.

On your main site you generate the session id as per normal and to perpetuate the session to another domain you could include image tags with the session id in the URL. In response, the other domain will set a cookie, so that when the visitor comes there it will already know the session id.

Feels a bit smarty pants solution, but it should work if you don't have too many other domains :) third party cookies can be disabled separately in browsers btw, something to consider.

Oh btw, session adoption (accepting an id via query parameters and setting a cookie) is delicate stuff and should be protected, i.e. session must already exist before setting cookie.

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
0

Configure each site individually:

<?php

$cfgsession['file'] = "../sessions_global.txt";
$cfgsession['keepalive'] = 7200;

?>

To make multiple sites share sessions, let them use the same $cfgsession['file']. Include a session from one site in a request to another domain (perhaps as recommended by Jack), and as long as you don't catch them making their request in another browser or whatever (please do something to inhibit session hijacking), let them specify a session with $_GET. For example:

include ("../session.php");
if (isset($_COOKIE['session'])) session_begin($_COOKIE['session'], $_SERVER['HTTP_USER_AGENT'] . "+" . $_SERVER['HTTP_ACCEPT_CHARSET'], $_SERVER['REMOTE_ADDR']);
else session_begin("", $_SERVER['HTTP_USER_AGENT'] . "+" . $_SERVER['HTTP_ACCEPT_CHARSET'], $_SERVER['REMOTE_ADDR']);
setcookie("session", session_identity(), 0);

And then just roll your own session_ functions:

<?php

function session_begin($mysession = "", $key = "", $client = "") {
  global $cfgsession;
  if (!preg_match("/^[a-z0-9]{32}$/i", $mysession)) $mysession = md5(microtime());
  $error = false;
  $client = trim($client);
  $key = trim($key);
  $cfgsession['returning'] = false;
  if ($chandle = @tmpfile()) {
    if ($shandle = @fopen($cfgsession['file'], "rb")) {
      flock($shandle, LOCK_SH);
      fputs($chandle, $mysession . " " . time() . " $" . $client . " $" . $key . "\n");
      while (!feof($shandle)) {
        $sline = explode(" ", trim(fgets($shandle)), 4);
        if ($sline[1] >= (time() - $cfgsession['keepalive'])) {
          if (($sline[0] == $mysession) && ($sline[3] == "$" . $key)) {
            $cfgsession['client'] = substr($sline[2], 1);
            $cfgsession['returning'] = true;
          } elseif (count($sline) > 2) fputs($chandle, implode(" ", $sline) . "\n");
        }
      }
      fclose($shandle);
      fseek($chandle, 0);
      if ($shandle = @fopen($cfgsession['file'], "cb")) {
        if (flock($shandle, LOCK_EX)) {
          ftruncate($shandle, 0);
          $cfgsession['count'] = 0;
          while (!feof($chandle)) {
            $cline = trim(fgets($chandle));
            fputs($shandle, $cline . "\n");
            $cfgsession['count']++;
          }
        } else $error = true;
        fclose($shandle);
      } else $error = true;
    } else $error = true;
    fclose($chandle);
  } else $error = true;
  if (($cfgsession['returning'] == false) && ($mysession == $cfgsession['session'])) {
    $cfgsession['returning'] = true;
    $mysession = md5(microtime());
  }
  $cfgsession['session'] = $mysession;

  if ($error) return -1;
  else return 0;
}

function session_count() {
  global $cfgsession;
  return $cfgsession['count'];
}

function session_client() {
  global $cfgsession;
  return $cfgsession['client'];
}

function session_id() {
  global $cfgsession;
  return $cfgsession['session'];
}

function session_index() {
  global $cfgsession;
  $index_return = array();
  if ($uhandle = @fopen($cfgsession['file'], "rb")) {
    flock($uhandle, LOCK_SH);
    while (!feof($uhandle)) {
      $uline = explode(" ", trim(fgets($uhandle)), 4);
      foreach ($uline as &$value) {
        if ($value[0] == "$") $value = substr($value, 1);
      }
      if (count($uline) >= 2) $index_return[] = $uline;
    }
    fclose($uhandle);
  }
  return $index_return;
}

function session_returning() {
  global $cfgsession;
  return $cfgsession['returning'];
}

?>
dogglebones
  • 387
  • 1
  • 8
0

If these are login sessions, consider using a single sign on (SSO) solution such as those that implement the SAML standard.

Derrick Miller
  • 1,860
  • 3
  • 21
  • 37