In this tutorial, we will build a multiple guards authentication allowing users and admins to login separately. This will be 2 parts series because we do have quite a bit of work to do and I will be explaining all the things that you need to know about custom authentication. Let’s get started.
What we will be doing
- Custom Guard, Model and Migration for Admin.
- Routes, Views, and Controllers for Admin.
- Manual Authentication.
- Login Throttling.
- Password Reset.
Let’s start by creating a new laravel project with composer:
composer create-project laravel/laravel multiauth
First thing we will do is add the database credentials to the .env file:
Start the development server with artisan (you can use a virtual host if you want):
php artisan serve
Admin Model and Migration
Let’s create a model as well as a migration for our admin:
php artisan make:model Admin -m
First, open the create_admins_table.php (prepended with a timestamp) and modify the up() method:
These fields are same as the users table fields but you can add more if you want. rememberToken() will create a column “remember_token” for remember me cookie. Let’s modify our Admin model:
A typical model would extends an eloquent model but we are using this model for authentication so we will extend it with authenticatable which is an alias to User class used for laravel authentication. We are using notifiable trait which will be used for password reset notification. We also have fillable attributes “name”, “email”, “password” for mass assignment and hidden attributes “password” and “remember_token” that are hidden for mass updates. (this model is identical to the User model, just a different class).
Laravel uses guards for authentication which allows you to manage multiple authenticated instances from multiple tables. To create a new guard open the auth.php from the config directory:
Inside the auth config array, we have four keys namely defaults, guards, providers, and passwords:
Defaults array is used to specify a default guard and default password reset setting. Web guard is used for default session based authentication. Users array inside the passwords array will be used as default passwords setting when resetting a password. You can also change these defaults to your preferred settings.
By default, there are two guards namely web and api. Laravel supports two types of authentication session-based and token-based (api authentication). A guard key has an array for it’s value and that array has two key-value pairs. First driver and second is provider.
Providers are used to define how our users will be retrieved and how the user data with be stored after authentication. Laravel supports eloquent and database drivers. We are using eloquent so we will define the model that will be used for authentication and if you want to use the database driver then you will need to define the database table where the users are stored.
All the settings related to resetting a user’s password are defined in passwords array. provider is the setting we talk in above section and table is the name of the table where all the password reset tokens will be stored. expire will define the expiry of the reset token (in minutes). We have set the token expiry to 60 minutes but you can change it if you want.
We will be using grouped routes so we don’t have to repeat certain things and we will store all of our admin controllers in a sub directory called Admin. For example, all the routes will have admin like /admin/other/route so we can use prefix() method and we are also using named routes so we need all our route to have “admin.” prefix when naming them. Last thing will be the namespace Admin because laravel uses psr-4 autoloading and all the classes need to have a namespace:
Now you won’t need to repeat yourself like:
Now whenever you define a route for admin users inside the group, you will simply do (add it to inside admin routes for dashboard view):
Let’s define all the authentication routes inside the admin routes group:
Since all the authentication controllers will be created inside Controllers/Admin/Auth so we are using group routes again inside the admin group routes. (you can also group password routes with a prefix of /password if you want). All routes and controller method names are identical to the routes created by make:auth command.
Let’s first generate the authentication scaffolding with artisan:
php artisan make:auth
I want to customize the layout file so open the app.blade.php inside layouts file and remove all the markup then add:
Above is a basic layout using bootstrap-4 that comes with laravel. We have a separate navbar inside the inc folder. “status” key will be used for success flash messages and “error” key will be used for error messages. I have also added a bit of css in the head that will animate the bootstrap alert and with jquery we are closing the alert after 3 seconds (you can change it if you want). Let’s create the navbar.blade.php inside the inc folder and add the following markup:
Above markup is taken from the default laravel layout but this navbar has two dropdown menus, one for our user and the other for our admin. I have also added ADMIN text with the name of the admin user just so you can tell the difference between both guards and we are not putting the admin login link on the navbar so you will have to specify the url in the browser’s url field (we don’t need an admin link on the navbar). It seems like whenever an admin is logged in, the default guard is overridden by the admin guard and retrieves the admin user so you will have to specify the web guard in @if instead of using @auth or @guest directives (I will update it if I find the solution).
For the admin views, create a folder called admin inside views directory and inside that folder create a view named home.blade.php and paste all the markup from home.blade.php inside views directory. For login admin login view, we will just modify the login.blade.php from the auth folder:
We have three variables $title, $loginRoute, and $forgotPasswordRoute instead of hard coded values so we can reuse this view for our both user and admin login. Now whenever we will use this view, we will define these values in the controller and pass them to the view.
Let’s create all the authentication controllers for our admin:
We also need a HomeController:
php artisan make:controller Admin/HomeController
HomeController will only have index() method which will simply return a view:
Finally, we can work on our LoginController so open the controller and define these methods:
As you can see that we have already defined the code inside the showLoginForm() method which is returning the login view. we also have to override the showLoginForm() inside the user LoginController so open the LoginController from Controllers\Auth directory and add the below method:
Let’s work on the login() method of our admin LoginController. First we will validate the form and to keep things clean, I have created a separate method for validation called validator(). Let’s add the code:
We are using exists rule to determine whether the email exists or not and customizing the error message saying “credentials” instead of just “email” so a hacker does not know that email is not registered in the database. We also have a loginFailed() method which is just used to redirect the admin back with input after a login has failed:
Now we will Complete the login() method:
We are using attempt() method to login the admin. $request->only() will return an array of specified fields and $request->filled(‘remember’) will see if the remember me checkbox was checked or not. After a successful login, admin will be redirected to the intended route if available else to the admin dashboard. Suppose you were going to /admin/my/desired/url but you were not logged in and got redirected back to the login form and when you login, you get redirect to the admin dashboard instead of that url and that’s where intended() method comes in handy, It will redirect you back to that url after login if available (if you want to learn more about authentication then read my recent tutorial on medium).
Whenever you use Auth for admin guard then don’t forget to specify the guard, e.g Auth::guard(‘admin’)->yourAuthMethod()
All you need to do in logout() method is call the Auth::logout() and redirect the admin to the login form:
By default, when a normal user logs out then all the session data will be flushed out and regenerated which will also logout the admin. If you don’t want to flush the session then override the default trait method by defining a logout() method in LoginController inside the Controllers/Auth directory:
You can create register functionality if you need but I will create a default admin with tinker which is a CLI tool that comes with laravel so go to your terminal and start tinker with:
php artisan tinker
Now you can type or paste the below commands/code in your terminal:
Now you can test the login by registering a normal user and logging into both admin and user accounts. Next tutorial will be about middleware, login throttling, and forgot password.
Thanks for reading the tutorial and let’s continue to the next part:
Laravel Multiple Guards Authentication: Middleware, Login Throttle, and Password Reset
We will customize the auth and guest middleware and add login throttling. Lastly, we will work on the password reset…
You can find the complete source code here: