php - Laravel Sanctum multi guard weird session issue (users sharing a session / logged in as multiple users)
Get the solution ↓↓↓I'm trying to make Fortify with sanctum work with a custom Guard called SPA.
The admins are logging in on the backend with the Web guard.
The users are logging in on a subdomain that will host a VUEJS SPA.
Admin logs in on -> https://test.local:8890/admin/login and is redirected to https://test.local:8890/admin/dashboard that works -> ok
Users log in on https://spa.test.local:8890 (vue app). -> ok works
Vuefile:
import axios from 'axios'
axios.defaults.withCredentials = true;
axios.defaults.baseURL = 'https://test.local:8890'
export default {
name: 'Home',
components: {
HelloWorld
},
data: () => {
return {
email : '[email protected]',
password : 'Password1!'
}
},
methods : {
login() {
axios.get('/sanctum/csrf-cookie').then(response => {
console.log(response.code);
axios.post('web-api/login', {
email : this.email,
password : this.password
}).then(response => {
console.log(response);
}
).catch(error => {
console.log(error);
})
});
}}}
So the idea is that users can not log in on the dashboard and have a separate table
When i log in on my admin i go to the dashboard. I open a new tab in chrome and log in as the user on the subdomain in the vue app. When i go back to the dashboard i'm still logged in so good and i'm logged in on the other tab as the user (super)
But when inspecting the cookies in chrome https://test.local:8890/ and https://spa.test.local:8890/ share the same cookie laravel_session and xcsrf token... they are identical...
So now when i go to admins tab and go to the web-api route https://test.local:8890/web-api/user i see the user's credentials :
{"id":4,"first_name":"Happy","last_name":"Doe","email":"[email protected]"}
Yet i can still visit my dashboard as Admin.
config/auth.php
'defaults' => [
'guard' => 'web',
'passwords' => 'admins',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'admins', //admin provider for web
],
'spa' => [
'driver' => 'session',
'provider' => 'users' //user provicer for spa (and api)
],
/*'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false, //user provider
],*/
],
I've added guard parameter to sanctum config.
config/sanctum:
'guard' => 'spa', //set sanctum guard to spa.
In the Kernel file i've copied everything from the 'web' middleware to 'spa' because it works almost the same.
Kernel.php:
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'spa' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class
],
'api' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
Configured Sanctum parameters in the env file.
.env :
SESSION_DOMAIN=test.local
SANCTUM_STATEFUL_DOMAINS=.test.local
Added the SPA to routeServiceProvider boot method
RouteServiceProvider.php:
public function boot()
{
$this->configureRateLimiting();
$this->routes(function () {
Route::prefix('web-api')
->middleware('spa')
->namespace($this->namespace)
->group(base_path('routes/spa.php'));
/*Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));*/
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
});
}
Then my login function in SpaAuthController: (as used by the spa)
public function loginSpa(Request $request){
//Regenerate session
$request->session()->regenerate();
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
$authAttempt = Auth::guard('spa')->attempt(['email' => $request->email, 'password' => $request->password]);
if($authAttempt){
$user = Auth::guard('spa')->user();
if (!$user->hasVerifiedEmail()){
abort(401, 'Email address not verified.');
}
if ($user->blocked){
abort(401, 'Your Account blocked.');
}
return response([],204);
}
return response(['message' => 'The provided credentials are incorrect.'],422);
}
The entire web login is handled by default fortify controllers...
POST | admin/login | | Laravel\Fortify\Http\Controllers\AuthenticatedSessionController@store | web
At this point it's getting kinda funny, what am i doing wrong here and should i be worried for potential security issue presume yes :D)
Share solution ↓
Additional Information:
Link To Answer People are also looking for solutions of the problem: method illuminate\database\eloquent\collection::paginate does not exist.
Didn't find the answer?
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Similar questions
Find the answer in similar questions on our website.
Write quick answer
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.