1. Code
  2. PHP
  3. Laravel

How to Create a Custom Authentication Guard in Laravel

Scroll to top

In this article, we’re going to cover the authentication system in the Laravel framework. The main aim of this article is to create a custom authentication guard by extending the core authentication system.

Laravel provides a very solid authentication system in the core that makes the implementation of basic authentication a breeze. In fact, you just need to run a couple of artisan commands to set up the scaffolding of an authentication system.

Moreover, the system itself is designed in such a way that you could extend it and plug in your custom authentication adapters as well. That’s what we'll discuss in detail throughout this article. Before we go ahead and dive into the implementation of the custom authentication guard, we’ll start with a discussion of the basic elements in the Laravel authentication system—guards and providers.

The Core Elements: Guards and Providers

The Laravel authentication system is made up of two elements at its core—guards and providers.

Guards

You could think of a guard as a way of supplying the logic that’s used to identify the authenticated users. In the core, Laravel provides different guards like session and token. The session guard maintains the state of the user in each request by cookies, and on the other hand the token guard authenticates the user by checking a valid token in every request.

So, as you can see, the guard defines the logic of authentication, and it’s not necessary that it always deals with that by retrieving valid credentials from the back end. You may implement a guard that simply checks the presence of a specific thing in request headers and authenticates users based on that.

Later in this article, we’ll implement a guard that checks certain JSON parameters in request headers and retrieves the valid user from the MongoDB back end.

Providers

If the guard defines the logic of authentication, the authentication provider is responsible for retrieving the user from the back-end storage. If the guard requires that the user must be validated against the back-end storage, then the implementation of retrieving the user goes into the authentication provider.

Laravel ships with two default authentication providers—Database and Eloquent. The Database authentication provider deals with the straightforward retrieval of the user credentials from the back-end storage, while Eloquent provides an abstraction layer that does the needful.

In our example, we’ll implement a MongoDB authentication provider that fetches the user credentials from the MongoDB back end.

So that was a basic introduction to guards and providers in the Laravel authentication system. From the next section onwards, we’ll focus on the development of the custom authentication guard and provider!

A Quick Glance at the File Setup

Let's have a quick look at the list of files that we'll implement throughout the course of this article.

  • config/auth.php: It's the authentication configuration file in which we'll add an entry of our custom guard.
  • config/mongo.php: It's the file that holds the MongoDB configuration.
  • app/Services/Contracts/NosqlServiceInterface.php: It's an interface that our custom Mongo database class implements.
  • app/Database/MongoDatabase.php: It's a main database class that interacts with MongoDB.
  • app/Models/Auth/User.php: It's the User model class that implements the Authenticable contract.
  • app/Extensions/MongoUserProvider.php: It's an implementation of the authentication provider.
  • app/Services/Auth/JsonGuard.php: It's an implementation of the authentication guard driver.
  • app/Providers/AuthServiceProvider.php: This is an existing file that we'll use to add our service container bindings.
  • app/Http/Controllers/MongoController.php: It's a demo controller file that we'll implement to test our custom guard.

Don't worry if the list of the files doesn't make much sense yet as we'll discuss everything in detail as we go through it.

Deep Dive Into the Implementation

In this section, we'll go through the implementation of the required files.

The first thing that we need to do is to inform Laravel about our custom guard. Go ahead and enter the custom guard details in the config/auth.php file as shown.

1
...
2
...
3
'guards' => [
4
    'web' => [
5
        'driver' => 'session',
6
        'provider' => 'users',
7
    ],
8
 
9
    'api' => [
10
        'driver' => 'token',
11
        'provider' => 'users',
12
        'hash' => false,
13
    ],
14
     
15
    'custom' => [
16
      'driver' => 'json',
17
      'provider' => 'mongo',
18
    ],
19
],
20
...
21
...

As you can see, we've added our custom guard under the custom key.

Next, we need to add an associated provider entry in the providers section.

1
...
2
...
3
'providers' => [
4
    'users' => [
5
        'driver' => 'eloquent',
6
        'model' => App\User::class,
7
    ],
8
    'mongo' => [
9
        'driver' => 'mongo'
10
    ],
11
 
12
    // 'users' => [

13
    //     'driver' => 'database',

14
    //     'table' => 'users',

15
    // ],

16
],
17
...
18
...

We've added our provider entry under the mongo key.

Finally, let's change the default authentication guard from web to custom.

