Laravel CMS | 10 | Login and Authentication

Video Tutorial

Overview

One of the most important steps you do for your content management system or for any other web application you are trying to create is the authentication system, where it plays a major role on defining specific permissions for specific authorized users whether you are using Laravel or other Frameworks.

For our CMS we are going to create an authentication system responsible for authorizing admins through a login form whenever they try to access the admin panel.

Login Controller

First, let’s make the main controller for our login system

# No need for a resource controller 
php artisan make:controller AdminLoginController

Now if you can notice that there is an Auth folder under the Controllers folder, make sure to move the controller into their since it is responsible for authentication, this is just for making your application a bit more organized.

We need include a couple of builtin laravel classes for the login.

<?php
//Change Namespace 
namespace App\Http\Controllers\Auth;
//Include Auth and other classes 
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Auth;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Support\Facades\Hash;

class AdminLoginController extends Controller
{
    //Login and Authentication Controller

    use ThrottlesLogins;

}

Also, you need to change the Admin model it is been inherited from the Model class and since we are going to use the Admin as a login model so we need to change the Model class with Laravel Auth class.

//Admin Model Class
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Admin extends Authenticatable
{
    use Notifiable;
    //Which fileds are going to filed on the login form 
    protected $fillable = [
        'name', 'email', 'password',
    ];
    //Hidden Fields (Password) for protecting your admin's data
    protected $hidden = [
        'password', 'remember_token',
    ];
    //Admin Model
    protected $table = "admin";
}

And make sure to name the admin table password filed under the database as (password) not (hash_password) as we have named it in the last tutorial cause laravel only accepts password fields and change the migrations.

Configure Laravel Authentication

We need to specify an additional configuration to laravel for our login system to work fine. Open up config folder and find auth.php

Add new providers for the admin and the admin guard.

//auth.php
//Authentication Guards 
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

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

    "admin" => [
        "driver" => "session",
        "provider" => "admins"
    ]
],
//Providers 
'providers' => [
'users' => [
    'driver' => 'eloquent',
    'model' => App\User::class,
],

"admins" => [
    "driver" => "eloquent",
    "model" => App\Admin::class,
]]

In the above configuration, we are creating a new provider naming it admins and we give a model which is our admin model class, then we create a new guard as admin and assign the provider. We use the session driver since we want from our admin to login only once in a single session.

Admin Login Page

create the blade template for the login page, this depends on how you want to customize the login page it should very simple all you need is a form with username, email, and password.

@extends("layouts.app")
@section("main-row")
    <div id="main-cms-login" class="col-sm-12">

        <div id="cms-login-header">
            Login To The Admin Panel
        </div>

        <div id="cms-login-container">
            {!! Form::open(["route" => "login.submit", "method" => "POST"]) !!}
                <div class="form-group">
                    {!! Form::label('username', 'Username', []) !!}
                    {!! Form::text('username', '', ['class' => 'form-control', 'placeholder' => 'User Name']) !!}
                    @if ($errors->has('username'))
                        <span class="help-block">
                            <strong class="text-danger">{{ $errors->first('username') }}</strong>
                        </span>
                    @endif
                </div>
                <div class="form-group">
                    {!! Form::label("email", "Email", []) !!}
                    {!! Form::text('email', '', ['class' => 'form-control', 'placeholder' => 'Email']) !!}
                    @if($errors->has('email'))
                        <span class="help-block">
                            <strong class="text-danger">{{ $errors->first('email') }}</strong>
                        </span>
                    @endif
                </div>
                <div class="form-group">
                    {!! Form::label('password', 'Password', []) !!}
                    {!! Form::password('password', ['class' => 'form-control', 'placeholder' => 'Password']) !!}
                    @if ($errors->has('password'))
                        <span class="help-block">
                            <strong class="text-danger">{{ $errors->first('password') }}</strong>
                        </span>
                    @endif
                </div>

                {!! Form::submit('Login!', ['class' => 'btn btn-success btn-block']) !!}

            {!! Form::close() !!}
        </div>
    </div> <!-- Main Container -->
@endsection

You can use the above HTML Structure it is being powered by bootstrap to make it looks a bit better (prettier).

Login System

First, let’s valid the input fields that are being submitted by the login form to make sure that we have a valid input data and then we check if the admin exists in the database using the provided password from the credentials.

public function login(Request $request) {
    //Validate Form
    $this->validate($request, ["username" => "required", "email" => "required|email", "password" => "required"]);
    //Credentials Array
    $credentials = ["username" => $request->username, "email" => $request->email, "password" => $request->password];
}

Finally, if the user information is right then we can authenticate it with the CMS, for authentication there are a plenty of ways to do it and laravel uses a session token auth system where a unique hash token gets created using the admin’s credentials (to make sure it is unique) and get saved on cookie in the current session and when ever we send a request to the server laravel checks for us for the token under the cookie if it does exists then we can view the protected content otherwise it redirect us into the login form.

...
//Check For Valid Admin and Authenticate
if(Auth::guard('admin')->validate($credentials, false)) {
    //Authenticate (Create and Save Token)
    $this->authenticate($credentials);
    //Welcome Back, Admin!
    session()->flash("Success", "Welcome Back " . $credentials["username"]);

    //Redirect To Dashboard //Success
    return redirect(route("category.index"));
}
//Error
return back()->with('Error', "Username/Email and/or Password are Incorrects");
...

Also, we need to provide the implementation of the authenticate method for login in admins.

public function authenticate($credentials) {
    //Retrieve Admin using Credentials
    $admin = Auth::guard("admin")->getProvider()->retrieveByCredentials($credentials);
    //Authorize Admin (generate and put token under cookie)
    Auth::guard("admin")->login($admin, false);
}

Now if the admin is logged in then he can access the restricted (protected) routes but we first need to tell it which routes are eligible for guest access or admins only access, therefore we use what is called a middleware.

Middleware is a piece of a function that runs on every request gets submitted to the server, they are used for checking request parameters in our case the middleware would check for the cookie token.

We are going to use two types of middleware, guest middleware which allows anyone to access and view the resource and Auth middleware only allow authenticated users (Logged in admins) to access the resource if they have no right to, the middleware will automatically redirect the request to the login page.

//AdminLoginController.php
public function __construct() {
   //Login Page can be viewd by anyone 
   $this->middleware("guest:admin");
}

For restricting other pages (Category page, AddNewPost…) we use the same middleware under the constructor but just change it from guest to auth.

//Category Page or AddNewPost or any other page you would like to protect 
//Since we are working on a CMS, we have to protect all the different pages
public function __construct() {
    $this->middleware("auth:admin");
}

Make sure to add the same middleware to the other pages as well.

What’s Next

So now you should be able to secure your own laravel application using the built-in authentication system, we still need more features for the login system to be ready for website use such as limiting login attempts and remember password.

No Comments Yet