Laravel E-Commerce Application Development – Backend Admin Authentication

Laravel E-Commerce Application Development – Backend Admin Authentication

Laravel E-Commerce Application Development ( 26 Lessons )

In this course, you’ll learn how to create an E-Commerce Website from scratch in Laravel. The process has never been easier I’ll take you from the very beginning stages of setting up Laravel till the last steps of adding products to the cart. If you’ve good understanding & experience in PHP & MySQL then this course is for you.

see full series
  1. Laravel E-Commerce Application Development – Introduction
  2. Laravel E-Commerce Application Development – Initial Project Setup
  3. Laravel E-Commerce Application Development – Assets Setup Using Laravel Mix
  4. Laravel E-Commerce Application Development – Admin Model and Migration
  5. Laravel E-Commerce Application Development – Backend Admin Authentication
  6. Laravel E-Commerce Application Development – Base Controller and Repository
  7. Laravel E-Commerce Application Development – Settings Section Part 1
  8. Laravel E-Commerce Application Development – Settings Section Part 2
  9. Laravel E-Commerce Application Development – Categories Section Part 1
  10. Laravel E-Commerce Application Development – Categories Section Part 2
  11. Laravel E-Commerce Application Development – Attributes Section Part 1
  12. Laravel E-Commerce Application Development – Attributes Section Part 2
  13. Laravel E-Commerce Application Development – Attributes Section Part 3
  14. Laravel E-Commerce Application Development – Brands Section
  15. Laravel E-Commerce Application Development – Products Section Part 1
  16. Laravel E-Commerce Application Development – Products Section Part 2
  17. Laravel E-Commerce Application Development – Products Section Part 3
  18. Laravel E-Commerce Application Development – Products Section Part 4
  19. Laravel E-Commerce Application Development – Frontend Login & Registration
  20. Laravel E-Commerce Application Development – Categories Navigation
  21. Laravel E-Commerce Application Development – Catalog Listing
  22. Laravel E-Commerce Application Development – Product Details Page
  23. Laravel E-Commerce Application Development – Shopping Cart
  24. Laravel E-Commerce Application Development – Checkout
  25. Laravel E-Commerce Application Development – Payment Processing
  26. Laravel E-Commerce Application Development – Wrap Up

This is the fourth part of the Laravel E-Commerce Application Development series, in this part will implement the admin authentication using Laravel guards.

I assume you should have the e-commerce application project on your machine or you can grab it from Laravel E-Commerce Application repository, we will start from where we left it in the last part.

In the last part, we created the admin model, migration and seed, in this post we will implement authentication for the admin area. Laravel’s default authentication works with the User model but we will implement our own login functionality for Admin model which means we are implementing adding multiple authentication for different models.

Setting Up Admin Guard

First this we have to add the admin guards in the config/auth.php file so Laravel will know which model we are trying to use for the admin authentication. Open you config/auth.php file and find guards array which will looks like this one.

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'token',
        'provider' => 'users',
        'hash' => false,
    ],
],

As you can see in this array Laravel defining the two different guards one for web application and on for the api. We will add our own guards for admin like below. Copy the below code and replace with the default guards array.

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'token',
        'provider' => 'users',
        'hash' => false,
    ],

    'admin' => [
        'driver' => 'session',
        'provider' => 'admins',
    ],

    'admin-api' => [
        'driver' => 'token',
        'provider' => 'admins',
        'hash' => false,
    ],
],

As you can see we have added the admin and admin-api guard so our application can use two different types of model for authentication purpose. In admin array we are defining session as a authentication driver which will use the admins provider and same for the admin-api array, basically we just copied the default guards and changed the values for them.

As you can see, we have defined the providers in both admin and admin-api to admins. Now we will add a new provider in auth.php config file.

The next array element is the providers, which looks like below.

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
],

As you can see in this array there is a users provider, so to add our admins provider we will simply copy the users provider and change its values to the admin ones like below.

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
    'admins' => [
        'driver' => 'eloquent',
        'model' => App\Models\Admin::class,
    ],
],

In the above code example, we added a new provider which is admins and it uses the eloquent as it’s driver. Next we defined the model which will be used for this provider which is App\Models\Admin::class.

Next, in the passwords array, we will define which table will be used to add the functionality for the admin password reset. We will copy the existing users one and replace it to admins.

'passwords' => [
    'users' => [
        'provider' => 'users',
        'table' => 'password_resets',
        'expire' => 60,
    ],
    'admins' => [
        'provider' => 'users',
        'table' => 'password_resets',
        'expire' => 60,
    ],
],

