PHP Sessions across sub domains

PhpAuthenticationSessionCross Domain

Php Problem Overview


I am trying to set up the following:

auth.example.com
sub1.example.com
sub2.example.com

If the user visits sub1.example.com or sub2.example.com and they are not logged in, they get redirected over to auth.example.com and can log in.

sub1.example.com and sub2.example.com are two separate applications but use the same credentials.

I tried setting the following in my php.ini:

session.cookie_domain = ".example.com"

but it doesn't seem to be passing the information from one domain to the other.

[Edit]

I tried the following:

sub1.example.com/test.php

session_set_cookie_params(0, '/', '.example.com');
session_start();
print session_id() . "<br>";
$_SESSION['Regsitered'] = 1;
echo '<a href="http://auth.example.com/test.php">Change Sites</a>'

auth.example.com/test.php

session_set_cookie_params(0, '/', '.example.com');
session_start();
print session_id() . "<br>";
$_SESSION['Checked'] = 1;
print_r($_SESSION);

The session IDs are exactly the same but when I dump out the $_SESSION variable it doesn't show both keys, just whatever key I set under each domain.

Php Solutions


Solution 1 - Php

I do not know if the problem still exists, but I just ran into the same problem and solved it setting a session name before calling session_set_cookie_params():

$some_name = session_name("some_name");
session_set_cookie_params(0, '/', '.example.com');
session_start();

I have changed nothing in my php.ini but now everything is working fine.

Solution 2 - Php

One thing which can mysteriously prevent session data being read on a subdomain, despite cookies being correctly set to .example.com is the PHP Suhosin patch. You can have everything configured correctly, as per the examples in the question, and it can just not work.

Turn the following Suhosin session settings off, and you're back in business:

suhosin.session.cryptua = Off 
suhosin.session.cryptdocroot = Off

Solution 3 - Php

Try using:

session.cookie_domain = "example.com"

Instead of:

session.cookie_domain = ".example.com"

Note the missing period at beginning.

Be careful using this, though, because it is not supported by all browsers.

Solution 4 - Php

Had this exact problem - I wanted session values created on x.example.local to be available on example.local and vice-versa.

All solutions I found said to change the Session domain by using php_value session.cookie_domain .example.local in .htaccess (or via php.ini or via ini_set).

The catch was I was setting the session.cookie_domain for all subdomains (so far ok) but also for the main domain. Setting the session.cookie_domain on the main domain is apparently a no-no.

Basically the way it worked for me:

  • set the session.cookie_domain for ALL SUBDOMAINS.
  • don't set it for the main DOMAIN

Oh yes, please make sure the domain has a TLD (in my case .local). Http protocol doesn't allow cookies/sessions to be stored on a domain without .tld (ie localhost won't work, but stuff.localhost will).

EDIT: Also make sure you always clear your browser cookies while testing/debugging sessions across subdomains. If you don't, your browser will always send the old session cookie which probably doesn't have the correct cookie_domain set yet. The server will revive the old session and therefore you'll get false negative results. (in many posts it's mentioned to use session_name('stuff') for the exact same effect)

Solution 5 - Php

I solved it like this

ini_set('session.cookie_domain', '.testdomain.example');
session_start();

Because I was working on localhost

ini_set('session.cookie_domain', '.localhost');

wasn't working, it sees .localhost as the toplevel instead of .com/.local/... (I suspect)

Solution 6 - Php

I have confirmed. joreon's answer is correct. I cannot comment because my reputation is not enough so I post my comment here.

Define the constant in a config file. If you want to change it, no need to modify whole files.

define('ROOT_DOMAIN',	'mysite.example');
define('PHP_SESSION_NAME', 'MYSITE'); 

The session name can't consist of digits only, at least one letter must be present. Otherwise, a new session id is generated every time.

Use the following code to start using session

session_name(PHP_SESSION_NAME);
session_set_cookie_params(0, '/', '.' . ROOT_DOMAIN);
session_start();

I'm using this function:

