Extending Laravel's Authentication: Creating Custom Guards
Laravel's authentication system is robust and flexible out of the box, but sometimes your application might require a specialised authentication method. This is where custom authentication guards come into play. Let's explore how to create and implement a custom guard in Laravel.
Understanding Custom Guards
Custom guards allow you to define your own authentication logic, which can be particularly useful for implementing JWT authentication, OAuth, or any other specialized auth system that doesn't fit into Laravel's default guard types.
Creating a Custom Guard
To create a custom guard, you'll need to use the Auth::extend()
method. This is typically done in a service provider. Let's walk through the process:
- Create Your Guard Class
First, create a new class that implements the Illuminate\Contracts\Auth\Guard
interface. For this example, we'll create a simple JWT guard:
namespace App\Services\Auth;
use Illuminate\Contracts\Auth\Guard;
class JwtGuard implements Guard
{
protected $provider;
protected $user;
public function __construct($provider)
{
$this->provider = $provider;
}
public function check()
{
// Check if the user is authenticated
}
public function user()
{
// Return the authenticated user
}
// Implement other methods required by the Guard interface
}
- Register the Custom Guard
In your AppServiceProvider
or a dedicated AuthServiceProvider
, register your custom guard:
namespace App\Providers;
use App\Services\Auth\JwtGuard;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Auth::extend('jwt', function ($app, $name, array $config) {
return new JwtGuard(Auth::createUserProvider($config['provider']));
});
}
}
- Configure the Guard
In your config/auth.php
file, add your new guard:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
Implementing the Guard Logic
In your guard class, you'll need to implement the authentication logic. Here's a basic example of what the check()
and user()
methods might look like in a JWT guard:
public function check()
{
if (! $this->user) {
$token = $this->getTokenFromRequest();
if ($token && $this->validateToken($token)) {
$this->user = $this->provider->retrieveById($this->getPayload($token)->sub);
}
}
return $this->user !== null;
}
public function user()
{
if (! $this->user) {
$this->check();
}
return $this->user;
}
protected function getTokenFromRequest()
{
// Logic to extract JWT from request
}
protected function validateToken($token)
{
// Logic to validate JWT
}
protected function getPayload($token)
{
// Logic to decode and return JWT payload
}
Using Your Custom Guard
Once your guard is set up, you can use it like any other Laravel guard:
if (Auth::guard('api')->check()) {
$user = Auth::guard('api')->user();
// Do something with the authenticated user
}
You can also set it as the default guard for certain routes in your RouteServiceProvider
:
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('auth:api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}
By creating custom authentication guards, you can tailor Laravel's authentication system to meet your specific needs. Whether you're implementing JWT, OAuth, or any other authentication method, custom guards provide the flexibility to integrate seamlessly with Laravel's existing authentication features.
If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!