1
...
2
...
3
'defaults' => [
4
    'guard' => 'custom',
5
    'passwords' => 'users',
6
],
7
...
8
...

Of course, it won't work yet, as we've not implemented the necessary files yet. And that's what we'll discuss in the next couple of sections.

Set Up the MongoDB Driver

In this section, we'll implement the necessary files that talk to the underlying MongoDB instance.

Let's first create the config/mongo.php configuration file, which holds the default MongoDB connection settings.

1
<?php
2
return [
3
  'defaults' => [
4
    'host' => '{HOST_IP}',
5
    'port' => '{HOST_PORT}',
6
    'database' => '{DB_NAME}'
7
  ]
8
];

Of course, you need to change the placeholder values as per your settings.

Instead of directly creating a class that interacts with MongoDB, we'll create an interface in the first place.

The benefit of creating an interface is that it provides a contract that a developer must adhere to while implementing it. Also, our implementation of MongoDB could be easily swapped with another NoSQL implementation if needed.

Go ahead and create the app/Services/Contracts/NosqlServiceInterface.php interface file with the following contents.

1
<?php
2
// app/Services/Contracts/NosqlServiceInterface.php

3
namespace App\Services\Contracts;
4
 
5
Interface NosqlServiceInterface
6
{
7
  /**

8
   * Create a Document

9
   *

10
   * @param string $collection Collection/Table Name

11
   * @param array  $document   Document

12
   * @return boolean

13
   */
14
  public function create($collection, Array $document);
15
  
16
  /**

17
   * Update a Document

18
   *

19
   * @param string $collection Collection/Table Name

20
   * @param mix    $id         Primary Id

21
   * @param array  $document   Document

22
   * @return boolean

23
   */
24
  public function update($collection, $id, Array $document);
25
 
26
  /**

27
   * Delete a Document

28
   *

29
   * @param string $collection Collection/Table Name

30
   * @param mix    $id         Primary Id

31
   * @return boolean

32
   */
33
  public function delete($collection, $id);
34
  
35
  /**

36
   * Search Document(s)

37
   *

38
   * @param string $collection Collection/Table Name

39
   * @param array  $criteria   Key-value criteria

40
   * @return array

41
   */
42
  public function find($collection, Array $criteria);
43
}

It's a pretty simple interface which declares the basic CRUD methods that a class must define that implements this interface.

Now, let's define the app/Database/MongoDatabase.php class with the following contents.

1
<?php
2
// app/Database/MongoDatabase.php

3
namespace App\Database;
4
 
5
use App\Services\Contracts\NosqlServiceInterface;
6
 
7
class MongoDatabase implements NosqlServiceInterface
8
{
9
  private $manager;
10
  private $database;
11
     
12
  public function __construct($host, $port, $database)
13
  {
14
    $this->database = $database;
15
    $this->manager = new \MongoDB\Driver\Manager( "mongodb://".$host.":".$port."/".$database );
16
  }
17
18
  /**

19
   * @see \App\Services\Contracts\NosqlServiceInterface::find()

20
   */
21
  public function find($collection, Array $criteria)
22
  {
23
    $query = new \MongoDB\Driver\Query($criteria);
24
    $result = $this->manager->executeQuery($this->database.".".$collection, $query);
25
26
    $user = array();
27
    foreach ($result as $row) {
28
        $user['username'] = $row->username;
29
        $user['password'] = $row->password;
30
    }
31
32
    return $user;
33
  }
34
 
35
  public function create($collection, Array $document) {}
36
  public function update($collection, $id, Array $document) {}
37
  public function delete($collection, $id) {}
38
}

Of course, I assume that you've installed MongoDB and the corresponding MongoDB PHP extension.

The __construct method instantiates the MongoClient class with the necessary parameters. The other important method we're interested in is the find method, which retrieves the record based on the criteria provided as method arguments.

So that was the implementation of the MongoDB driver, and I tried to keep it as simple as possible.

Set Up the User Model

Adhering to the standards of the authentication system, we need to implement the User model, which must implement the Illuminate\Contracts\Auth\Authenticatable contract.

Go ahead and create a file app/Models/Auth/User.php with the following contents.

1
<?php
2
// app/Models/Auth/User.php

3
namespace App\Models\Auth;
4
 
5
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
6
use App\Services\Contracts\NosqlServiceInterface;
7
 
