Create MultiAuth in Laravel 7.x

Steps1: Scaffold migration and Roles

First

Install laravel project and make scaffold.

Second

·         Add role_id column in users table

    public function up()

    {

        Schema::create('users'function (Blueprint $table) {

            $table->id();

            $table->string('name');

            $table->string('email')->unique();

            $table->timestamp('email_verified_at')->nullable();

            $table->string('password');

            $table->foreignId('role_id')->constrained();

            $table->rememberToken();

            $table->timestamps();

        });

    }

·         Create roles table

   public function up()

    {

        Schema::create('roles'function (Blueprint $table) {

            $table->id();

            $table->string('nickname',20);

            $table->string('name',20);

            $table->timestamps();

        });

        DB::table('roles')->insert(['nickname'=>'admin''name'=>'Admin']);

        DB::table('roles')->insert(['nickname'=>'user''name'=>'User']);

    }

Third

In Users table for just start set role_id column default 2.

 

Steps2: Custom Guard and Provider

1. Go config/auth.php and add guards for user and admin then below add proivders and password field for admin and user

    'guards' => [

        'web' => [

            'driver' => 'session',

            'provider' => 'users',

        ],

 

        'user' => [

            'driver' => 'session',

            'provider' => 'users',

        ],

 

        'admin' => [

            'driver' => 'session',

            'provider' => 'admins',

        ],

 

        'api' => [

            'driver' => 'token',

            'provider' => 'users',

            'hash' => false,

        ],

    ],

 

    'providers' => [

        'users' => [

            'driver' => 'eloquent',

            'model' => App\User::class,

        ],

 

        'admins' => [

            'driver' => 'eloquent',

            'model' => App\User::class,

        ],

        //above for admins I want use same model if you have other model then specify model name

 

        // 'users' => [

        //     'driver' => 'database',

        //     'table' => 'users',

        // ],

    ],

 

    'passwords' => [

        'users' => [

            'provider' => 'users',

            'table' => 'password_resets',

            'expire' => 60,

            'throttle' => 60,

        ],

        'admins' => [

            'provider' => 'admins',

            'table' => 'password_resets',

            'expire' => 60,

            'throttle' => 60,

        ],

    ],

 

2. Go to LoginController and go to find traits for AuthenticatesUsers.php in LoginController. And last add the line user.

 protected function guard()

    {

        return Auth::guard('user');

    }

 

3. Go to HomeController and change the middleware (‘auth’) => (‘auth:user’).

 

Step3: Routes for Admin and User

1. Search Router.php file (vendor/laravel/framework/src/illuminate/Routing/Router.php) and find route like login/register etc...

2. Go to app\http\controller\auth and create folder inside auth admin and user and copy all file under auth and paste under these folder and change the path inside controller like for all:

namespace App\Http\Controllers\Auth\Admin;

same for user also but follow if traditional auth file moved because you have to change these file also in router.php

namespace App\Http\Controllers\Auth\User;

3. Go to Authenticates user for default user and change the redirect route after logout=> this change is up to you if you want then okk otherwise this will be okk: optional case

 return $request->wantsJson()

            ? new Response(''204)

            : redirect('/login');

 

Now for Admin part this is important: Login Controller

<?php

 

namespace App\Http\Controllers\Auth\Admin;

 

use Illuminate\Http\Request;

use Illuminate\Http\Response;

use App\Http\Controllers\Controller;

use Illuminate\Support\Facades\Auth;

use App\Providers\RouteServiceProvider;

use Illuminate\Foundation\Auth\RedirectsUsers;

use Illuminate\Validation\ValidationException;

use Illuminate\Foundation\Auth\ThrottlesLogins;

use Illuminate\Foundation\Auth\AuthenticatesUsers;

 

class LoginController extends Controller

{

    /*

    |--------------------------------------------------------------------------

    | Login Controller

    |--------------------------------------------------------------------------

    |

    | This controller handles authenticating users for the application and

    | redirecting them to your home screen. The controller uses a trait

    | to conveniently provide its functionality to your applications.

    |

    */

 

    /**

     * Where to redirect users after login.

     *

     * @var string

     */

    protected $redirectTo = '/admin/dashboard';

 

    /**

     * Create a new controller instance.

     *

     * @return void

     */

    public function __construct()

    {

        $this->middleware('guest')->except('logout');

    }

 

    use RedirectsUsersThrottlesLogins;

 

    /**

     * Show the application's login form.

     *

     * @return \Illuminate\Http\Response

     */