function load_session() {
    if (session_status() == PHP_SESSION_NONE) {
        session_name(PHP_SESSION_NAME);
        session_set_cookie_params(0, '/', '.' . ROOT_DOMAIN);
        session_start();
    } elseif (session_name() != PHP_SESSION_NAME) {
        session_destroy();
        session_name(PHP_SESSION_NAME);
        session_set_cookie_params(0, '/', '.' . ROOT_DOMAIN);
        session_start();
    }
}
load_session(); // put it in anywhere you want to use session

Solution 7 - Php

Use it on every domain/subdomain:

session_name('name');
ini_set('session.cookie_domain', '.example.com');
ini_set('session.save_path', '/var/lib/php/session');
session_start();

Path for session.save_path can be different for your case but it should be the same on every domain/subdomain. It is not always true by default.

Solution 8 - Php

Use this , it works:

ini_set('session.cookie_domain', 
    substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));

Solution 9 - Php

Sub domain and root domain Cookie Sessions Combined Use

Resource: http://php.net//manual/tr/function.session-set-cookie-params.php

I've tested works

sub.example.com/sessionadd.php?id=123

example.com/sessionview.php // 123

-- Codes

<?php 
$currentCookieParams = session_get_cookie_params(); 

$rootDomain = '.example.com'; 

session_set_cookie_params( 
    $currentCookieParams["lifetime"], 
    $currentCookieParams["path"], 
    $rootDomain, 
    $currentCookieParams["secure"], 
    $currentCookieParams["httponly"] 
); 

session_name('mysessionname'); 
session_start(); 

setcookie($cookieName, $cookieValue, time() + 3600, '/', $rootDomain); 
?>

Solution 10 - Php

I get the idea that you don't want something like OpenID, like Joel is suggesting, but that you want to have access to the session data across multiple domains.

The only possibility that I can think of as a solution for that problem is to store the sessiondata in a database, and pull it out of that database.

Solution 11 - Php

I know this is old but this works fine for me with multiple domains and sub domains on the same box.

<?php
define('site_domain','example.com');
session_set_save_handler('_open',
                         '_close',
                         '_read',
                         '_write',
                         '_destroy',
                         '_clean');
						 
function _open(){
	
	global $_sess_db;

$db_user = 'user';
$db_pass = 'pass';
$db_host = 'localhost';

if ($_sess_db = mysql_connect($db_host, $db_user, $db_pass)){
	
    return mysql_select_db('database', $_sess_db);
	
}

return false;

}

function _close(){
	
	global $_sess_db;
	return mysql_close($_sess_db);
	
}

function _read($id){
	
	global $_sess_db;
	$id = mysql_real_escape_string($id);
	$domain = mysql_real_escape_string(site_domain);
	$agent = mysql_real_escape_string(isset($_SERVER['HTTP_USER_AGENT']));
	
	$sql = "SELECT data
	FROM sessions
	WHERE id = '$id' AND domain = '$domain' AND agent = '$agent'";
	
	 if ($result = mysql_query($sql, $_sess_db)){
		 
		 if (mysql_num_rows($result)){
			 $record = mysql_fetch_assoc($result);
			 return $record['data'];
		}
	
	}
	
	return '';
	
}

function _write($id, $data){
	
	global $_sess_db;
	$access = time();
	
	$id = mysql_real_escape_string($id);
	$access = mysql_real_escape_string($access);
	$data = mysql_real_escape_string($data);
	$domain = mysql_real_escape_string(site_domain);
	$agent = mysql_real_escape_string(isset($_SERVER['HTTP_USER_AGENT']));
	
	$sql = "REPLACE INTO sessions
	VALUES ('$id', '$access', '$data', '$domain', '$agent')";
	
	return mysql_query($sql, $_sess_db);
	
}

function _destroy($id){
	
	global $_sess_db;
	$id = mysql_real_escape_string($id);
	$domain = mysql_real_escape_string(site_domain);
	$agent = mysql_real_escape_string(isset($_SERVER['HTTP_USER_AGENT']));
	
	$sql = "DELETE FROM sessions
	WHERE id = '$id' AND domain = '$domain' AND agent = '$agent'";
	
	return mysql_query($sql, $_sess_db);
	
}

