Laravel 8 Multiauth


laravel application हमें कई सारे authentication packages provide करता है। इस topic आप सीखेंगे कि breeze authentication package का use करके multi authentication कैसे बनाते हैं।

multi authentication means ऐसा application जिसमे अलग तरह के users हो सकते हैं like : user , admin & many more.


इस topic में हम laravel में Breeze Authentication Package की help से दो user (User & Admin) को manage करेंगे।

What is laravel breeze

laravel में breeze package authentication के लिए use किया जाता है , जो कि आपको hand to hand , user registration , login , reset password etc provide करता है।

I Hope, आप breeze auth package से aware होंगे और हम यह मानकर चलते हैं कि आपने application में breeze auth package install कर लिया है। अगर install नहीं किया है तो आप Laravel Install Breeze article पढ़कर install कर लें।


तो जब laravel application में breeze package install करते हैं तो by default user के लिए तो users table automatically बन जाती है। admin users manage करने के लिए हमें अलग से एक admins table बनानी पड़ेगी।


बनाने के लिए command line open करें और type करे -

 php artisan make:migration create_admins_table

इसके बाद database/migrations/ folder में create_admins_table.php file मिलेगी जिसमे हमें कुछ extra fields add करने हैं।

File : database / migrations / 2021_12_04_045932_create_admins_table.php

Copy Fullscreen Close Fullscreen
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAdminsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('admins', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('admins');
    }
}

file save करें and run करें -
php artisan migrate
ये command run करते ही आपके database में एक admins name की table create हो जायगी।

Laravel Set guards

Next, हमें users को manage करने के लिए guards create करने के लिए config/auth.php file open करें -

in guards array put these line of code :
---------------------------------------------------------------
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

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

make some changes In providers array.
--------------------------------------

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

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

finally change passwords array.
-----------------------------------

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

    'admins' => [
        'provider' => 'admins',
        'table' => 'password_resets',
        'expire' => 60,
        'throttle' => 60,
    ],
],
What did we just do?

basically auth.php file में ये define किया है कि कौन सा user किस table से manage होगा। हालाँकि password reset करने के लिए हम users & admins दोनों के लिए एक ही table use करेंगे , आप चाहो तो दूसरी table भी ले सकते हैं।

Prepare Admin Model

अब हमें guards में define किया गया Admin model बनाना होगा जिसमे कुछ changes करने होंगे।

php artisan make:model Admin

File : app/Models/Admin.php

Copy Fullscreen Close Fullscreen
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use App\Notifications\AdminResetPasswordNotification;
class Admin extends Authenticatable 
{
    use HasFactory, Notifiable;
    protected $guard = 'admin';
    /**
     * The attributes that are mass assignable.
     *
     * @var array
    */
    protected $fillable = ['name', 'role_id', 'email', 'password'];

     /**
      * The attributes that should be hidden for arrays.
      *
      * @var array
     */
     protected $hidden = [ 'password', 'remember_token'];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = ['email_verified_at' => 'datetime'];

    /**
     * this method will use when we reset password for admin
     * @param $token
    */
    public function sendPasswordResetNotification($token)
   {
        $this->notify(new AdminResetPasswordNotification($token));
   }
}

अगर आप ध्यान से देखेंगे तो पायंगे कि एक AdminResetPasswordNotification class use किया गयी जिसके through हमें admin के लिए password reset करेंगे। इसके लिए हमें notification बनाना पड़ेगा।

php artisan make:notification AdminResetPasswordNotification

इसके बाद app / Notifications / AdminResetPasswordNotification.php file open करें और resetUrl() function में वो route name दे जिसपर admin अपना password reset करेगा।

protected function resetUrl($notifiable)
    {
        if (static::$createUrlCallback) {
            return call_user_func(static::$createUrlCallback, $notifiable, $this->token);
        }

        return url(route('admin.password.reset', [
            'token' => $this->token,
            'email' => $notifiable->getEmailForPasswordReset(),
        ], false));
    }

Define Routes For Admin

By default normal user के लिए तो breeze package routes automatically add करता है , हमें सिर्फ admin routes add करने पड़ेंगे।

add these routes in routes/web.php file
----------------------------------------------------------------------

