ngplayground
ngplayground

Reputation: 21667

PHP $_SESSION across subdomains

Ok so I have example.com which I then use Javascript to run XHR requests to api.example.com Previously I had the api.example.com as example.com/api but I wanted to move it to a subdomain and the sign in worked fine until I moved it to api.example.com

I am testing out a sign in script and trying to keep the session live but each time it runs it clears the $_SESSION

db_connect.php

include_once("config.php");
ob_start();
session_start();
$db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);

auth.php

<?php
require($_SERVER['DOCUMENT_ROOT'].'/db_connect.php');

if (!$db) {
    die('Could not connect: ' . mysql_error());
}
$method = $_SERVER['REQUEST_METHOD'];

if ( isset($_GET['id']) ){
    $id = $_GET['id'];
} else {
    $id = 'all';
}

switch (strtoupper($method)) {
    case "GET":
        if ($_SESSION['auth']) {
            $check = true;
        } else {
            $check = false;
        }
        $arr = json_encode(array('result'=>$check));
        echo $arr;
    break;
    default:
        echo "Streets closed pizza boy!";
}

signin.php

<?php
require($_SERVER['DOCUMENT_ROOT'].'/db_connect.php');

if (!$db) {
    die('Could not connect: ' . mysql_error());
}
$method = $_SERVER['REQUEST_METHOD'];

if ( isset($_GET['id']) ){
    $id = $_GET['id'];
} else {
    $id = 'all';
}

switch (strtoupper($method)) {

    case "POST":
        $postdata = json_decode(file_get_contents("php://input"));
        $src = (array)$postdata->user;
        $password = hash( 'sha512', $src['password']);

        $q = $db->query("SELECT *
            FROM users u
            WHERE u.email = '".$src['email']."'
            AND u.password = '".$password."'");

            if($q->num_rows > 0){
                $check = true;
                $_SESSION['auth'] = 1;

                $maps = array();
                while($row = mysqli_fetch_array($q)) {
                    $product = array(
                        'auth' => 1,
                        'id' => $row['id'],
                        'name' => $row['name'],
                        'email' => $row['email'],
                        'access' => $row['access']
                    );
                    array_push($maps, $product);
                }

                //$_SESSION['company_id'] = $product['company_id'];
            }else{
                $check = false;
            }

            $_SESSION['id'] = $product['id'];   
            $_SESSION['email'] = $product['email']; 

            setcookie("username", $productx§['email'], time()+(84600*30));

            $arr = json_encode(array('result'=>$check, 'user'=>$maps));
            echo $arr;
    break;

    default:
        echo "Your favorite color is neither red, blue, or green!";
}

I have tried setting db_connect.php to

<?php
include_once("config.php");
ob_start();
session_set_cookie_params(0, '/', '.example.com');
session_start();
$db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);

But this does nothing and the session variables are lost.

The PHP files are called via AJAX too.

Should ALL pages whether its the angularjs DOM connect to the database?

Upvotes: 3

Views: 2660

Answers (4)

Nicoli
Nicoli

Reputation: 944

This worked for me:

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

At first, it did not work, I had to delete all cookies and finally it worked as expected.

Upvotes: 0

ngplayground
ngplayground

Reputation: 21667

.htaccess on api.example.com

# CORS Headers (add this)
<ifModule mod_headers.c>
    Header add Access-Control-Allow-Origin "http://example.com"
      ## Post the domain that will be doing the XHR requests
    Header add Access-Control-Allow-Credentials: "true"
    Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
    Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
</ifModule>
<Limit GET POST PUT DELETE>
    Allow from all
</Limit>

example.com

Post the following in the header of your main website

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

XHR Request

Now we need to post the credentials from example.com to api.example.com I'm using AngularJS with this

$http({
    method: 'GET',
    url: '//api.example.com/auth/',
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true
}).success....

Also change your config to allow sending with Credentials

.config(function ($routeProvider, $httpProvider) {
    $httpProvider.defaults.withCredentials = true;
    //rest of route code

Upvotes: 0

Dmitriy.Net
Dmitriy.Net

Reputation: 1500

For using cross subdomain session, at all subdomain projects you must to use following code:

session_name('SessionName');
session_set_cookie_params(
    1800,
    ini_get('session.cookie_path'),
    '.example.com'
);
session_start();

Important: it works only if all subdomains at one server (cause sessions stored on one tmp dir). If you want to use similar session on different servers, use SAN storage or store sessions in memcached, etc.

ini_set('session.save_handler', 'memcache');
ini_set('session.save_path', 'tcp://122.122.122.122:11211');

session_name('SessionName');
session_set_cookie_params(
    1800,
    ini_get('session.cookie_path'),
    '.exmaple.com'
);
session_start();

Upvotes: 2

user3745735
user3745735

Reputation:

Try setting the session name:

$session_name = session_name("my_session");

Then, set the session cookie to span all subdomains:

session_set_cookie_params(0, "/", ".example.com");

Then do session_start() - it should now work.

Upvotes: 0

Related Questions