As you can see, for password we have just added the guard name admins and used the same details as users one, which means we will use the same password_reset table for the admins password reset functionality.

That’s it for the guard’s changes, now we will add the login functionality for the admin users.

Adding Admin Auth Routes

Now we will add the login routes for admin authentication, as we will be implementing a complete backend in this series, it’s right time to create a new routes file and separate all admin routes in a separate file.

Learn More

You can learn more about the Laravel Routing by reading the Laravel Routing Made Easy post.

Go ahead and create a new PHP file in routes folder called admin.php. Now in our routes/web.php file, we will add the below line to include the admin routes into the web.php file.

require 'admin.php';

In part two of this series, we added the below routes just for checking the admin views.

Route::view('/admin', 'admin.dashboard.index');
Route::view('/admin/login', 'admin.auth.login');

Go ahead and delete them from routes/web.php file as we will add the actual routes for admin in admin.php file.

In admin.php file, add the below routes.

Route::group(['prefix'  =>  'admin'], function () {

    Route::get('login', 'Admin\[email protected]')->name('admin.login');
    Route::post('login', 'Admin\[email protected]')->name('admin.login.post');
    Route::get('logout', 'Admin\[email protected]')->name('admin.logout');

    Route::get('/', function () {
        return view('admin.dashboard.index');
    });

});

Let’s go through each routes one by one. Firstly, we are adding a routes group to prefix all our admin routes with /admin. Next within this route group we added the login routes, first one is the GET route (/admin/login) which will load the admin login page. Next one is the POST route (/admin/login), where we will send the post request for authentication. Next one is the logout route (/admin/logout) which will be again a GET request.

The last one is the dashboard route which will map to /admin URL and will load the dashboard view of admin.

We will protect the dashboard view for authenticated admins, in the coming sections of this post.

Creating Admin Auth Controller

As you have seen, in the last section our all routes are pointed to Admin\LoginController. We will create a new controller using the artisan command. Go to your terminal and run the below command.

php artisan make:controller Admin\\LoginController

Above command will generate a LoginController in the app/Http/Controllers/Admin folder. Open your LoginController and replace with the below one.

namespace App\Http\Controllers\Admin;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    use AuthenticatesUsers;

    /**
     * Where to redirect admins after login.
     *
     * @var string
     */
    protected $redirectTo = '/admin';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest:admin')->except('logout');
    }

    /**
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function showLoginForm()
    {
        return view('admin.auth.login');
    }
}

Let me go through with this code step by step. Firstly we added the AuthenticatesUsers trait which Laravel provides for authenticating users and then used this trait like below.

use AuthenticatesUsers;

Next we defined the $redirectTo property to define which admin users will be redirected after successfully login.

/**
     * Where to redirect admins after login.
     *
     * @var string
     */
    protected $redirectTo = '/admin';

Next we added the constructor for this controller to use the guest middleware for admins except logout method which will add in the coming section.

/**
 * Create a new controller instance.
 *
 * @return void
 */
public function __construct()
{
    $this->middleware('guest:admin')->except('logout');
}

In the last section, we pointed our login route to showLoginForm method in the LoginController controller, so we will add that and return a login page view.

/**
 * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
 */
public function showLoginForm()
{
    return view('admin.auth.login');
}

In the above method we are loadin a login view from admin/auth folder.

Creating Admin Login Page

Now we will add a new file in resources/views/admin/auth folder named login.blade.php. Add the below HTML markup code in this file.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" href="{{ asset('backend/css/main.css') }}" />
    <link rel="stylesheet" type="text/css" href="{{ asset('backend/css/font-awesome/4.7.0/css/font-awesome.min.css') }}"/>
    <title>Login - {{ config('app.name') }}</title>
</head>
<body>
<section class="material-half-bg">
    <div class="cover"></div>