    public function showLoginForm()

    {

        return view('auth.admin.login');

    }

 

    /**

     * Handle a login request to the application.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse

     *

     * @throws \Illuminate\Validation\ValidationException

     */

    public function login(Request $request)

    {

        $this->validateLogin($request);

 

        // If the class is using the ThrottlesLogins trait, we can automatically throttle

        // the login attempts for this application. We'll key this by the username and

        // the IP address of the client making these requests into this application.

        if (method_exists($this'hasTooManyLoginAttempts') &&

            $this->hasTooManyLoginAttempts($request)) {

            $this->fireLockoutEvent($request);

 

            return $this->sendLockoutResponse($request);

        }

 

        if ($this->attemptLogin($request)) {

            return $this->sendLoginResponse($request);

        }

 

        // If the login attempt was unsuccessful we will increment the number of attempts

        // to login and redirect the user back to the login form. Of course, when this

        // user surpasses their maximum number of attempts they will get locked out.

        $this->incrementLoginAttempts($request);

 

        return $this->sendFailedLoginResponse($request);

    }

 

    /**

     * Validate the user login request.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return void

     *

     * @throws \Illuminate\Validation\ValidationException

     */

    protected function validateLogin(Request $request)

    {

        $request->validate([

            $this->username() => 'required|string',

            'password' => 'required|string',

        ]);

    }

 

    /**

     * Attempt to log the user into the application.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return bool

     */

    protected function attemptLogin(Request $request)

    {

        return $this->guard()->attempt(

            $this->credentials($request), $request->filled('remember')

        );

    }

 

    /**

     * Get the needed authorization credentials from the request.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return array

     */

    protected function credentials(Request $request)

    {

        return $request->only($this->username(), 'password');

    }

 

    /**

     * Send the response after the user was authenticated.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return \Illuminate\Http\Response

     */

    protected function sendLoginResponse(Request $request)

    {

        $request->session()->regenerate();

 

        $this->clearLoginAttempts($request);

 

        if ($response = $this->authenticated($request$this->guard()->user())) {

            return $response;

        }

 

        return $request->wantsJson()

                    ? new Response(''204)

                    : redirect()->intended($this->redirectPath());

    }

 

    /**

     * The user has been authenticated.

     *

     * @param  \Illuminate\Http\Request  $request

     * @param  mixed  $user

     * @return mixed

     */

    protected function authenticated(Request $request, $user)

    {

        //

    }

 

    /**

     * Get the failed login response instance.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return \Symfony\Component\HttpFoundation\Response

     *

     * @throws \Illuminate\Validation\ValidationException

     */

    protected function sendFailedLoginResponse(Request $request)

    {

        throw ValidationException::withMessages([

            $this->username() => [trans('auth.failed')],

        ]);

    }

 

    /**

     * Get the login username to be used by the controller.

     *

     * @return string

     */

    public function username()

    {

        return 'email';

    }

 

    /**

     * Log the user out of the application.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return \Illuminate\Http\Response

     */

    public function logout(Request $request)

    {

        $this->guard()->logout();

 

        $request->session()->invalidate();

 

        $request->session()->regenerateToken();

 

        if ($response = $this->loggedOut($request)) {

            return $response;

        }

 

        return $request->wantsJson()

            ? new Response(''204)

            : redirect('/login');

    }

 

    /**

     * The user has logged out of the application.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return mixed

     */

    protected function loggedOut(Request $request)

    {

        //

    }

 

    /**

     * Get the guard to be used during authentication.

     *

     * @return \Illuminate\Contracts\Auth\StatefulGuard

     */

    protected function guard()

    {

        return Auth::guard('admin');

    }

}

 

 

Make some modification user redirectTo after login => /user/dashboard

4. Make dashboardController for admin and user And make route for both also make blade file

5. Add construct function in controller for admin and user.

6. Make auth resource file for admin and change route also also like auth blade file for user.

Step4: Important and 3 steps problems solved OR exception handler and middleware

·         Change in layouts/app.blade.php for logout route

@if(auth()->user()->role->nickname == ‘user’) @else @endif

·         Search unauthenticated function in vendor structure and add into Exception/handler.php file and make some little modification like this

    /**

     * Convert an authentication exception into a response.

     *

     * @param  \Illuminate\Http\Request  $request

     * @param  \Illuminate\Auth\AuthenticationException  $exception

     * @return \Symfony\Component\HttpFoundation\Response

     */

    protected function unauthenticated($requestAuthenticationException $exception)

    {

        if$request->expectsJson() )

        {

            return response()->json(['message' => $exception->getMessage()], 401);

        }

        $guard = Arr::get$exception->guards(), 0 );

 

        $route = '';

 

        if ( $guard == 'admin') {

            $route = 'admin/login';

        }

        else if$guard == 'user') {

            $route = 'login';

        }

 

        return redirect($route);

 

    }

 

