Cookie-less Laravel sessions

404 Views Asked by At

We have a small quiz type functionality built in Laravel to be embedded in a site via an iframe served from a separate domain (to work around CMS limitations).

It uses sessions to keep track of the user's progress in the quiz. This doesn't work in Safari (Mac/iOS), I believe because Apple disable cookies issued from within an iframe.

Assuming that limitation is one we're stuck with, has anyone had any success making Laravel sessions cookie-less? I found this code on Github, which looks promising but is old enough (and incompatible with current Laravel) that I can't tell if it's going to be a solution.

1

There are 1 best solutions below

0
On

In case it helps someone else, or anyone can see any silly errors in my code, this is what I did (an adaption of the Github code, to work in Laravel 9).

I extended StartSession and SessionServiceProvider (to use my new StartSession). I created an override for handleStatefulRequest in Start Session, and where it adds a cookie to the reponse (it calls addCookieToResponse) did this:

if ($request->cookies->get($session->getName())) {
    $this->addCookieToResponse($response, $session);
}
else {
    // Add session ID to header
    $this->addIdentifierToResponse($response, $session);
}

That new function looks like this:

protected function addIdentifierToResponse(Response $response, Session $session)
{
    if ($this->sessionIsPersistent($config = $this->manager->getSessionConfig())) {
        $response->headers->set("X-Session-Token", $session->getId());
    }
}

I also changed the getSession method to get the session ID from that newly set header (when no cookie found):

public function getSession(Request $request)
{
    return tap($this->manager->driver(), function ($session) use ($request) {
        if ($request->cookies->get($session->getName())) {
            Log::debug('1. Set session ID from cookie');
            $session->setId($request->cookies->get($session->getName()));
        }
        else if ($request->headers->get("X-Session-Token", $request->input("sess_id"))) {
            $sessionToken = $request->headers->get("X-Session-Token", $request->input("sess_id"));
            $session->setId($sessionToken);
        }
    });
}

I created a Github repo containing the whole thing.