2

I'm trying to get my sessions working for API-Routes. On Web-Routes everything is fine, but the Moment I try to use it on API-Routes the Session is empty.

I know APIs should be stateless but I just communicate with an external API and my Laravel instance is just the frontend.

So my authentification is just a simple Session::put('userData', $response->data); after the successful request to the login endpoint of the API. In there some data about name, email, some default data and the auth token for the user.

The last one is important because I'd like to access some endpoints via AJAX (axios) and I need to send the saved auth token to the API to get things working. But everything is broken at the moment I try to guard the API-Routes with my RedirectIfUnauthenticated-Middleware. It always redirects me to the login page, because the session is empty.

If I remove it, I get to the Controller but the session is still empty and I can't add the auth token to the api request.

I think I do something fundamentally wrong here. So maybe someone can help here.

I already tried to add \Illuminate\Session\Middleware\StartSession::class, to the $middlewareGroups api section, but it seems to reset all session data so I get logged out. But maybe I do something wrong here too.

kaiserkiwi
  • 516
  • 1
  • 5
  • 17
  • 2
    You said it yourself; APIs are stateless. Putting `session()->put()` in an API would mean that anyone who accesses the API would get that data, which is not likely what you want. You have the right idea with auth tokens, but the frontend should be sending the token to cross-reference with a user. – Tim Lewis Nov 25 '19 at 18:07
  • Although highly inadvisable, some people who took your approach suggest including `\App\Http\Middleware\EncryptCookies::class` along with the `StartSession`. Also, please don't do it :) – user3532758 Nov 25 '19 at 18:13
  • @user3532758 any explanation why? Or you just made this up? I mean the official docs say for SPA we should use the session flow. SPA should use API middleware group and not web middleware group. The whole this is soo messy – Peter Apr 11 '21 at 14:42
  • The comment above, and looks like even the answer, covered it. Inadvisable because its anti-pattern. Many believe api should be stateless. Specially if you are following RESTful, to give a small context. But, yeah sometimes it boils down to whatever works. Also this might be helpful: https://stackoverflow.com/questions/3105296/if-rest-applications-are-supposed-to-be-stateless-how-do-you-manage-sessions/ – user3532758 Apr 11 '21 at 18:38

3 Answers3

12

It's anti-pattern but you can use sessions in Laravel API. Head to /app/Http/Kernel.php and add the following code:

'api' => [
    \App\Http\Middleware\EncryptCookies::class,
    \Illuminate\Session\Middleware\StartSession::class,

    'throttle:60,1',
    'bindings',
    ...
];

It's important after you've done this to clear all your active sessions from session driver storage (whether it's files, database, memcache, etc). For sessions stored on files go to /storage/framework/sessions and remove all files except .gitignore.

Now Sessions should work for API routes as well.

user8555937
  • 2,161
  • 1
  • 14
  • 39
  • 1
    To be honest I think most implementation with REST do have state. Many implementations use JWT to for authentication, and JWT ALSO maintains state due to checking for revoked tokens, etc. – Bernard Wiesner Oct 29 '21 at 07:29
  • @BernardWiesner they do have state. The difference between REST and session is that state is held as much as possible by client. – user8555937 May 26 '22 at 06:41
1

To avoid redirection, make sure you add Accept : application/json to the request headers.

You can try and use laravel\sanctum (now included in a Laravel installation) and the EnsureFrontendRequestsAreStateful middleware by adding it to the api middleware groups in App\Http\Kernel

'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],
damask
  • 529
  • 4
  • 17
0

go to /app/Http/Kernel.php and add the following code:

'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
],

'api' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
Mohsen_AB
  • 41
  • 1
  • 5
  • 3
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 08 '21 at 20:27