·         Now go to Middleware=> RedirectIfAuthenticated.php file where we define if admin is logged in then admin/login page not redirected.

Note: First go to your auth controller and define guard:admin/user in construct function.Login Controller

    public function __construct()

    {

        $this->middleware('guest:admin')->except('logout');

    }

Add below condition in file: add this into a middleware file RedirectedifAuthenticated.php

    public function handle($requestClosure $next, $guard = null)

    {

        if (Auth::guard($guard)->check()) {

            // return redirect(RouteServiceProvider::HOME);

            //here it will check if admin/user is logged in then then pop up the login page

            if ($guard == 'admin') {

                return redirect('admin/dashboard');

            }

            else if($guard == 'user')

            {

                return redirect('/dashboard');

            }

 

        }

 

        return $next($request);

    }

 

·         Final Note: don’t forgot add this add this for both Admin/User in Admin LoginController and for user LoginController AuthenticatesUsers trait.

These methods add between login function of both admin and user.

        $user = User::where('email'request()->email)->first();

 

        if ($user AND $user->role->nickname !== 'admin') {

            return redirect('/admin/login')->with(['status'=>'Sorry! Invalid Credentials']);

        }

 

Step5: Forgot password add:

1.      Users Section=> main file ForgotPasswordController and ResetPasswordController.

Construct add in both controller copy and paste it this: same will paste.

In laravel7.x this function method is not define you have to write or define manually OR in previous version it already defined:

    /**

     * Create a new controller instance.

     *

     * @return void

     */

    public function __construct()

    {

        $this->middleware('guest:user');

    }

 

Broker add => users

Find two file using ForgotPasswordController and ResetPasswordController

·         In SendPasswordResetEmails add broker(‘users’) like below

·         In add ResetPasswords.php file add broker(‘users’) and guard(‘users’) like below

If you see broker function in files then add like this OR if you see two function broker and guard then add values like this: these function are already predefine you don’t have to create, you just have to call value.

    public function broker()

    {

        return Password::broker('users');

    }

   protected function guard()

    {

        return Auth::guard('user');

    }

 

2.     Admin Section

§  Forgot password

·         First create the Admin routes for forgot and reset find in Router.php(vendor structure)

·         Go to admin ForgotPasswordController:

o   Same as login functionality go to trait in forgotpassword copy and paste in forgot password section and modify the controller file

<?php

 

namespace App\Http\Controllers\Auth\Admin;

 

use Illuminate\Http\Request;

use Illuminate\Http\JsonResponse;

use App\Http\Controllers\Controller;

use Illuminate\Support\Facades\Password;

use Illuminate\Validation\ValidationException;

use Illuminate\Foundation\Auth\SendsPasswordResetEmails;

 

class ForgotPasswordController extends Controller

{

    /*

    |--------------------------------------------------------------------------

    | Password Reset Controller

    |--------------------------------------------------------------------------

    |

    | This controller is responsible for handling password reset emails and

    | includes a trait which assists in sending these notifications from

    | your application to your users. Feel free to explore this trait.

    |

    */

 

    use SendsPasswordResetEmails;

 

    /**

     * Create a new controller instance.

     *

     * @return void

     */

    public function __construct()

    {

        $this->middleware('guest:admin');

    }

 

    /**

     * Display the form to request a password reset link.

     *

     * @return \Illuminate\Http\Response

     */

    public function showLinkRequestForm()

    {

        return view('auth.admin.passwords.email');

    }

 

    /**

     * Send a reset link to the given user.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse

     */

    public function sendResetLinkEmail(Request $request)

    {

        $this->validateEmail($request);

 

        // 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.

        $response = $this->broker()->sendResetLink(

            $this->credentials($request)

        );

 

        return $response == Password::RESET_LINK_SENT

                    ? $this->sendResetLinkResponse($request$response)

                    : $this->sendResetLinkFailedResponse($request$response);

    }

 

    /**

     * Validate the email for the given request.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return void

     */

    protected function validateEmail(Request $request)

    {

        $request->validate(['email' => 'required|email']);

    }

 

    /**

     * Get the needed authentication credentials from the request.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return array

     */

