9

I have one main domain: main.com, subdomains: test1.main.com, test2.main.com and other domains one.com, two.com.

Now it's done like these:

ini_set("session.cookie_domain", ".main.com");

$domain = 'main.com';

login.php

$user = $db->query("SELECT id, login FROM users WHERE email=? AND password=?", 
array($email, $password), "rowassoc");

if($user)
{
  $_SESSION['user_id'] = $user['id'];
  $_SESSION['user_name'] = $user['login'];

  $time = 100000; 

  setcookie('email', $email, time() + $time, "/", "." . $domain);
  setcookie('password', $password, time() + $time, "/", "." . $domain);

  header('Location: http://' . $user['login'] . "." . $domain);
  exit;
}

added on each page:

if(!isset($_SESSION['user_id']))
{
  if(isset($_COOKIE['email']) && isset($_COOKIE['password']))
  {
    $email = $_COOKIE['email'];
    $password = $_COOKIE['password'];

    $user = $db->query("SELECT id, login FROM users WHERE email=? AND password=?",
    array($email, $password), "rowassoc");

    if($user)
    {
      $_SESSION['user_id'] = $user['id'];
      $_SESSION['user_name'] = $user['login'];
    }
  }
}
else
{
  $user = $db->query("SELECT id, login FROM users WHERE id=?", 
  array($_SESSION['user_id']), "rowassoc");


  if(!$user)
  {
    setcookie('email', '', time() , "/", "." . $domain);
    setcookie('password', '', time() , "/", "." . $domain);
    unset($_SESSION['user_id']);

    session_destroy();
    setcookie("PHPSESSID","",time(), "/", "." . $domain);
  }
  else
  {
    $_SESSION['user_id'] = $user['id'];
    $_SESSION['user_name'] = $user['login'];
  }
}

logout.php

if(isset($_SESSION['user_id']))
{
  setcookie('email', '', time() , "/", "." . $domain);
  setcookie('password', '', time() , "/", "." . $domain);
  unset($_SESSION['user_id']);
  unset($_SESSION['user_name']);

  session_destroy();
  setcookie("PHPSESSID","",time(), "/", "." . $domain);

  header('Location: /main');
  exit;
}

But it works only on domain main.com and its subdomains test1.main.com, test2.main.com.

I need to somehow save the session and on other domains one.com, two.com.

How best to do safe authentication, if there are solutions, i really confused, please tell with example.

jb.
  • 23,300
  • 18
  • 98
  • 136
swamprunner7
  • 1,321
  • 6
  • 16
  • 25
  • We need **way** more details on what you're trying to accomplish. What does authentication have to do with the different domains? Please edit your question to add more specifics. – webbiedave Nov 03 '10 at 21:38
  • Duplicate of http://stackoverflow.com/questions/244008/how-do-i-maintain-php-sessions-across-multiple-domains-on-the-same-server – Brad Nov 03 '10 at 22:26
  • 1
    Whoa! Do not ever store passwords in a cookie, nor DB table. Passwords should be stored hashed by the PHPass library. – Steve Clay Nov 04 '10 at 16:25
  • I have already corrected the issue in another – swamprunner7 Nov 04 '10 at 20:05
  • Ajax/JS and iframe solution proposed here: https://stackoverflow.com/q/4813498/1066234 Check also this example here: https://github.com/0k/multidomain-sso – Avatar Aug 21 '17 at 21:50

3 Answers3

12

As far as I know, crossing sessions between sub-domains is fine, but it won't carry over to a whole new domain. To do that you need some sort of centralized data method, or an API.

Database method: you will have to create a remote MySQL data access so that domain2.com can access the database on domain1.com. When a log-in is performed, not only should it create a new session, but a unique log-in token (with an expiry time) should be put into the mysql database. Now, for every link that goes from domain1.com to domain2.com, you should add a $_GET variable that contains a randomly generated session id (md5 hash will do). domain2.com, upon receiving the visitor, will take the $_GET variable, run it through the MySQL database to find the login token, and if there is a match, consider that user to be logged on (and perhaps embed a $_COOKIE as well to store the login data). This will make the log-in transferrable between two completely different domains.

API method: you need to create an API method, so that domain1.com can respond to an external request from authorized domains to retrieve the login token upon a user being forwarded. This method will also require that all links going from domain1.com to domain2.com to be appended with a $_GET variable to pass the unique session hash. Then upon receiving the visitor, domain2.com will do a curl() request to domain1.com/userapi.php (or whatever you call the file) and the variables should be tested against what's in the database.

This is the best I can explain it.. to write this out in code is a significant piece of work so I cannot commit. But judging by your code, you have a very good understanding of PHP so I'm confident you will pull this off!

Good luck mate.

