We are moving our forum in GitHub Discussions. For questions about Phalcon v3/v4 you can visit here and for Phalcon v5 here.

Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

Session across subdomains


I am trying to make session work across multiple subdomains (typically : domain.local, client1.domain.local, and api.domain.local)

I am on the login page on domain.local, and I call the api.domain.local in order to login, then I refresh the page is it was correct.

I did that on both domains:

$session = new Phalcon\Session\Adapter\Files(); $session->start();

But then I added that before session->start() :

$session->setOptions(array('cookie' => array('domain' => '.' . $oConfig->application->domain))); ini_set('session.cookie_domain', '.' . $oConfig->application->domain);

And it still does not work. When I display $_COOKIE, it works fine, I get the same PHPSESSID cookie on both domains, but when I var_dump $_SESSION, I only have '_started' => boolean true , nothing else.

What am I doing wrong please?

Also, if there is a way to prevent using sessions, and use HTTP headers instead (Authorization header) and keep a pool of authorized tokens in a memcached, it would be really great, any tips greatly appreciated!

Thank you in advance,

from: http://forum.phalcon.io/discussion/64/session-service-to-be-valid-accross-all-subdomains

$di['session'] = function() {

    session_set_cookie_params(0, '/', '.some_domain.com');

    $session = new \Phalcon\Session\Adapter\Files();

    return $session;
edited Jun '14

Thank you David for your answer, but that's pretty much what I am already doing, and as I said I already have the proper PHPSESSID cookie available on both subdomains, which means that the cookies work, and session should be recognized.

But the session is still always empty (only "_started" = true). I did not have this problem when using only one domain.


$di->setShared('session', function() use ($di)
    $oConfig = $di->getShared('config');
    //ini_set('session.cookie_domain', '.' . $oConfig->application->domain);

    session_set_cookie_params(0, '/', '.' . $oConfig->application->domain);
    $session = new Phalcon\Session\Adapter\Files();
    //$session->setOptions(array('cookie' => array('domain' => '.' . $oConfig->application->domain)));
    //ini_set('session.cookie_domain', '.' . $oConfig->application->domain);
    return $session;



Where I set the value in session:

// ... function handling login ...
// ...
if ($this->session->has('memberId'))
// ...
// ... retrieve user ...
// ...
$this->session->set('memberId', $oMember->getId());


Ok nevermind, I stopped using sessions, and I am now using an Authorization header stored in a tokens pool in memcached. Works like a charm :)

Thank you all,


it's cool.

@RenaudParis Can you explain further what you're doing with the Authorization header? I'm running into the same issue and am interested in other options, especially if they're working great :)


edited Jul '14



I'm doing nothing out of the extraordinary :) I have multiple webapp domains (say, client1.site.com, ...) and an API (api.site.com).

When logging in, I call a "guest-allowed" API URL in order to login, which generates a token (stored in redis/memcached along with the user ID and a last action timestamp for token-TTL management). I hash (reversible) the user id and use it to generate an "Authorization" token like this : {hash-user-id}-{token}.

The client keeps that value in a cookie, and provides it along with each Ajax request to the API in a header (either "Authorization" or any other custom header of your choosing). The API checks the values, and if everything is ok, it executes the requested action.

Beware of CORS, as you will have to handle them properly because you will be sending "custom" headers, which triggers preflights (there will be OPTIONS preflight requests, to reply with a cache TTL -- which is ignored by some browsers and limited to 5 minutes... boring)

You will also have to manage your response headers properly (allowed headers, allow origin, allow methods, ...) (sometimes, putting "*" in the response headers for allow-origin is not accepted because too permissive)

Hope this helps!

(I can provide more specific data when I'm home in a few hours if necessary)