    protected function credentials(Request $request)

    {

        return $request->only('email');

    }

 

    /**

     * Get the response for a successful password reset link.

     *

     * @param  \Illuminate\Http\Request  $request

     * @param  string  $response

     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse

     */

    protected function sendResetLinkResponse(Request $request, $response)

    {

        return $request->wantsJson()

                    ? new JsonResponse(['message' => trans($response)], 200)

                    : back()->with('status'trans($response));

    }

 

    /**

     * Get the response for a failed password reset link.

     *

     * @param  \Illuminate\Http\Request  $request

     * @param  string  $response

     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse

     */

    protected function sendResetLinkFailedResponse(Request $request, $response)

    {

        if ($request->wantsJson()) {

            throw ValidationException::withMessages([

                'email' => [trans($response)],

            ]);

        }

 

        return back()

                ->withInput($request->only('email'))

                ->withErrors(['email' => trans($response)]);

    }

 

    /**

     * Get the broker to be used during password reset.

     *

     * @return \Illuminate\Contracts\Auth\PasswordBroker

     */

    public function broker()

    {

        return Password::broker('admins');

    }

}

·           

 

o   As well as modify the blade file related to Admin auth controller

o   Now next create new email file for admin like this: Note: add ResetPasswordNotification function in User Model

o    php artisan make:notification ResetPasswordNotification

And modigy the ResetPasswordNotification file like below:

<?php

 

namespace App\Notifications;

 

use Illuminate\Bus\Queueable;

use Illuminate\Support\Facades\Lang;

use Illuminate\Notifications\Notification;

use Illuminate\Contracts\Queue\ShouldQueue;

use Illuminate\Notifications\Messages\MailMessage;

class ResetPasswordNotification extends Notification

{

    use Queueable;

 

    public $token;

 

    public $route;

 

    /**

     * The callback that should be used to create the reset password URL.

     *

     * @var \Closure|null

     */

    public static $createUrlCallback;

 

    /**

     * The callback that should be used to build the mail message.

     *

     * @var \Closure|null

     */

    public static $toMailCallback;

 

    /**

     * Create a new notification instance.

     *

     * @return void

     */

    public function __construct($route, $token)

    {

        $this->token = $token;

        $this->route = $route;

    }

 

  /**

     * Get the notification's delivery channels.

     *

     * @param  mixed  $notifiable

     * @return array

     */

    public function via($notifiable)

    {

        return ['mail'];

    }

 

    /**

     * Get the mail representation of the notification.

     *

     * @param  mixed  $notifiable

     * @return \Illuminate\Notifications\Messages\MailMessage

     */

    public function toMail($notifiable)

    {

        if (static::$toMailCallback) {

            return call_user_func(static::$toMailCallback$notifiable$this->token);

        }

 

        if (static::$createUrlCallback) {

            $url = call_user_func(static::$createUrlCallback$notifiable$this->token);

        } else {

            $url = url(config('app.url').route($this->route, [

                'token' => $this->token,

                'email' => $notifiable->getEmailForPasswordReset(),

            ], false));

        }

        return (new MailMessage)

            ->subject(Lang::get('Reset Password Notification'))

            ->line(Lang::get('You are receiving this email because we received a password reset request for your account.'))

            ->action(Lang::get('Reset Password'), $url)

            ->line(Lang::get('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.'.config('auth.defaults.passwords').'.expire')]))

            ->line(Lang::get('If you did not request a password reset, no further action is required.'));

    }

    /**

     * Get the array representation of the notification.

     *

     * @param  mixed  $notifiable

     * @return array

     */

    public function toArray($notifiable)

    {

        return [

            //

        ];

    }

}

 

o   Go to User Model and add function like this: In this function I have written some line of code for distinct between user and admin.

    public function sendPasswordResetNotification($token)

    {

        $route = $this->role->nickname == 'admin' ? 'admin.password.reset' : 'password.reset';

        $this->notify(new ResetPasswordNotification$route$token));

    }

§  Reset Password

ResetsPasswords Go to this Traits and copy all his code and paste it on ResetPasswordController and modified for Admins

<?php

 

namespace App\Http\Controllers\Auth\Admin;

 

use Illuminate\Support\Str;

use Illuminate\Http\Request;

use Illuminate\Http\JsonResponse;

use App\Http\Controllers\Controller;

use Illuminate\Support\Facades\Auth;

use Illuminate\Support\Facades\Hash;

use App\Providers\RouteServiceProvider;