jeffkee
  • 5,106
  • 12
  • 44
  • 76
  • Sweet... comment here if you have any other questions, I'd be interested in getting this to work as well. As far as I know, Facebook authentication on 3rd party websites (totally different domains) use a similar API token methodology. – jeffkee Nov 04 '10 at 05:52
  • Agreed, but with recommendation that OP find an existing solution rather than roll his own. "My First Security System"s are notoriously vulnerable to attack. – Steve Clay Nov 04 '10 at 16:28
  • please, tell me about existing solutions – swamprunner7 Nov 04 '10 at 17:06
  • really can`t understand how to recieve my sessid or cookie or something from main domain. i tried send sessid on logining with img to all domains but i have so many domains, i can`t understand – swamprunner7 Nov 04 '10 at 20:59
  • 1
    So far I am unaware of existing solutions.. I tend to do heavy PHP coding on my own, from scratch. I hate Joomla/Drupal etc. For security, just use your common sense - prevent sql injections using the mysql_real_escape_string() function, make sure the tokens on the db auto-expire every 10 minutes or so UNLESS the user is active, in which case on each page-load, renew the token for another 10 minutes from the current active state. Make sure the tokens are not sent to any emails etc. and perhaps re-set the token hash on each jump from site to another.. and don't forget the md5() command! – jeffkee Nov 04 '10 at 21:11
  • i hate too joomla and others, for mysql use my small class, if i find solution i`ll update this post, thank you for thoughts – swamprunner7 Nov 04 '10 at 21:25
  • OK when a session is created on first login (let's say, on one.com) enter a mysql row into the 'tokens' table that contains a unique session id tha tlooks like this : fg4d56f4ds98f4dasf ... md5() will create that. Then you have a database row that contains the user's unique id, login token, and an expiry time. then create a .php file within one.php that will either answer 1 or 0 depending on whether there is a valid login for a certain user (for example, my user row happens to be row 4324, so query for id=4324 AND hash='fg4d56f4ds98f4dasf')... – jeffkee Nov 04 '10 at 21:54
  • and then use the curl function from two.com to verify against this value. if the answer is 1, meaning positive, then the login should be transferred.. instantly create a session on two.com indicating a successful login, with the hash # taken. For security, the .php file on one.com that checks for login should ONLY give the value out if the originating domain is one of the verified domains. – jeffkee Nov 04 '10 at 21:58
  • you want to say that we don`t need transfer sessid and cookies but only 1 or 0 and if 1 than create new session on secondary domain with «ok, he is logged in» in hash. And on main domain use authentication with checking cookies token with db token. i can`t think today, tomorrow will try, thanx – swamprunner7 Nov 04 '10 at 22:29
  • maybe something I did not understand correctly, plesae, give a code example – swamprunner7 Nov 04 '10 at 22:41
  • OK lets say when I log in, a token row is created in the 'tokens' table.. id: 4324, token: fg4d56f4ds98f4dasf, exp: 2010-11-03 14:00:00 then if there are any links that go to two.com, it should be appended with ?hash=fg4d56f4ds98f4dasf. Then upon receiving this link, on two.com's side, the PHP code processes that a $_GET['hash'] var was given.. so does the curl function, verifies the login (all this happens before any screen output!) then redirects the user to the page WITHOUT the ?hash=fg4d56f4ds98f4dasf.. because that remaining ont he browser top screen will be a security issue. – jeffkee Nov 04 '10 at 22:56
  • Using curl, you can send POST and GET vars. So then you would send the hash from two.com to one.com, and the .php file on one.com does a database query.. "SELECT * FROM tokens WHERE userid='4324' AND hash='fg4d56f4ds98f4dasf' and exp<'$currenttime'" Oh remember to include the uid in the link too, not just the hash: ?hash=fg4d56f4ds98f4dasf&uid=4324 – jeffkee Nov 04 '10 at 22:58
  • now i understand, it`s works. but how tumblr.com do it without tokens in links on domains? – swamprunner7 Nov 05 '10 at 00:30
  • but if if the user goes directly without token in GET? – swamprunner7 Nov 08 '10 at 21:30
  • Hmmm I'm not 100% sure how Tumbler does it.. i'd have to see it. I know that FB authentication is done through their login API. Could be an iFrame method too? It's worth researching or digging through for sure. I'd love to try to make a smoother login interface! – jeffkee Nov 08 '10 at 23:44
2

But if user reach domains one.com directly, than one.com can't know if user had login by the right answer mentioned above, seems like must use some extra js, it's jsonP! we let account.main.com/userLoginStat.php?callback=loginThisDomain to check if user had login main.com, if so, the js callback function loginThisDomain do some thing to autologin user to one.com.

hamlet
  • 356
  • 1
  • 4
  • 11
2

To keep your sessions going across multiple domains, you need to use session_set_cookie_params(). With that, you can specify your domain. For example...

session_set_cookie_params(10000, "/", ".main.com");

That will set the session timeout at 10,000 seconds for all documents under the site root, and for all subdomains of main.com.

You should call session_set_cookie_params() before you do session_start().

Brad
  • 159,648
  • 54
  • 349
  • 530
  • i did it too ini_set("session.cookie_domain", ".main.com"); but problem in other domains (one.com, two.com) not subdomains. – swamprunner7 Nov 03 '10 at 22:22
  • 1
    Ah, I see. Well for that, you are going to have to pass the session ID manually, and probably store this session information somewhere. You can't have cookies created on one domain and read by another. – Brad Nov 03 '10 at 22:25