Getting below error when I am trying to set session by laravel passport
"message": "Session store not set on request.", "exception": "RuntimeException",
This can be done in several ways.
StartSession
middleware after auth:api
.This is the most straightforward solution. Add the following three lines right after auth:api
.
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
Then remove \Illuminate\View\Middleware\ShareErrorsFromSession::class
from
middlewarePriority
protected property. Without this StartSession
middleware will get control before auth
and, more importantly, before EncryptCookies
middlewares which, basically, will always lead to a new session.
<?php
namespace App\Http;
class Kernel extends HttpKernel
{
// Copy this values from
// \Illuminate\Foundation\Http\Kernel::$middlewarePriority
// then remove or comment line with StartSession. Without it,
// StartSession middleware will get control right before Auth.
// Which, basically, will create a new session because at this
// time cookies are still encrypted.
protected $middlewarePriority = [
// \Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Auth\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
...
],
'api' => [
'throttle:120,1',
'bindings',
'auth:api', // https://laravel.com/docs/5.7/passport#protecting-routes
// Add the following three middleware right after `auth`
// in order to have a session.
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
],
];
}
StartSession
middleware.Having your own middleware for starting session will free you from necessaty to override middlewarePriority
.
First, create a new class.
<?php
namespace App\Http\Middleware;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\Session\SessionManager;
class StartSessionShared extends StartSession
{
public function __construct(Application $app, SessionManager $manager)
{
parent::__construct($manager);
$app->singleton(StartSessionShared::class);
}
}
Then add the following three lines right after auth:api
.
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSessionShared::class,
One important note in this method is call to $app->singleton
. Without it Laravel will always create a new instance of this class. Which will lead \Illuminate\Session\Middleware\StartSession::terminate
method to skip saving session.
StartSessionReadonly
middleware.This is a good choice if you want just to share session from web
guard to api
guard and don't intend to alter its values in any way. This was my case.
Create the following StartSessionReadonly
middleware. Then use it in api
guard instead of StartSession
and two its friends.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Contracts\Encryption\Encrypter;
use Illuminate\Contracts\Session\Session;
use Illuminate\Http\Request;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\Session\SessionManager;
/**
* Middleware for sharing session between `web` and `api` guards.
* Since the latter is essentially stateless, the session from
* `web` is shared as readonly.
*
* @package App\Http\Middleware
*/
class StartSessionReadonly extends StartSession
{
protected $encrypter;
public function __construct(Encrypter $encrypter, SessionManager $manager)
{
parent::__construct($manager);
$this->encrypter = $encrypter;
}
public function handle($request, Closure $next)
{
// If a session driver has been configured, we will need to start the session here
// so that the data is ready for an application. Note that the Laravel sessions
// do not make use of PHP "native" sessions in any way since they are crappy.
if ($this->sessionConfigured()) {
$request->setLaravelSession($this->startSession($request));
}
return $next($request);
}
public function getSession(Request $request)
{
return tap($this->manager->driver(), function (Session $session) use ($request) {
$payload = $request->cookies->get($session->getName());
$unserialize = EncryptCookies::serialized($session->getName());
try {
$session->setId($this->encrypter->decrypt($payload, $unserialize));
}
catch (DecryptException $exception) {
}
});
}
}
After updating app/Http/Kernel.php
you will have readonly session for all of your api.
<?php
namespace App\Http;
class Kernel extends HttpKernel
{
[...]
/****
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
[...]
'api' => [
'throttle:120,1',
'bindings',
'auth:api', // https://laravel.com/docs/5.7/passport#protecting-routes
StartSessionReadonly::class,
],
];
Laravel Passport is a token-based authentication package for laravel
APIs typically use tokens to authenticate users and do not maintain session state between requests. Laravel makes API authentication a breeze using Laravel Passport, which provides a full OAuth2 server implementation for your Laravel application in a matter of minutes.
Almost all the token-based systems including oAuth2 are by default stateless, which means there is no session attached to it,
Which means there is no session store.You can only rely on the token which is supplied on each request to validate the users identity.
That's why you are not able to set session when using laravel passport
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With