Question

I need to switch to another user, create session for him, write data into the session(his UID), save the session id, then switch back to original user and work with the session id.

The account switcher is disabling session and I haven' been able to make it work manually with session or session_manager services.

Was it helpful?

Solution

I'd delete this question but someone might find this useful.

It toke me half a day to figure this thing out and the result feels quite hacky and not Drupal-way in any shape or form but it's the only working solution I have been able to put together. The SessionBag is just a simple wrapper around session information - for my purposes.

/**
   * Creates session for provided user without destroying
   * the current user's session.
   *
   * @see user_login_finalize()
   * @see \Drupal\Core\Session\SessionManager::regenerate()
   *
   * @param int $uid
   *
   * @return \Drupal\foo_auth\SessionBag
   *   Session information.
   */
  public function createSession(int $uid): ?SessionBag {
    $session_options = $this->sessionConfig->getOptions($this->requestStack->getCurrentRequest()) + session_get_cookie_params();
    $session_id = Crypt::randomBytesBase64();

    // @see \Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag
    // @see \Symfony\Component\HttpFoundation\Session\Session::set()
    $data = [
      '_sf2_attributes' => [
        'uid' => $uid
      ]
    ];

    // Special handling for session serialization.
    $current_session = $_SESSION;
    $_SESSION = $data;
    $serialized_data = session_encode();
    $_SESSION = $current_session;

    // @see \Drupal\Core\Session\SessionHandler::write
    try {
      $this->database->insert('sessions')
        ->fields([
          'uid' => $uid,
          'hostname' => $this->requestStack->getCurrentRequest()->getClientIP(),
          'session' => $serialized_data,
          'timestamp' => REQUEST_TIME,
          'sid' => Crypt::hashBase64($session_id)
        ])
        ->execute();
    } catch (\Exception $e) {
      watchdog_exception('foo_auth', $e);
      return NULL;
    }

    return new SessionBag(
      $session_options['name'],
      $session_id,
      $session_options['cookie_lifetime'] + REQUEST_TIME,
      $session_options['path'],
      $session_options['cookie_domain'],
      $session_options['cookie_secure'],
      $session_options['httponly']
    );
  }
Licensed under: CC-BY-SA with attribution
Not affiliated with drupal.stackexchange
scroll top