/** 
* Admin Routes
* prefix : admin, so that we don't need to specify every time
* namespace Admin, we make controllers in Constrollers/ folder
* name : admin, now we can access every route admin.routename
*/
Route::prefix('admin')->namespace('Admin')->name('admin.')->group(function()
{
    //middleware guest so that , login user could not access
    Route::middleware(['guest:admin'])->namespace('Auth')->group(function()
    {	
        //login controller
	Route::get('login', 'AdminLoginController@create')->name('login');
	Route::post('login', 'AdminLoginController@store')->name('authenticate');
		
        //forget pasword
	Route::get('forgot-password', 'AdminForgetPasswordController@forget_password')->name('password.request');
	Route::post('forgot-password', 'AdminForgetPasswordController@send_reset_link')->name('password.email');

        //reset password
        Route::get('reset-password/{token}', 'AdminForgetPasswordController@reset_password')->name('password.reset');
	Route::post('reset-password', 'AdminForgetPasswordController@update_password')->name('password.update');
    });

    //use auth:admin login so that only login user can access these routes
    Route::middleware(['auth:admin'])->group(function()
    {	
	Route::get('/', 'AdminHomeController@home') ->name('home');
	Route::get('logout', 'AdminHomeController@destroy')->name('logout');
    });
});

Prepare middleware

अब जो भी middlewares (guest , auth) को हमें routes में use किया है , उनमें admin के according middlwares changes करने पड़ेंगे।

File: app/Http/Middleware/Authenticate.php

Copy Fullscreen Close Fullscreen
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
    /**
     * Get the path the user should be redirected to when they are not authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return string|null
     */
    protected function redirectTo($request)
    {
        if (! $request--->expectsJson()) 
        {
            if(str_contains('admin', $request->path()))
                return route('admin.login');

            return route('login');
        }
    }
}

File: app / Http / Middleware / RedirectIfAuthenticated.php

Copy Fullscreen Close Fullscreen
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  ...$guards
     * @return mixed
     */
    public function handle(Request $request, Closure $next, ...$guards)
    {
        $guards = empty($guards) ? [null] : $guards;

        foreach ($guards as $guard) 
        {
            if (Auth::guard($guard)->check()) 
            {
                if ($guard === 'admin')
                   return redirect(route('admin.home'));

                return redirect(RouteServiceProvider::HOME);
            }
        }

        return $next($request);
    }
}

Prepare Controllers

Run these commands.
----------------------------------------

php artisan make:controller Admin/Auth/AdminLoginController
php artisan make:controller Admin/Auth/AdminForgetPasswordController
php artisan make:controller Admin/AdminHomeController

Controllers create करने के बाद files में code को replace करें।

Replace this code in app / Http / Controllers / AdminLoginController.php

Copy Fullscreen Close Fullscreen
<?php
namespace App\Http\Controllers\Admin\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\AdminLoginRequest;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AdminLoginController extends Controller
{
    /**
     * Display the login view.
     *
     * @return \Illuminate\View\View
     */
    public function create()
    {
    	if(auth()->guard('admin')->check())
            return redirect()->route('admin.home');

        return view('admin/auth/login');
    }

    /**
     * Handle an incoming authentication request.
     *
     * @param  \App\Http\Requests\Auth\AdminLoginRequest  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(AdminLoginRequest $request)
    {
        $request->authenticate();
        $request->session()->regenerate();
        return redirect(route('admin.home'));
    }
}
Make AdminLoginRequest

AdminLoginController के store() method में अगर आप ध्यान से देखोगे तो पायंगे कि Normal Request की जगह AdminLoginRequest instance use किया गया है , तो हमें इसके लिए एक request भी बनांनी होगी। नीचे कुछ steps दी गयी हैं जिन्हे follow करके आप AdminLoginRequest बना सकते हैं।

1. Run this command : php artisan make:request Auth/AdminLoginRequest
2. open app/Http/Request/ folder you will see two file LoginRequest for User & AdminLoginRequest For Amdin
3. copy LoginRequest content and paste into AdminLoginRequest file.
4. inside AdminLoginRequest class change authenticate() method.

public function authenticate()
{
    $this->ensureIsNotRateLimited();

    if (! Auth::guard('admin')->attempt($this->only('email', 'password'), $this->boolean('remember'))) {
        RateLimiter::hit($this->throttleKey());

        throw ValidationException::withMessages([
            'email' => __('auth.failed'),
        ]);
    }

    RateLimiter::clear($this->throttleKey());
}

Replace this code in app / Http /Controllers / AdminForgetPasswordController.php

Copy Fullscreen Close Fullscreen
<?php
namespace App\Http\Controllers\Admin\Auth;
use Models\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules;
class AdminForgetPasswordController extends Controller
{
    /*
    * set password broker name according to guard which you have set in config/auth.php
    */
    protected function broker()
    {
      return Password::broker('admins');
    }