function _clean($max){
	
	global $_sess_db;
	$old = time() - $max;
	$old = mysql_real_escape_string($old);
	$domain = mysql_real_escape_string(site_domain);
	$agent = mysql_real_escape_string(isset($_SERVER['HTTP_USER_AGENT']));
	
	$sql = "DELETE FROM sessions
	WHERE  access < '$old' AND domain = '$domain' AND agent = '$agent'";
	
	return mysql_query($sql, $_sess_db);
	
}

?>

Solution 12 - Php

I have read all answers above, I think my answer is helpful for people googling this:

  • make sure the browsers send session cookie back to servers (of domain and sub-domains), set session cookie domain as .example.com.

  • Make sure PHP find the right "target" to restore the session variable:

  • If domain and subdomains point to the same machine (maybe different virtual hosts), make sure session_save_path is the same for all (I tested)
  • If domain and subdomains point to different machines, the common storage (like database) is best for saving and restoring session data (I didn't test yet). Use session_set_save_handler to do that.

Solution 13 - Php

Simply try using following code just above session_start() method

$sess_life_time = 21600; //in seconds
$sess_path = "/";
$sess_domain = ".example.com";
$sess_secure = true; // if you have secured session
$sess_httponly = true; // httponly flag

session_set_cookie_params($sess_life_time, $sess_path, $sess_domain, $sess_secure, $sess_httponly);

Solution 14 - Php

I had a similar problem, however, this solution was good for me, perhaps will help others in the future

edit the php.ini

> session.cookie_domain = ".example.com"

the magic is here

suhosin.session.cryptdocroot = Off

suhosin.cookie.cryptdocroot = Off

https://www.sitepoint.com/community/t/sessions-across-subdomains-domain-com-phpsessid-changes/3013/19

Solution 15 - Php

I can't speak for other versions of PHP, but in 5.6.6, simply setting the session.cookie_domain value in the php.ini file did the trick to allow all of my subdomains on iPage to share the same set of session variables.

Be sure to remove any existing cookies related to your domain from your browser to test.

session.cookie_domain = '.yourdomainname.example'

Oh, don't know if it makes any difference but I'm also using session autostart.

session.auto_start = 1

Solution 16 - Php

Use :

session_name("put_a_session_name");
session_start([
  "cookie_domain" => ".example.com",
  "cookie_path" => "/"
]);

Solution 17 - Php

A quick and dirty solution is to use this for your redirect:

header( $url.'?'.session_name().'='.session_id() );

this will add something along the lines of ?PHPSESSID=etnm7kbuf5lg0r6tv7je6ehtn4 to the URL, which tells PHP the session id it should use.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondragonmantankView Question on Stackoverflow
Solution 1 - PhpjeroenView Answer on Stackoverflow
Solution 2 - PhpdrewmView Answer on Stackoverflow
Solution 3 - PhpGeorge ClaghornView Answer on Stackoverflow
Solution 4 - PhpValentin FloreaView Answer on Stackoverflow
Solution 5 - PhpxtdsView Answer on Stackoverflow
Solution 6 - PhpTerry LinView Answer on Stackoverflow
Solution 7 - Phptellnobody1View Answer on Stackoverflow
Solution 8 - PhpIvanView Answer on Stackoverflow
Solution 9 - PhpLimitless isaView Answer on Stackoverflow
Solution 10 - PhpThomasView Answer on Stackoverflow
Solution 11 - PhpIanView Answer on Stackoverflow
Solution 12 - Phpuser953985View Answer on Stackoverflow
Solution 13 - Phpmohsin.mrView Answer on Stackoverflow
Solution 14 - PhpWillian SantanaView Answer on Stackoverflow
Solution 15 - Phpuser3232196View Answer on Stackoverflow
Solution 16 - PhpShakil AhmmedView Answer on Stackoverflow
Solution 17 - PhpsakabakoView Answer on Stackoverflow