TL;DR - the guard essentially gets the credentials/token to check and asks the provider to check them and return a user, it then stores the user on the guard, calls to the auth facade/manager will then return this user.
I've decided to write a series of blog posts that I can look up whenever I've forgotten how something pretty fundamental works. This seems to happen from time to time with me for core concepts that web frameworks handle for us, as soon as I have to work with them again I'll be like 'what does a Guard do again'.
So this is the first one, and it's covering Laravel Authentication... if this is future me reading this... you're welcome.
Guards
Guards are responsible for authenticating users with the application. Laravel comes with two configured guards, 'web' and 'api'. The web guard is an alias for Illuminate\Auth\SessionGuard. This guard assumes the existence of a session, the session will use one of the configured session drivers, but the guard doesn't really care about which session driver is in use.
So whenever the auth facade is used or the Authenticate middleware is used, the default behaviour is for the web guard (SessionGuard) to be called to try to retrive the user from the current session.
The other provided auth guard is 'api', this maps to Illuminate\Auth\TokenGuard. So when you explicitly set the api guard on your route like 'auth:api', Laravel will drop in the token guard to the auth system.
So guards are essentially a layer that sits at the top of the auth system to abstract how the application retrieves an authenticated user. This leads on to the next layer down, providers.
Providers
Laravel ships with two user providers, eloquent and database. They both do pretty much the same thing, find and authenticate a user in the db based on the identifier (usually email), the eloquent provider returns an eloquent user model whereas the database provider returns a GenericUser.
The providers are \Auth\EloquentUserProvider and \Auth\DatabaseUserProvider. The UserProvider contract is pretty concise and shows what to expect from a provider, although retrieveByToken isn't what you'd think, it's actually referring to the remember token, not an api token.
Providers get really interesting if your application needs to authenticate entities other than users. It's pretty trivial to add a custom provider to allow you to authenticate Customers from a customers table. If you combine this with a new 'guard' you can use this in your app routes to allow different user types to authenticate for different parts of your application.
Starter Kits
Laravel introduced a couple of 'starter kits' for authentication, Jetstream and Breeze. Breeze offers a simple auth scaffold with blade templates and even Vue and React front ends. It's designed for simple apps that only need the usual register/login/reset flow, it's kind of a modernised version of the original auth templates Laravel had in v5, (those are now in a separate package called laravel/ui along with the controller traits etc). Jetstream is a more full-featured auth implmentation with support for teams, api token mangement (via Sanctum), profiles and two factor authentication. You don't actually need any of these though, you can get up and running with the auth layer pretty quickly, it's really as simple as validate the user credentials and call attempt on the Auth facade:
public function authenticate(Request $request): RedirectResponse
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
return redirect()->intended('dashboard');
}
return back()->withErrors([
'email' => 'The provided credentials do not match our records.',
])->onlyInput('email');
}
https://laravel.com/docs/11.x/authentication#authenticating-users
So, there it is, a quick explanation on these two core concepts in Laravel.
Photo by rc.xyz NFT gallery on Unsplash