8
class User implements AuthenticatableContract
9
{
10
  private $conn;
11
  
12
  private $username;
13
  private $password;
14
  protected $rememberTokenName = 'remember_token';
15
 
16
  public function __construct(NosqlServiceInterface $conn)
17
  {
18
    $this->conn = $conn;
19
  }
20
 
21
  /**

22
   * Fetch user by Credentials

23
   *

24
   * @param array $credentials

25
   * @return Illuminate\Contracts\Auth\Authenticatable

26
   */
27
  public function fetchUserByCredentials(Array $credentials)
28
  {
29
    $arr_user = $this->conn->find('users', ['username' => $credentials['username']]);
30
     
31
    if (! is_null($arr_user)) {
32
      $this->username = $arr_user['username'];
33
      $this->password = $arr_user['password'];
34
    }
35
 
36
    return $this;
37
  }
38
 
39
  /**

40
   * {@inheritDoc}

41
   * @see \Illuminate\Contracts\Auth\Authenticatable::getAuthIdentifierName()

42
   */
43
  public function getAuthIdentifierName()
44
  {
45
    return "username";
46
  }
47
  
48
  /**

49
   * {@inheritDoc}

50
   * @see \Illuminate\Contracts\Auth\Authenticatable::getAuthIdentifier()

51
   */
52
  public function getAuthIdentifier()
53
  {
54
    return $this->{$this->getAuthIdentifierName()};
55
  }
56
 
57
  /**

58
   * {@inheritDoc}

59
   * @see \Illuminate\Contracts\Auth\Authenticatable::getAuthPassword()

60
   */
61
  public function getAuthPassword()
62
  {
63
    return $this->password;
64
  }
65
 
66
  /**

67
   * {@inheritDoc}

68
   * @see \Illuminate\Contracts\Auth\Authenticatable::getRememberToken()

69
   */
70
  public function getRememberToken()
71
  {
72
    if (! empty($this->getRememberTokenName())) {
73
      return $this->{$this->getRememberTokenName()};
74
    }
75
  }
76
 
77
  /**

78
   * {@inheritDoc}

79
   * @see \Illuminate\Contracts\Auth\Authenticatable::setRememberToken()

80
   */
81
  public function setRememberToken($value)
82
  {
83
    if (! empty($this->getRememberTokenName())) {
84
      $this->{$this->getRememberTokenName()} = $value;
85
    }
86
  }
87
 
88
  /**

89
   * {@inheritDoc}

90
   * @see \Illuminate\Contracts\Auth\Authenticatable::getRememberTokenName()

91
   */
92
  public function getRememberTokenName()
93
  {
94
    return $this->rememberTokenName;
95
  }
96
}

You should have already noticed that App\Models\Auth\User implements the Illuminate\Contracts\Auth\Authenticatable contract.

Most of the methods implemented in our class are self-explanatory. Having said that, we've defined the fetchUserByCredentials method, which retrieves the user from the available back end. In our case, it'll be a MongoDatabase class which will be called to retrieve the necessary information.

So that's the implementation of the User model.

Set Up the Authentication Provider

As we discussed earlier, the Laravel authentication system consists of two elements—guards and providers.

In this section, we'll create an authentication provider, which deals with the user retrieval from the back end.

Go ahead and create a file app/Extensions/MongoUserProvider.php as shown below.

1
<?php
2
// app/Extensions/MongoUserProvider.php

3
namespace App\Extensions;
4
 
5
use Illuminate\Support\Str;
6
use Illuminate\Contracts\Auth\UserProvider;
7
use Illuminate\Contracts\Auth\Authenticatable;
8
 
9
class MongoUserProvider implements UserProvider
10
{
11
  /**

12
   * The Mongo User Model

13
   */
14
  private $model;
15
 
16
  /**

17
   * Create a new mongo user provider.

18
   *

19
   * @return \Illuminate\Contracts\Auth\Authenticatable|null

20
   * @return void

21
   */
22
  public function __construct(\App\Models\Auth\User $userModel)
23
  {
24
    $this->model = $userModel;
25
  }
26
 
27
  /**

28
   * Retrieve a user by the given credentials.

29
   *

30
   * @param  array  $credentials

31
   * @return \Illuminate\Contracts\Auth\Authenticatable|null

32
   */
33
  public function retrieveByCredentials(array $credentials)
34
  {
35
      if (empty($credentials)) {
36
          return;
37
      }
38
 
39
    $user = $this->model->fetchUserByCredentials(['username' => $credentials['username']]);
40
 
41
      return $user;
42
  }
43
  
44
  /**

45
   * Validate a user against the given credentials.

46
   *

47
   * @param  \Illuminate\Contracts\Auth\Authenticatable  $user

48
   * @param  array  $credentials  Request credentials

49
   * @return bool

50
   */
51
  public function validateCredentials(Authenticatable $user, Array $credentials)
52
  {
53
      return ($credentials['username'] == $user->getAuthIdentifier() &&
54
    md5($credentials['password']) == $user->getAuthPassword());
55
  }
56
 
57
  public function retrieveById($identifier) {}
58
 
59
  public function retrieveByToken($identifier, $token) {}
60
 
61
  public function updateRememberToken(Authenticatable $user, $token) {}
62
}

