7

I'm currently porting SimpleFBConnect module to Drupal 8. This module uses Facebook PHP SDK which expects that we have established a session before the user is redirected to Facebook for authentication.

By reading SessionManager API, I assumed that SessionManager::start would start the session. However, this does not seem to be the case. The same thing applies to SessionManager::save (description says that this function will "Force the session to be saved and closed.").

The only way how I was able to force a session start was to call SessionManager::regenerate.

Is this the correct way to force session start in Drupal 8?

Debug code, which will show that SessionManager::start will not start the session.

class TestController extends ControllerBase {
  public function test() {
    $session_manager = Drupal::service('session_manager');
    $session_manager->start();

    if ($session_manager->isStarted()) {
      $msg = 'Sesssion started';
    }
    else {
      $msg = 'Sesssion not started';
    }

    return array(
      '#markup' => $msg
    );
  }
}

4 Answers 4

2

Drupal only starts a session if at the end of the request the $_SESSION super global contains any data. Empty sessions are actively destroyed. This is in order to maximize cache-hit ratios when operating a site behind a reverse proxy server (e.g. Varnish).

Like pointed out by @Berdir already, the proper way to trigger a session start in Drupal is to store something in it. However, the Facebook SDK tries to protect its users against data-loss due to improper session management. According to the source code, this feature can be disabled via the method FacebookRedirectLoginHelper::disableSessionStatusCheck(). Please use that instead of trying to enforce a session start.

1
  • Many thanks @znerol! I just tested and you were right with the disableSessionStatusCheck(). Cheers, Markus Jul 1, 2015 at 6:59
7

Okay, found the answer from this change record: https://www.drupal.org/node/2228871

The session can be force-started like this:

// Force session start if we don't already have a session.
$session = \Drupal::service('session');
if (!$session->isStarted()) {
  $session->migrate();
}
1
  • Note: The comment for migrate in the change record confusingly says "Migrate the current session from anonymous to authenticated (or vice-versa).". The 8.2 docs say "Migrates the current session to a new session id while maintaining all session attributes".
    – Tim
    Dec 7, 2016 at 7:24
1

I think the only way to force a session is to store something in it.

There's no point in manually starting it, since Drupal won't save a session that has no session data, AFAIK.

So try to just put a dummy key in $_SESSION.

1
  • The reason why I have to force session start is that if I don't, FacebookRedirectLoginHelper will throw Uncaught PHP Exception Facebook\\FacebookSDKException: "Session not active, could not store state." I don't think that setting a dummy key directly to $_SESSION is an elegant way of doing this. Especially because of this change record which discourages using $_SESSION directly: drupal.org/node/2380327 Jun 25, 2015 at 11:30
0

I know this is an old question but this showed up high in the search results when I was trying to figure out why even when I stored something in a user's session, it wasn't always actually creating a session when dealing with anonymous users. If you run into this same issue, it's very likely due to the Internal Page Cache core module caching things at such a low level that sessions don't get started if the page is already cached. To quote the documentation:

Websites that serve personalized content to anonymous users (dynamic, per-session, e.g. a shopping cart) will want to disable the Internal Page Cache module. This module assumes pages are identical for all anonymous users. Those websites can still take advantage of the Dynamic Page Cache module[.]

The solution is to either disable the module (while using other forms of caching), or keep it enabled and possibly decorate the service to allow the request through to Drupal if no session is detected, allowing the session to be initialized (and thus a cookie sent), and then have subsequent requests served from the page cache. This assumes that your anonymous content is all identical and you only need sessions for back-end stuff that doesn't change the content itself. An example of this is if you're trying to keep track of which recent pages a user has just visited to avoid showing those when a user asks for a random page, which is something we have on Omnipedia.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.