    //defining which guard to use in our case, it's the admin guard
    protected  function guard() {
      return Auth::guard('admin');
    }

    /**
     * Display the password reset link request view.
     *
     * @return \Illuminate\View\View
    */
    public function forget_password()
    {
        return view('admin.auth.forgot-password');
    }

    /**
     * Handle an incoming password reset link request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse
     *
     * @throws \Illuminate\Validation\ValidationException
    */
    public function send_reset_link(Request $request)
    {
        $request->validate([
            'email' => ['required', 'email'],
        ]);

        // We will send the password reset link to this user. Once we have attempted
        // to send the link, we will examine the response then see the message we
        // need to show to the user. Finally, we'll send out a proper response.
        $status = Password::broker('admins')->sendResetLink(
            $request->only('email')
        );

        return $status == Password::RESET_LINK_SENT
                    ? back()->with('status', __($status))
                    : back()->withInput($request->only('email'))
                            ->withErrors(['email' => __($status)]);
    }

    /**
     * Display the password reset view.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\View\View
    */
    public function reset_password(Request $request)
    {
        return view('admin.auth.reset-password', ['request' => $request]);
    }

    /**
     * Handle an incoming new password request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse
     *
     * @throws \Illuminate\Validation\ValidationException
    */
    public function update_password(Request $request)
    {
        $request->validate([
            'token' => ['required'],
            'email' => ['required', 'email'],
            'password' => ['required', 'confirmed', Rules\Password::defaults()],
        ]);

        // Here we will attempt to reset the user's password. If it is successful we
        // will update the password on an actual user model and persist it to the
        // database. Otherwise we will parse the error and return the response.
        $status = Password::broker('admins')->reset(
            $request->only('email', 'password', 'password_confirmation', 'token'),
            function ($user) use ($request) {
                $user->forceFill([
                    'password' => Hash::make($request->password),
                    'remember_token' => Str::random(60),
                ])->save();

                event(new PasswordReset($user));
            }
        );

        // If the password was successfully reset, we will redirect the user back to
        // the application's home authenticated view. If there is an error we can
        // redirect them back to where they came from with their error message.
        return $status == Password::PASSWORD_RESET
                    ? redirect()->route('admin.login')->with('success', __($status))
                    : back()->withInput($request->only('email'))
                            ->withErrors(['email' => __($status)]);
    }
}

Replace this code in app / Http / Controllers / AdminHomeController.php

Copy Fullscreen Close Fullscreen
<?php
namespace App\Http\Controllers\Admin;
use Auth;
use App\Models\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class AdminHomeController extends Controller
{
	/**
     * Destroy an authenticated session for admin.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse
     */
     public function destroy(Request $request)
     {
        Auth::guard('admin')->logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();
        return redirect(route('admin.login'));
     }

     /**
     * Admin home page
     */
     public function home()
     {
           return "Logged In as Admin";
    }
}

Prepare View

By default normal user के लिए तो login / forget password के लिए views आते हैं जिन्हे आप resources/views/auth directory में देख सकते हैं। हमें सिर्फ admin के लिए view prepare करना होगा।


admin के लिए simple views folder में एक new directory views/admin बनाये और admin directory के अंदर auth name की directory बना लें।

उसके बाद normal users के लिए बनाई गयी files (login.blade.php, forgot-password.blade.php & reset-password.blade.php ) को copy करके resources/views/admin/authdirectory के अंदर paste कर दें और फिर उन files के अंदर login / reset form का action (route url) admin का दे दे जो आपने admin routes define किये हैं।


Important
ध्यान रहें admin routes के लिए हमें name('admin.') लिखा था , हमें हर routes से पहले admin लिखना होगा जैसे -

  • For Admin : route('admin.home') // localhost / projectname / admin
  • For Admin Login : route('admin.login')   // localhost / projectname / admin / login
  • For Forget password : route('admin.password.request')   // localhost / projectname / admin / forgot-password
  • For Logout : route('admin.logout')   // localhost/projectname / admin/logout

Hey ! I'm Rahul founder of learnhindituts.com. Working in IT industry more than 4.5 years. I love to talk about programming as well as writing technical tutorials and blogs that can help to others .... keep learning :)

Get connected with me - LinkedIn Twitter Instagram Facebook