If you want to do this, why are using API routes? You could just web-routes and life would be perfectly fine. You are just accessing the system with ajax/axios instead of the browser... calling this an api is wrong. Use web-routes and you will probably remove the vast majority of your issues.
Laravel 5.6 - How to authenticate API using sessions for same folder SPA?
I have a React SPA in the same Laravel project. The login/signup/logout and all other js views are in the js folder and use axios api calls for all POST/GET requests. I want to use the default Laravel session based web authentication for the embedded SPA, since it's in the same project folder and it will be the only javascript client accessing it. This api does not need to be open to the public, just for this react app, and it's an SPA for the speed and good user experience instead of full page reloads.
I do not want to deal with Passport tokens, access tokens, refresh tokens, revoking tokens, CSRF, etc. Just the out of the box simple Laravel session based auth that works so easily on web, but want it to work on my react app. The only blade file is the index.blade.php which includes the react app.js
Someone on Stack Overflow guided me to:
You have to add the various Session/Cookie middlewares in app/Http/Kernel.php (stuff like \Illuminate\Session\Middleware\StartSession::class) to the API routes.
Based on that suggestion, I added to $middlewareGroups.api to match the web middleware in app/Http/Kernel.php:
'api' => [
'throttle:60,1',
'bindings',
// Newly added middleware to match web middleware
\App\Http\Middleware\EncryptCookies::class
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
I realized there are two issues that occurred:
-
In the sessions table, even if not logged in, when loading app home page (or any page), multiple sessions are inserted into the
sessionstable. Shouldn't a new single session be inserted into this table only after user login? -
After user log in, when refreshing the page manually in the browser and a call is made to a protected route, I get a
401 Unauthenticatedwhich points me to this method inIlluminate/Auth/GuardHelpers.php:public function authenticate() { if (! is_null($user = $this->user())) { return $user; } throw new AuthenticationException; // throws this 401 exception on logged in page refresh when fetching data from private route }
Some additional notes:
-
In
config/auth.phpI updated theguards.api.drivertosessioninstead oftoken. -
In
routes/api.phpI have the protected routes wrapped in auth middleware like this:Route::group(['middleware' => 'auth'], function() { PRIVATE ROUTES HERE } -
In
config/session.phpI have'domain' => '.mydomain.com' -
I am sending back these headers with each axios api request like this:
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; let token = document.head.querySelector('meta[name="csrf-token"]'); window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
Any idea how we can fix these 2 issues?
Good news! I figured it out, so in config/session.php I had the last variable 'same_site' => 'strict' after changing it to 'same_site' => null the 401 error went away, and everything works perfectly.
I really appreciate all the help guys, thank you all so much!
Please or to participate in this conversation.