use Illuminate\Support\Facades\Password;

use Illuminate\Auth\Events\PasswordReset;

use Illuminate\Foundation\Auth\RedirectsUsers;

use Illuminate\Validation\ValidationException;

use Illuminate\Foundation\Auth\ResetsPasswords;

 

class ResetPasswordController extends Controller

{

    /*

    |--------------------------------------------------------------------------

    | Password Reset Controller

    |--------------------------------------------------------------------------

    |

    | This controller is responsible for handling password reset requests

    | and uses a simple trait to include this behavior. You're free to

    | explore this trait and override any methods you wish to tweak.

    |

    */

    use RedirectsUsers;

 

    /**

     * Display the password reset view for the given token.

     *

     * If no token is present, display the link request form.

     *

     * @param  \Illuminate\Http\Request  $request

     * @param  string|null  $token

     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View

     */

    public function showResetForm(Request $request, $token = null)

    {

        return view('auth.admin.passwords.reset')->with(

            ['token' => $token'email' => $request->email]

        );

    }

 

    /**

     * Reset the given user's password.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse

     */

    public function reset(Request $request)

    {

        $request->validate($this->rules(), $this->validationErrorMessages());

 

        // 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.

        $response = $this->broker()->reset(

            $this->credentials($request), function ($user, $password) {

                $this->resetPassword($user$password);

            }

        );

 

        // 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 $response == Password::PASSWORD_RESET

                    ? $this->sendResetResponse($request$response)

                    : $this->sendResetFailedResponse($request$response);

    }

 

    /**

     * Get the password reset validation rules.

     *

     * @return array

     */

    protected function rules()

    {

        return [

            'token' => 'required',

            'email' => 'required|email',

            'password' => 'required|confirmed|min:8',

        ];

    }

 

    /**

     * Get the password reset validation error messages.

     *

     * @return array

     */

    protected function validationErrorMessages()

    {

        return [];

    }

 

    /**

     * Get the password reset credentials from the request.

     *

     * @param  \Illuminate\Http\Request  $request

     * @return array

     */

    protected function credentials(Request $request)

    {

        return $request->only(

            'email''password''password_confirmation''token'

        );

    }

 

    /**

     * Reset the given user's password.

     *

     * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user

     * @param  string  $password

     * @return void

     */

    protected function resetPassword($user, $password)

    {

        $this->setUserPassword($user$password);

 

        $user->setRememberToken(Str::random(60));

 

        $user->save();

 

        event(new PasswordReset($user));

 

        $this->guard()->login($user);

    }

 

    /**

     * Set the user's password.

     *

     * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user

     * @param  string  $password

     * @return void

     */

    protected function setUserPassword($user, $password)

    {

        $user->password = Hash::make($password);

    }

 

    /**

     * Get the response for a successful password reset.

     *

     * @param  \Illuminate\Http\Request  $request

     * @param  string  $response

     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse

     */

    protected function sendResetResponse(Request $request, $response)

    {

        if ($request->wantsJson()) {

            return new JsonResponse(['message' => trans($response)], 200);

        }

 

        return redirect($this->redirectPath())

                            ->with('status'trans($response));

    }

 

    /**

     * Get the response for a failed password reset.

     *

     * @param  \Illuminate\Http\Request  $request

     * @param  string  $response

     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse

     */

    protected function sendResetFailedResponse(Request $request, $response)

    {

        if ($request->wantsJson()) {

            throw ValidationException::withMessages([

                'email' => [trans($response)],

            ]);

        }

 

        return redirect()->back()

                    ->withInput($request->only('email'))

                    ->withErrors(['email' => trans($response)]);

    }

 

    /**

     * Get the broker to be used during password reset.

     *

     * @return \Illuminate\Contracts\Auth\PasswordBroker

     */

    public function broker()

    {

        return Password::broker('admins');

    }

 

    /**

     * Get the guard to be used during password reset.

     *

     * @return \Illuminate\Contracts\Auth\StatefulGuard

     */

    protected function guard()

    {

        return Auth::guard('admin');

    }

 

    /**

     * Where to redirect users after resetting their password.

     *

     * @var string

     */

    protected $redirectTo = '/admin/dashboard';

 

    /**

     * Create a new controller instance.

     *

     * @return void

     */

    public function __construct()

    {

        $this->middleware('guest:admin');

    }

}

 

·         Don’t forgot to modify the blade file

Done


Comments

Popular posts from this blog

Create Virtual Host in Localhost

User Active/Inactive using Jquery

laravel passport