</section>
<section class="login-content">
    <div class="logo">
        <h1>{{ config('app.name') }}</h1>
    </div>
    <div class="login-box">
        <form class="login-form" action="{{ route('admin.login.post') }}" method="POST" role="form">
            @csrf
            <h3 class="login-head"><i class="fa fa-lg fa-fw fa-user"></i>SIGN IN</h3>
            <div class="form-group">
                <label class="control-label" for="email">Email Address</label>
                <input class="form-control" type="email" id="email" name="email" placeholder="Email address" autofocus value="{{ old('email') }}">
            </div>
            <div class="form-group">
                <label class="control-label" for="password">Password</label>
                <input class="form-control" type="password" id="password" name="password" placeholder="Password">
            </div>
            <div class="form-group">
                <div class="utility">
                    <div class="animated-checkbox">
                        <label>
                            <input type="checkbox" name="remember"><span class="label-text">Stay Signed in</span>
                        </label>
                    </div>
                </div>
            </div>
            <div class="form-group btn-container">
                <button class="btn btn-primary btn-block" type="submit"><i class="fa fa-sign-in fa-lg fa-fw"></i>SIGN IN</button>
            </div>
        </form>
    </div>
</section>
<script src="{{ asset('backend/js/jquery-3.2.1.min.js') }}"></script>
<script src="{{ asset('backend/js/popper.min.js') }}"></script>
<script src="{{ asset('backend/js/bootstrap.min.js') }}"></script>
<script src="{{ asset('backend/js/main.js') }}"></script>
<script src="{{ asset('backend/js/plugins/pace.min.js') }}"></script>
</body>
</html>

Above view is displaying a simple login form with email address field and a password field. We have added the form action to point to our post login route which is named as admin.login.post.

Now if you visit /admin/login URL, you will be presented with the login form something like below.

Admin Login Page
Admin Login Page

Adding Admin Login Functionality

Now as we have the login page ready but it’s not functional at the moment. To make this login form functional we need to add login() method to our LoginController. Open LoginController and add the below code.

/**
 * @param Request $request
 * @return \Illuminate\Http\RedirectResponse
 * @throws \Illuminate\Validation\ValidationException
 */
public function login(Request $request)
{
    $this->validate($request, [
        'email'   => 'required|email',
        'password' => 'required|min:6'
    ]);
    if (Auth::guard('admin')->attempt([
        'email' => $request->email,
        'password' => $request->password
    ], $request->get('remember'))) {
        return redirect()->intended(route('admin.dashboard'));
    }
    return back()->withInput($request->only('email', 'remember'));
}

Now add the Auth facade in the controller like below:

use Auth;

In the login method, we are firstly validating the user input for email and password. Then we are using the Auth:: facade to define our admin guard and then making the attempt to authenticate the admin user.

If the authentication is successful we are redirecting the admin users to admin.dashboard route which loads the admin dashboard view. If authentication is not successful then we are returning the user back to the login page.

At this point, you can load the login page and test the login page, but I recommend that you complete the full post and then try it.

Adding Admin Logout Functionality

Next we will add the logout function to LoginController class. Open LoginController class and add the below function.

/**
 * @param Request $request
 * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
 */
public function logout(Request $request)
{
    Auth::guard('admin')->logout();
    $request->session()->invalidate();
    return redirect()->route('admin.login');
}

Now open resources/views/admin/partials/header.blade.php file and replace the Logout link from:

<a class="dropdown-item" href="page-login.html"><i class="fa fa-sign-out fa-lg"></i> Logout</a>

to:

<a class="dropdown-item" href="{{ route('admin.logout') }}"><i class="fa fa-sign-out fa-lg"></i> Logout</a>

Now we have a working, log out for the admin area.

Redirecting Authenticated Admin To Dashboard Page

Now we have added the login functionality, we want to make sure if an admin is authenticated then redirect them to the dashboard page when they try to load the login route again. As they are already logged in so there is no point to show them the login page.

For this we need to adjust the RedirectIfAuthenticated middleware which comes with the Laravel and located at app/Http/Middleware. Open this middleware and update the handle() method with the below one.

/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @param  string|null  $guard
 * @return mixed
 */
public function handle($request, Closure $next, $guard = null)
{
    switch($guard){
        case 'admin':
            if (Auth::guard($guard)->check()) {
                return redirect('/admin');
            }
            break;
        default:
            if (Auth::guard($guard)->check()) {
                return redirect('/');
            }
            break;
    }
    return $next($request);
}

In this method, we are adding a switch statement for the $guard value. If $guard value is admin then checking if its authenticated then retrun to the /admin which is our dashboard route.

If the $guard value is user then we are returning to the making website homepage /.

Redirecting Unauthenticated Admin To Login Page

Next, we want to make a check if the admin is not authenticated then don’t let them load the dashboard view instead redirect them to the login page. For this open app/Exceptions/Handler.php file and add the below method at the bottom of the class.

/**
 * @param \Illuminate\Http\Request $request
 * @param AuthenticationException $exception
 * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\Response
 */