Again, you need to make sure that the custom provider must implement the Illuminate\Contracts\Auth\UserProvider contract.

Moving ahead, it defines two important methods—retrieveByCredentials and validateCredentials.

The retrieveByCredentials method is used to retrieve the user credentials using the User model class which was discussed in the earlier section. On the other hand, the validateCredentials method is used to validate a user against the given set of credentials.

And that was the implementation of our custom authentication provider. In the next section, we'll go ahead and create a guard which interacts with the MongoUserProvider authentication provider.

Set Up the Authentication Guard

As we discussed earlier, the guard in the Laravel authentication system provisions how a user is authenticated. In our case, we'll check the presence of the jsondata request parameter which should contain the JSON-encoded string of the credentials.

In this section, we'll create a guard which interacts with the authentication provider which was just created in the last section.

Go ahead and create a file app/Services/Auth/JsonGuard.php with the following contents.

1
<?php
2
// app/Services/Auth/JsonGuard.php

3
namespace App\Services\Auth;
4
 
5
use Illuminate\Http\Request;
6
use Illuminate\Contracts\Auth\Guard;
7
use Illuminate\Contracts\Auth\UserProvider;
8
use GuzzleHttp\json_decode;
9
use phpDocumentor\Reflection\Types\Array_;
10
use Illuminate\Contracts\Auth\Authenticatable;
11
 
12
class JsonGuard implements Guard
13
{
14
  protected $request;
15
  protected $provider;
16
  protected $user;
17
 
18
  /**

19
   * Create a new authentication guard.

20
   *

21
   * @param  \Illuminate\Contracts\Auth\UserProvider  $provider

22
   * @param  \Illuminate\Http\Request  $request

23
   * @return void

24
   */
25
  public function __construct(UserProvider $provider, Request $request)
26
  {
27
    $this->request = $request;
28
    $this->provider = $provider;
29
    $this->user = NULL;
30
  }
31
 
32
  /**

33
   * Determine if the current user is authenticated.

34
   *

35
   * @return bool

36
   */
37
  public function check()
38
  {
39
    return ! is_null($this->user());
40
  }
41
 
42
  /**

43
   * Determine if the current user is a guest.

44
   *

45
   * @return bool

46
   */
47
  public function guest()
48
  {
49
    return ! $this->check();
50
  }
51
 
52
  /**

53
   * Get the currently authenticated user.

54
   *

55
   * @return \Illuminate\Contracts\Auth\Authenticatable|null

56
   */
57
  public function user()
58
  {
59
    if (! is_null($this->user)) {
60
      return $this->user;
61
    }
62
  }
63
     
64
  /**

65
   * Get the JSON params from the current request

66
   *

67
   * @return string

68
   */
69
  public function getJsonParams()
70
  {
71
    $jsondata = $this->request->query('jsondata');
72
 
73
    return (!empty($jsondata) ? json_decode($jsondata, TRUE) : NULL);
74
  }
75
 
76
  /**

77
   * Get the ID for the currently authenticated user.

78
   *

79
   * @return string|null

80
  */
81
  public function id()
82
  {
83
    if ($user = $this->user()) {
84
      return $this->user()->getAuthIdentifier();
85
    }
86
  }
87
 
88
  /**

89
   * Validate a user's credentials.

90
   *

91
   * @return bool

92
   */
93
  public function validate(Array $credentials=[])
94
  {
95
    if (empty($credentials['username']) || empty($credentials['password'])) {
96
      if (!$credentials=$this->getJsonParams()) {
97
        return false;
98
      }
99
    }
100
 
101
    $user = $this->provider->retrieveByCredentials($credentials);
102
       
103
    if (! is_null($user) && $this->provider->validateCredentials($user, $credentials)) {
104
      $this->setUser($user);
105
 
106
      return true;
107
    } else {
108
      return false;
109
    }
110
  }
111
 
112
  /**

113
   * Set the current user.

114
   *

115
   * @param  Array $user User info

116
   * @return void

117
   */
118
  public function setUser(Authenticatable $user)
119
  {
120
    $this->user = $user;
121
    return $this;
122
  }
123
}

