Laravel provide authentication out of the box with many features and perks, in this tutorial we'll use it to implement multiple authentication system meaning having different type of users let's say admin or author.
What drove me to this approach is the attempt to extended laravel authentication to support multi auth without losing any functionality.
Blog will be the tutorial subject where we implement admin auth alongside the default user auth.
Content:
- Initialization
- Model and Migration
- Configuration
- Service Provider
- Middlewares
- Controllers
- Routing
- Views
- Conclusion
Create a fresh laravel installation with authentication scaffolding included and configure Database and Mail in .env
laravel new blog --auth
Setup Password Confirmation
routes/web.php
-
copy documentation demo route and register it as '/confirmed' and make it return 'password confirmed' string
Route::get('/confirmed', function () { return 'password confirmed'; })->middleware(['auth', 'password.confirm']);
Setup Email Verification
app/User.php
- in
App\User
model implementIlluminate\Contracts\Auth\MustVerifyEmail
routes/web.php
-
email verification routes are disabled by default we'll have to enable them, in
Auth::routes
method set the verify option to trueAuth::routes(['verify' => true]);
-
copy documentation demo route and register it as '/verified' and make it return 'email verified' string
Route::get('/verified', function () { return 'email verified'; })->middleware('verified');
Setup API Authentication
Note: this feature completes laravel authentication by providing simple api authentication which we think is missing but is actually there, it's available since 5.2 release but without documentation it was just mentioned in the authentication documentation, in 5.8 release luckily they decided to document it, in 7.x release for some reason the documentation is gone although the feature still exists (probably it has something to do with releasing Sanctum Package that offers similar capabilities).
database/migrations/xxxx_xx_xx_xxxxxx_create_users_table.php
-
api authentication uses the token driver which require a column to store tokens by default this column is named api_token, in users migration add api_token column
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->string('api_token', 80)->unique()->nullable()->default(null); $table->rememberToken(); $table->timestamps(); });
app/Http/Controllers/Auth/RegisterController.php
-
in
create
method assign random api token to user during registrationuse Illuminate\Support\Str; protected function create(array $data) { return User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), 'api_token' => Str::random(80), ]); }
app/User.php
-
because user registration logic use mass assignment the previous step won't work unless we make api_token attribute mass assignable by adding it to
$fillable
propertyprotected $fillable = [ 'name', 'email', 'password', 'api_token' ];
Create admin model and it's corresponding migration
php artisan make:model -m Admin
database/migrations/xxxx_xx_xx_xxxxxx_create_admins_table.php
-
we'll use user migration as a template for admin migration, copy user migration columns into admin migration
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->string('api_token', 80)->unique()->nullable()->default(null); $table->rememberToken(); $table->timestamps(); });
app/Admin.php
-
we'll use user model as a template for admin model, replace admin model code with user model code and change the class name accordingly
<?php namespace App; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; class Admin extends Authenticatable implements MustVerifyEmail { use Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', 'api_token' ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; /** * The attributes that should be cast to native types. * * @var array */ protected $casts = [ 'email_verified_at' => 'datetime', ]; }
Admin
model extends Authenticatable
an alias for Illuminate\Foundation\Auth\User
which provide authentication functionalities, the latter use Illuminate\Auth\Passwords\CanResetPassword
trait to include reset password necessary methods, this trait use ResetPasswordNotification
an alias for Illuminate\Auth\Notifications\ResetPassword
notification to send reset password email containing reset password link that expire after a period specified in user reset password configuration, we'll customize this notification to receive reset password url and configuration as parameters.
Create a new notification named ResetPasswordNotification
php artisan make:notification ResetPasswordNotification
app/Notifications/ResetPasswordNotification.php
-
import and extend
Illuminate\Auth\Notifications\ResetPassword
-
remove
Illuminate\Bus\Queueable
,Illuminate\Contracts\Queue\ShouldQueue
,Illuminate\Notifications\Notification
imports -
remove
Queueable
trait -
remove
via
,toMail
,toArray
methods -
define
$resetPasswordRoute
,$resetPasswordConfig
propertiesclass ResetPasswordNotification extends ResetPassword { public $resetPasswordRoute; public $resetPasswordConfig; // ... }
-
in constructor define
$token
parent class property and nullable$resetPasswordRoute
,$resetPasswordConfig
parameters, call parent constructor, assign$resetPasswordRoute
,$resetPasswordConfig
parameters to corresponding propertiespublic function __construct($token, $resetPasswordRoute = null, $resetPasswordConfig = null) { parent::__construct($token); $this->resetPasswordRoute = $resetPasswordRoute; $this->resetPasswordConfig = $resetPasswordConfig; }
-
override
Illuminate\Auth\NotificationsResetPassword
notification toMail method using same code, use$resetPasswordRoute
property instead of 'password.reset' and$resetPasswordConfig
property instead ofconfig('auth.defaults.passwords')
when properties are not null, importIlluminate\Support\Facades\Lang
use Illuminate\Support\Facades\Lang; 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->resetPasswordRoute ?: 'password.reset', [ '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.'.($this->resetPasswordConfig ?: config('auth.defaults.passwords')).'.expire')])) ->line(Lang::get('If you did not request a password reset, no further action is required.')); }
app/Admin.php
-
override
Illuminate\Auth\Passwords\CanResetPassword
trait sendPasswordResetNotification method using same code, inResetPasswordNotification
instantiation pass$resetPasswordRoute
parameter as 'admin.password.reset' and$resetPasswordConfig
parameter as 'admins' alongside$token
, importApp\Notifications\ResetPasswordNotification
use App\Notifications\ResetPasswordNotification; public function sendPasswordResetNotification($token) { $this->notify(new ResetPasswordNotification($token, 'admin.password.reset', 'admins')); }
Admin model extends Authenticatable
an alias for Illuminate\Foundation\Auth\User
which provide authentication functionalities, the latter use Illuminate\Auth\MustVerifyEmail
trait to include email verification necessary methods, this trait use Illuminate\Auth\Notifications\VerifyEmail
notification to send emails containing verification link, we'll customize this notification to receive email verification route as parameter instead of using staticly defined one.
create a new notification named VerifyEmailNotification
php artisan make:notification VerifyEmailNotification
app/Notifications/VerifyEmailNotification.php
-
import and extend
Illuminate\Auth\Notifications\VerifyEmail
-
remove
Illuminate\Bus\Queueable
,Illuminate\Contracts\Queue\ShouldQueue
,Illuminate\Notifications\Messages\MailMessage
,Illuminate\Notifications\Notification
imports -
remove
Queueable
trait -
remove
via
,toMail
,toArray
methods -
define
$verifyEmailRoute
propertyclass VerifyEmailNotification extends VerifyEmail { public $verifyEmailRoute; // ... }
-
in constructor define nullable
$verifyEmailRoute
parameter, assign$verifyEmailRoute
parameter to corresponding propertypublic function __construct($verifyEmailRoute) { $this->verifyEmailRoute = $verifyEmailRoute; }
-
override
Illuminate\Auth\Notifications\VerifyEmail
notification verificationUrl method using same code, use$verifyEmailRoute
property instead of 'verification.verify' when property is not null, importIlluminate\Support\Facades\URL
,Illuminate\Support\Carbon
,Illuminate\Support\Facades\Config
use Illuminate\Support\Facades\URL; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Config; /** * Get the verification URL for the given notifiable. * * @param mixed $notifiable * @return string */ protected function verificationUrl($notifiable) { return URL::temporarySignedRoute( $this->verifyEmailRoute ?: 'verification.verify', Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), [ 'id' => $notifiable->getKey(), 'hash' => sha1($notifiable->getEmailForVerification()), ] ); }
app/Admin.php
-
override
Illuminate\Auth\MustVerifyEmail
trait sendEmailVerificationNotification using same code, useApp\Notifications\VerifyEmailNotification
instead ofIlluminate\Auth\Notifications\VerifyEmail
, in instantiation pass$verifyEmailRoute
parameter as 'admin.verification.verify', importApp\Notifications\VerifyEmailNotification
use App\Notifications\VerifyEmailNotification; public function sendEmailVerificationNotification() { $this->notify(new VerifyEmailNotification('admin.verification.verify')); }
config/auth.php
-
guards define how users are authenticated, define 'admin-web' / 'admin-api' guards by copying 'web' / 'api' guards and changing provider option to 'admins'
'guards' => [ // ... 'admin-web' => [ 'driver' => 'session', 'provider' => 'admins', ], 'admin-api' => [ 'driver' => 'token', 'provider' => 'admins', 'hash' => false, ], ],
-
providers define how users are retrieved, define 'admins' provider by copying 'users' provider and changing model option to
App\Admin::class
'providers' => [ // ... 'admins' => [ 'driver' => 'eloquent', 'model' => App\Admin::class, ], ],
-
passwords define users reset password configurations, define 'admins' reset password configuration by copying 'users' reset password configuration and changing provider option to 'admins'
'passwords' => [ // ... 'admins' => [ 'provider' => 'admins', 'table' => 'password_resets', 'expire' => 60, 'throttle' => 60, ], ],
Laravel defines user home url using HOME
constant in RouteServiceProvider
we'll do the same for admin
app/Providers/RouteServiceProvider.php
-
define
ADMIN_HOME
const and set it to '/admin/home'class RouteServiceProvider extends ServiceProvider { public const ADMIN_HOME = '/admin/home'; // ... }
App\Http\Middleware\Authenticate=auth
middleware checks if user is authenticated before accessing protected routes if not user is redirected to login route, we'll have to customize redirection logic so that redirection is done based on specified guard
app/Http/Middleware/Authenticate.php
-
App\Http\Middleware\Authenticate=auth
extendsIlluminate\Auth\Middleware\Authenticate
which provide the functionality, we'll have to customizeunauthenticated
method to retreive request guard, override unauthenticated method using same code, inAuthenticationException
instantiation pass$guards
as a second parameter onredirectTo
method, importIlluminate\Auth\AuthenticationException
use Illuminate\Auth\AuthenticationException; protected function unauthenticated($request, array $guards) { throw new AuthenticationException( 'Unauthenticated.', $guards, $this->redirectTo($request, $guards) ); }
-
in
redirectTo
method add$guards
parameter, redirect based on$guards
to corresponding login routeprotected function redirectTo($request, array $guards) { if (! $request->expectsJson()) { switch (current($guards)) { case 'admin-web': return route('admin.login'); default: return route('login'); } } }
App\Http\Middleware\RedirectIfAuthenticated=guest
middleware checks if user is authenticated before accessing protected routes if so user is redirected to home route, we'll have to customize redirection logic so that redirection is done based on specified guard
app/Http/Middleware/RedirectIfAuthenticated.php
-
redirect based on
$guard
to corresponding home routepublic function handle($request, Closure $next, $guard = null) { if (Auth::guard($guard)->check()) { switch ($guard) { case 'admin-web': return redirect(RouteServiceProvider::ADMIN_HOME); default: return redirect(RouteServiceProvider::HOME); } } return $next($request); }
Illuminate\Auth\Middleware\EnsureEmailIsVerified=verified middleware checks if user email is verified before accessing protected routes, we'll have to customize it's logic to retrieve user using the specified guard
create a new middleware named EnsureEmailIsVerified
php artisan make:middleware EnsureEmailIsVerified
app/Http/Middleware/EnsureEmailIsVerified.php
-
we'll use original middleware as a template for
App\Http\Middleware\EnsureEmailIsVerified
middleware, replaceApp\Http\Middleware\EnsureEmailIsVerified
code with Illuminate\Auth\Middleware\EnsureEmailIsVerified code, add a new nullable parameter called$guard
, in$request->user
method occurrences set$guard
parameter to the newly defined parameter<?php namespace App\Http\Middleware; use Closure; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Support\Facades\Redirect; class EnsureEmailIsVerified { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string|null $redirectToRoute * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse */ public function handle($request, Closure $next, $redirectToRoute = null, $guard = null) { if (! $request->user($guard) || ($request->user($guard) instanceof MustVerifyEmail && ! $request->user($guard)->hasVerifiedEmail())) { return $request->expectsJson() ? abort(403, 'Your email address is not verified.') : Redirect::route($redirectToRoute ?: 'verification.notice'); } return $next($request); } }
app/Http/Kernel.php
-
in
$routeMiddleware
property comment existing verified middleware registration and keep it as reference, registerApp\Http\Middleware\EnsureEmailIsVerified
middleware as verifiedprotected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, // 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'verified' => \App\Http\Middleware\EnsureEmailIsVerified::class, ];
Laravel ships with several pre-built authentication controllers which handles registration, authentication, resetting passwords and email verification, these controllers use traits to include their necessary methods, we'll create admin auth controllers by copying existing ones and making needed adjustments
Group admin controllers in a directory / namespace, create app/Http/Controllers/Admin directory / namespace
Create admin auth controllers, copy app/Http/Controllers/Auth directory as app/Http/Controllers/Admin/Auth
app/Http/Controllers/Admin/Auth/RegisterController.php
-
change namespace to
App\Http\Controllers\Admin\Auth
-
import
App\Admin
model instead ofApp\User
-
set
$redirectTo
property toRouteServiceProvider::ADMIN_HOME
-
in constructor specify 'admin-web' as the guard that
guest=App\Http\Middleware\RedirectIfAuthenticated
middleware should usepublic function __construct() { $this->middleware('guest:admin-web'); }
-
in
validator
method set unique rule table parameter to 'admins'protected function validator(array $data) { return Validator::make($data, [ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:admins'], 'password' => ['required', 'string', 'min:8', 'confirmed'], ]); }
-
in
create
method changeUser
model toAdmin
protected function create(array $data) { return Admin::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), 'api_token' => Str::random(80), ]); }
-
RegisterController
usesIlluminate\Foundation\Auth\RegistersUsers
trait showRegistrationForm method to show registration form, override this method using same code, changeview('auth.register')
toview('admin.auth.register')
public function showRegistrationForm() { return view('admin.auth.register'); }
-
RegisterController
usesIlluminate\Foundation\Auth\RegistersUsers
trait guard method to get the guard to be used during registration, override this method using same code, inAuth::guard
method pass guard parameter as 'admin-web', importIlluminate\Support\Facades\Auth
use Illuminate\Support\Facades\Auth; protected function guard() { return Auth::guard('admin-web'); }
app/Http/Controllers/Admin/Auth/LoginController.php
-
change namespace to
App\Http\Controllers\Admin\Auth
-
set
$redirectTo
property toRouteServiceProvider::ADMIN_HOME
-
in constructor specify 'admin-web' as the guard that
guest=App\Http\Middleware\RedirectIfAuthenticated
middleware should usepublic function __construct() { $this->middleware('guest:admin-web'); }
-
LoginController
usesIlluminate\Foundation\Auth\AuthenticatesUsers
trait showLoginForm method to show login form, override this method using same code, changeview('auth.login')
toview('admin.auth.login')
public function showLoginForm() { return view('admin.auth.login'); }
-
LoginController
usesIlluminate\Foundation\Auth\AuthenticatesUsers
trait logout method to log the user out, this trait offer loggedOut method which allow customization oflogout
method response, override this method, uselogout
method response and changeredirect('/')
toredirect('/admin')
, importIlluminate\Http\Request
,Illuminate\Http\Response
use Illuminate\Http\Request; use Illuminate\Http\Response; protected function loggedOut(Request $request) { return $request->wantsJson() ? new Response('', 204) : redirect('/admin'); }
-
LoginController
usesIlluminate\Foundation\Auth\AuthenticatesUsers
trait guard method to get the guard to be used during authentication, override this method, inAuth::guard
method pass guard parameter as 'admin-web', importIlluminate\Support\Facades\Auth
use Illuminate\Support\Facades\Auth; protected function guard() { return Auth::guard('admin-web'); }
app/Http/Controllers/Admin/Auth/VerificationController.php
-
change namespace to
App\Http\Controllers\Admin\Auth
-
set
$redirectTo
property toRouteServiceProvider::ADMIN_HOME
-
in constructor specify 'admin-web' as the guard that
auth=App\Http\Middleware\Authenticate
middleware should usepublic function __construct() { $this->middleware('auth:admin-web'); $this->middleware('signed')->only('verify'); $this->middleware('throttle:6,1')->only('verify', 'resend'); }
-
VerificationController
usesIlluminate\Foundation\Auth\VerifiesEmails
trait show method to show email verification notice form, override this method using same code, in$request->user
method pass guard parameter as 'admin-web', changeview('auth.verify')
toview('admin.auth.verify')
, importIlluminate\Http\Request
use Illuminate\Http\Request; public function show(Request $request) { return $request->user('admin-web')->hasVerifiedEmail() ? redirect($this->redirectPath()) : view('admin.auth.verify'); }
app/Http/Controllers/Admin/Auth/ConfirmPasswordController.php
-
change namespace to
App\Http\Controllers\Admin\Auth
-
set
$redirectTo
property toRouteServiceProvider::ADMIN_HOME
-
in constructor specify 'admin-web' as the guard that
auth=App\Http\Middleware\Authenticate
middleware should usepublic function __construct() { $this->middleware('auth:admin-web'); }
-
ConfirmPasswordController
usesIlluminate\Foundation\Auth\ConfirmsPasswords
trait showConfirmForm method to show the password confirmation form, override this method using same code, changeview('auth.passwords.confirm')
toview('admin.auth.passwords.confirm')
public function showConfirmForm() { return view('admin.auth.passwords.confirm'); }
app/Http/Controllers/Admin/Auth/ForgotPasswordController.php
-
change namespace to
App\Http\Controllers\Admin\Auth
-
ForgotPasswordController
usesIlluminate\Foundation\Auth\SendsPasswordResetEmails
trait showLinkRequestForm method to show the form to request a password reset link, override this method using same code, changeview('auth.passwords.email')
toview('admin.auth.passwords.email')
public function showLinkRequestForm() { return view('admin.auth.passwords.email'); }
-
ForgotPasswordController
usesIlluminate\Foundation\Auth\SendsPasswordResetEmails
trait broker method to get the broker to be used during password reset, override this method using same code, inPassword::broker
method pass broker parameter as 'admins', importIlluminate\Support\Facades\Password
public function broker() { return Password::broker('admins'); }
app/Http/Controllers/Admin/Auth/ResetPasswordController.php
-
change namespace to
App\Http\Controllers\Admin\Auth
-
set
$redirectTo
property toRouteServiceProvider::ADMIN_HOME
-
ResetPasswordController
usesIlluminate\Foundation\Auth\ResetsPasswords
trait showResetForm method to show the password reset form, override this method, changeview('auth.passwords.reset')
toview('admin.auth.passwords.reset')
, importIlluminate\Http\Request
use Illuminate\Http\Request; public function showResetForm(Request $request, $token = null) { return view('admin.auth.passwords.reset')->with( ['token' => $token, 'email' => $request->email] ); }
-
ResetPasswordController
usesIlluminate\Foundation\Auth\ResetsPasswords
trait broker method to get the broker to be used during password reset, override this method, inPassword::broker
method pass broker parameter as 'admins', importIlluminate\Support\Facades\Password
use Illuminate\Support\Facades\Password; public function broker() { return Password::broker('admins'); }
-
ResetPasswordController
usesIlluminate\Foundation\Auth\ResetsPasswords
trait guard method to get the guard to be used during password reset, override this method, inAuth::guard
method pass guard parameter as 'admin-web', importIlluminate\Support\Facades\Auth
use Illuminate\Support\Facades\Auth; protected function guard() { return Auth::guard('admin-web'); }
Create admin home controller, copy app/Http/Controllers/HomeController.php as app/Http/Controllers/Admin/HomeController.php
app/Http/Controllers/Admin/HomeController.php
-
change namespace to
App\Http\Controllers\Admin\Auth
-
import
App\Http\Controllers\Controller
-
in constructor specify 'admin-web' as the guard that
auth=App\Http\Middleware\Authenticate
middleware should usepublic function __construct() { $this->middleware('auth:admin-web'); }
-
in
index
method changeview('home')
toview('admin.home')
public function index() { return view('admin.home'); }
routes/web.php
-
register admin route group and set 'prefix' option to 'admin', 'namespace' option to 'Admin' and 'as' option to 'admin.'
Route::group(['prefix' => '/admin', 'namespace' => 'Admin', 'as' => 'admin.'], function () { // ... });
-
copy user routes into admin group
-
in '/' route change
view('welcome')
toview('admin.welcome')
Route::get('/', function () { return view('admin.welcome'); });
-
in '/confirmed' route pass auth middleware guard parameter as 'admin-web' and password.confirm middleware
$redirectToRoute
parameter as 'admin.password.confirm'Route::get('/confirmed', function () { return 'password confirmed'; })->middleware(['auth:admin-web', 'password.confirm:admin.password.confirm']);
-
in '/verified' route pass verified middleware
$redirectToRoute
parameter as 'admin.verification.notice' and guard parameter as 'admin-web'Route::get('/verified', function () { return 'email verified'; })->middleware('verified:admin.verification.notice,admin-web');
Laravel ships with a user demo api route, we'll add one for admin
routes/api.php
-
copy '/user' route and register it as '/admin', set auth middleware and
$request->user
method guard parameter to 'admin-api'Route::middleware('auth:admin-api')->get('/admin', function (Request $request) { return $request->user('admin-api'); });
Create a layout for admin, copy resources\views\layouts\app.blade.php as resources\views\layouts\admin.blade.php
resources/views/layouts/admin.blade.php
-
change
url('/')
tourl('/admin')
-
pass
@guest
directive guard parameter as 'admin-web' -
add 'admin.' route name prefix to auth routes
-
in
Auth::user
specify the guard that auth facade should use, chainguard
method and pass guard parameter as 'admin-web'{{ Auth::guard('admin-web')->user()->name }}
Group admin views in a directory, create resources/views/admin directory
Create admin welcome view, copy resources/views/welcome.blade.php as resources/views/admin/welcome.blade.php
resources/views/admin/welcome.blade.php
- add 'admin.' route name prefix to auth routes
- set
@auth
directive guard parameter to 'admin-web' - change
url('/home')
tourl('/admin/home')
Create admin auth views, copy resources/views/auth as resources/views/admin/auth
resources/views/admin/auth/register.blade.php
- change
@extends('layouts.app')
to@extends('layouts.admin')
- add 'admin.' route name prefix to auth routes
resources/views/admin/auth/login.blade.php
- change
@extends('layouts.app')
to@extends('layouts.admin')
- add 'admin.' route name prefix to auth routes
resources/views/admin/auth/verify.blade.php
- change
@extends('layouts.app')
to@extends('layouts.admin')
- add 'admin.' route name prefix to auth routes
resources/views/admin/auth/passwords/confirm.blade.php
- change
@extends('layouts.app')
to@extends('layouts.admin')
- add 'admin.' route name prefix to auth routes
resources/views/admin/auth/passwords/email.blade.php
- change
@extends('layouts.app')
to@extends('layouts.admin')
- add 'admin.' route name prefix to auth routes
resources/views/admin/auth/passwords/reset.blade.php
- change
@extends('layouts.app')
to@extends('layouts.admin')
- add 'admin.' route name prefix to auth routes
Create admin home view, copy resources\views\home.blade.php as resources\views\admin\home.blade.php
resources\views\admin\home.blade.php
- change
@extends('layouts.app')
to@extends('layouts.admin')
Now that we've finished we should check that multi auth is working by trying available actions on user and admin. Finally i want to say that Laravel flexibility is what made this implementation that simple so the next time you look for something that's not available out of the box get the shovel and start digging