protected function unauthenticated($request, AuthenticationException $exception)
{
    if ($request->expectsJson()) {
        return response()->json(['message' => $exception->getMessage()], 401);
    }
    $guard = array_get($exception->guards(), 0);
    switch($guard){
        case 'admin':
            $login = 'admin.login';
            break;
        default:
            $login = 'login';
            break;
    }
    return redirect()->guest(route($login));
}

In the above method, we are getting the current guard from the AuthenticationException class and running the switch statement on it. Based on the guard value we are redirecting the user to the right login page.

Don’t forget to import, AuthenticationException class in the top of the class like below:

use Illuminate\Auth\AuthenticationException;

Now we will protect our dashboard route, so only authenticated admin can load the dashboard view. Open admin.php routes file and replace the dashboard route with below one.

Route::group(['middleware' => ['auth:admin']], function () {

    Route::get('/', function () {
        return view('admin.dashboard.index');
    })->name('admin.dashboard');

});

We are adding the admin.dashboard route into a route group and passing the middleware auth:admin so that all the admin routes under this group will be protected using the admin guard.

Testing

Now you can go ahead and try to login the admin using email [email protected] and password is password. Try to load the login page when admin is logged in, you will be redirected to dashboard view. Also try to load the dashboard page without login as admin and you will be redirected to the login page.

Conclusion

In this part, we have successfully created the login functionality for admin users. In the next part of this series, we will start adding some core functionalities which we will be using throughout our application like a base repository, base form request, and base controller.

Code Repository

You can find the code base of this series on Laravel eCommerce Application repository.

If you have any question about this post, please leave a comment in the comment box below.

34 comments on “Laravel E-Commerce Application Development – Backend Admin Authentication

    1. Thanks boris.

      You are getting response Route [login] not defined because in Handler.php file we are sending admins to admin.login route and other users to login route.

      If you simply add in your web.php file Auth::routes();, that will resolve the issue for time being. But later in this series I will be adding customers login then we have to redefine these routes as it will be totally a custom authentication either with username or email.

      Thanks again.

  1. Hi, I am getting this error:-
    Argument 2 passed to Illuminate\Auth\SessionGuard::__construct() must be an instance of Illuminate\Contracts\Auth\UserProvider, null given, called in E:\xampp72\htdocs\laravel\ecommerce\vendor\laravel\framework\src\Illuminate\Auth\AuthManager.php on line 125

    How to solve it.

  2. Hi,
    I follow the tutorial till the try to login section.
    I get a error “Undefined index: driver”.
    not sure how to solve it.

      1. Hi,
        Think found the solution. Just check that it didn’t read the .env file to get database information to connect.

        After using this,”php artisan config:clear” , it manage to read .env file.

  3. hi i worked through till the login page everything is working fine but after the implimentation of the (Redirecting Unauthenticated Admin To Login Page) my page stops loading i restarted the server and it give the following error in the termina

    C:\wamp64\www\ecommerce-application\app\Exceptions\Handler.php on line 60
    [Sat Jun 22 15:02:07 2019] PHP Fatal error: Exception thrown without a stack frame in Unknown on line 0

    1. Double check your middleware code might be something missing. If you have a github repo I can look into the issue.

      Thanks

  4. Great tutorial, I’ve been learning new stuff about Laravel, thanks for sharing your
    knowledge. Doing my homework, I was able to simplify the file code admin.php as following:

    Route::namespace(‘Admin’)->prefix(‘admin’)->group(function () {

    Route::get(‘login’, ‘[email protected]’)->name(‘admin.login’);
    Route::post(‘login’, ‘[email protected]’)->name(‘admin.login.post’);
    Route::get(‘logout’, ‘[email protected]’)->name(‘admin.logout’);

    Route::middleware([‘auth:admin’])->group(function () {
    Route::get(‘/’, function () {
    return view(‘admin.dashboard.index’);
    })->name(‘admin.dashboard’);
    });

    });

  5. Hi there,
    brilliant tutorial.
    I have a question, how can I get error messages on login page if password is not correct or just the account do not exists?
    Thanks

    1. Change the array_get() function in app/Exceptions/Handler.php file to Arr::get() and include the class like this.

      use Illuminate\Support\Arr;

      Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

*When sharing a code snippet please wrap you code with pre tag and add a class code-block to it like below.
<pre class="code-block">you code here</pre>

*
*

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Your little help will keep this site alive and help us to produce quality content for you.