First of all, our class needs to implement the Illuminate\Contracts\Auth\Guard interface. Thus, we need to define all the methods declared in that interface.

The important thing to note here is that the __construct function requires an implementation of Illuminate\Contracts\Auth\UserProvider. In our case, we'll pass an instance of App\Extensions\MongoUserProvider, as we'll see in the later section.

Next, there's a function getJsonParams that retrieves the user credentials from the request parameter named jsondata. As it's expected that we'll receive a JSON encoded string of the user credentials, we've used the json_decode function to decode the JSON data.

In the validate function, the first thing we check is the existence of the $credentials argument. If it's not present, we'll call the getJsonParams method to retrieve user credentials from the request parameters.

Next, we call the retrieveByCredentials method of the MongoUserProvider provider that retrieves the user from the MongoDB database back end. Finally, it's the validateCredentials method of the MongoUserProvider provider that checks the validity of the user.

So that was the implementation of our custom guard. The next section describes how to stitch these pieces together to form a successful authentication system.

Putting It All Together

So far, we've developed all the elements of the custom authentication guard that should provide us with a new authentication system. However, it won't work out of the box as we need to register it in the first place using the Laravel service container bindings.

As you should already know, the Laravel service provider is the right place to implement the necessary bindings.

Go ahead and open the file app/Providers/AuthServiceProvider.php which allows us to add authentication service container bindings. If it doesn't contain any custom changes, you could just replace it with the following contents.

1
<?php
2
// app/Providers/AuthServiceProvider.php

3
namespace App\Providers;
4
 
5
use Illuminate\Support\Facades\Auth;
6
use Illuminate\Support\Facades\Gate;
7
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
8
use App\Services\Auth\JsonGuard;
9
use App\Extensions\MongoUserProvider;
10
use App\Database\MongoDatabase;
11
use App\Models\Auth\User;
12
use Illuminate\Http\Request;
13
use Illuminate\Support\Facades\Config;
14
 
15
class AuthServiceProvider extends ServiceProvider
16
{
17
  /**

18
   * The policy mappings for the application.

19
   *

20
   * @var array

21
   */
22
  protected $policies = [
23
    'App\Model' => 'App\Policies\ModelPolicy',
24
  ];
25
 
26
  /**

27
   * Register any authentication / authorization services.

28
   *

29
   * @return void

30
   */
31
  public function boot()
32
  {
33
    $this->registerPolicies();
34
     
35
    $this->app->bind('App\Database\MongoDatabase', function ($app) {
36
      return new MongoDatabase(config('mongo.defaults.host'), config('mongo.defaults.port'), config('mongo.defaults.database'));
37
    });
38
     
39
    $this->app->bind('App\Models\Auth\User', function ($app) {
40
      return new User($app->make('App\Database\MongoDatabase'));
41
    });
42
 
43
    // add custom guard provider

44
    Auth::provider('mongo', function ($app, array $config) {
45
      return new MongoUserProvider($app->make('App\Models\Auth\User'));
46
    });
47
 
48
    // add custom guard

49
    Auth::extend('json', function ($app, $name, array $config) {
50
      return new JsonGuard(Auth::createUserProvider($config['provider']), $app->make('request'));
51
    });
52
  }
53
 
54
  public function register()
55
  {
56
    $this->app->bind(
57
      'App\Services\Contracts\NosqlServiceInterface',
58
      'App\Database\MongoDatabase'
59
    );
60
  }
61
}

Let's go through the boot method which contains most of the provider bindings.

To start with, we'll create bindings for the App\Database\MongoDatabase and App\Models\Auth\User elements.

1
$this->app->bind('App\Database\MongoDatabase', function ($app) {
2
  return new MongoDatabase(config('mongo.defaults.host'), config('mongo.defaults.port'), config('mongo.defaults.database'));
3
});
4
 
5
$this->app->bind('App\Models\Auth\User', function ($app) {
6
  return new User($app->make('App\Database\MongoDatabase'));
7
});

