Laravel uses token auth by default, here’s how to switch it out for simple cookie-based auth for quick and easy API tinkering for logged-in users.
Note: I’m not a general PHP security expert. There may be good reasons not to do this aside from the fact that it’s not stateless (please comment if so!) and definitely use it over HTTPS if you can!!
I’ve been through this several times and I forget about it each time. So it’s worth writing down because it doesn’t seem to be well documented or explained even on Laracasts or Stack Overflow.
Let’s say you’re in the early stages of creating a simple app and you want to allow some actions to be taken using AJAX so you want to write some simple API routes that will return JSON.
Laravel has an api.php routes file which automatically applies some useful middlewares to requests, such as request throttling, and returns responses in JSON with appropriate HTTP headers. But it also uses per-user token auth by default using a token guard. A part of the framework that doesn’t even seem to be documented. The best I could find was a few tutorials, and the alternative seems to be to implement oAuth2 using Passport, which seems like overkill for smaller, simpler apps.
So perhaps this method really is frowned upon because it’s not stateless and violates REST principles. In any case, I’m pragmatic and I want to get started with my requests. So I want to switch this out for session based auth.
The config in question
Note: this is Laravel 5.5 – things may have changed.
So you put your route into
routes/api.php and you may note that that has the
auth:api middleware applied. Though I’m not quite sure (and am really struggling to find out) how this happens and exactly what gets applied.
It also has a bunch of other middleware applied that we can control, as we’ll see later.
Let’s deal with the latter first. The “other middleware” used are specified in
You’ll see in there the
$middlewareGroups property which looks like this:
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, ], 'api' => [ 'throttle:60,1', 'bindings', ], ]
And you’ll hopefully note that there’s a
web and an
api group in here. The
api group includes the throttling and something called bindings that remains mysterious to me.
Now, I THINK that the
auth:api middleware that you see mentioned in
routes/api.php refers to the guards listed in
config/auth.php. These look like:
'guards' => [ 'web'=>[ 'driver'=>'session', 'provider'=>'users', ], 'api'=>[ 'driver'=>'token', 'provider'=>'users', ], ],
Note that the driver for the
api guard here is token. Now I think this refers to a per-user-token style of authentication (a bit like the method described here), but this token-driver-auth is not, as far as I can tell, document ANYWHERE, even though it seems to be the default for routes in
So that what we seem to be dealing with. BUT…something either is not right with my understanding of the
auth:api middleware or it doesn’t work, or something else is going on that I don’t know about (and that no one seems to be able to tell me about).
Given what I found about the config, you’d think that the solution is to set the
api driver in
config/auth.php to be
session, but this doesn’t work.
One reason this doesn’t work is that the other lot of middleware defined in
'api' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, 'throttle:60,1', 'bindings', ],
But this STILL doesn’t work.
And in the absence of any further information about how the
auth:api middleware works, I can only get this working by changing
auth:api to just
So…steps to get this working
- Add the cookies and session middlewares to the
- Add your routes and controllers and away you go!
- Oh, and make sure you’re using HTTPS. You don’t want your cookies being intercepted!
If you know how the
auth:api middleware works, or if you can explain why any of what I’ve suggested is a bad idea, please leave comments.