We've been talking about providers and guards for a while, and it's time to plug our custom guard into the Laravel authentication system.

We've used the provider method of the Auth Facade to add our custom authentication provider under the key mongo. Recall that the key reflects the settings that were added earlier in the auth.php file.

1
Auth::provider('mongo', function ($app, array $config) {
2
  return new MongoUserProvider($app->make('App\Models\Auth\User'));
3
});

In a similar way, we'll inject our custom guard implementation using the extend method of the Auth facade.

1
Auth::extend('json', function ($app, $name, array $config) {
2
  return new JsonGuard(Auth::createUserProvider($config['provider']), $app->make('request'));
3
});

Next, there's the register method which we've used to bind the App\Services\Contracts\NosqlServiceInterface interface to the App\Database\MongoDatabase implementation.

1
$this->app->bind(
2
  'App\Services\Contracts\NosqlServiceInterface',
3
  'App\Database\MongoDatabase'
4
);

So whenever there's a need to resolve the App\Services\Contracts\NosqlServiceInterface dependency, Laravel responds with the implementation of the App\Database\MongoDatabase adapter.

The benefit of using this approach is that one could easily swap the given implementation with a custom implementation. For example, let's say someone would like to replace the App\Database\MongoDatabase implementation with the CouchDB implementation adapter in future. In that case, they just need to add the corresponding binding in the register method.

So that was the service provider at your disposal. At this moment, we have everything which is required to test our custom guard implementation, so the next and concluding section is all about that.

Does It Work?

You've done all the hard work setting up your first custom authentication guard, and now it's time to reap the benefits as we'll go ahead and give it a try.

Let's quickly implement the app/Http/Controllers/MongoController.php controller as shown below.

1
<?php
2
// app/Http/Controllers/MongoController.php

3
namespace App\Http\Controllers;
4
 
5
use App\Http\Controllers\Controller;
6
use Illuminate\Contracts\Auth\Guard;
7
 
8
class MongoController extends Controller
9
{
10
  public function login(Guard $auth_guard)
11
  {
12
    if ($auth_guard->validate()) {
13
      // get the current authenticated user

14
      $user = $auth_guard->user();
15
     
16
      echo 'Success!';
17
    } else {
18
      echo 'Not authorized to access this page!';
19
    }
20
  }
21
}

Take a close look at the dependency of the login method, which requires the implementation of the Illuminate\Contracts\Auth\Guard guard. Since we've set the custom guard as the default guard in the auth.php file, it's the App\Services\Auth\JsonGuard that'll be injected actually!

Next, we've called the validate method of the App\Services\Auth\JsonGuard class, which in turn initiates a series of method calls:

  • It calls the retrieveByCredentials method of the App\Extensions\MongoUserProvider class.
  • The retrieveByCredentials method calls the fetchUserByCredentials method of the App\Models\Auth\User class.
  • The fetchUserByCredentials method calls the find method of the App\Database\MongoDatabase to retrieve the user credentials.
  • Finally, the find method of the App\Database\MongoDatabase returns the response!

If everything works as expected, we should get the authenticated user by calling the user method of our guard.

To access the controller, you should add an associated route in the routes/web.php file.

1
Route::get('/custom/mongo/login', 'MongoController@login');

Try accessing the URL https://your-laravel-site/custom/mongo/login without passing any parameters and you should see the not authorized message.

On the other hand, try something like http://your-laravel-site/custom/mongo/login?jsondata={"username":"admin","password":"admin"} and that should return the success message if the user is present in your database.

Please note that this is just for example purposes to demonstrate how a custom guard works. You should implement a foolproof solution for a feature like a login. In fact, I've just provided an insight into the authentication flow; you're responsible for building a robust and secure solution for your application.

That ends our journey today, and hopefully I'll be back with more useful stuff.

Conclusion

The Laravel framework provides a solid authentication system in the core that could be extended if you want to implement a custom one. That was the topic of today's article: to implement a custom guard and plug it in to the Laravel authentication workflow.

In the course of that, we went ahead and developed a system that authenticates the user based on the JSON payload in the request and matches it with the MongoDB database. And to achieve that, we ended up creating a custom guard and a custom provider implementation.

I hope the exercise has given you an insight into the Laravel authentication flow, and you should now feel more confident about its inner workings.

For those of you who are either just getting started with Laravel or looking to expand your knowledge, site, or application with extensions, we have a variety of things you can study on Envato Market.

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.