Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Mikejs's avatar

MultiAuth single table using Laravel breeze

Hi I would like to create a multi user app, using the breeze scaffolding.

I have added a field in the user table user_type, admin=0 user=1 agent=2 I have created the following folder structure:

Views/admin/dashboard Views/admin/editprofile Views/partials/ with the 3 files provided by breeze

Views/user/dashboard Views/user/editprofile Views/user/ with the 3 files provided by breeze

Views/agent/dashboard Views/agent/editprofile Views/agent/ with the 3 files provided by breeze

I have created the different user Routes, in web

I have tried using chatGPT to help create the login logic, however we end up going around in circles.

One suggestions was using routes

 Route::middleware(['auth', 'verified'])->group(function () {
  Route::get('/dashboard', function () {
    $userType = auth()->user()->user_type;

    switch ($userType) {
        case 0: // admin
            return redirect()->route('admin.dashboard');
        case 1: // user
            return redirect()->route('user.dashboard');
        case 2: // manager
            return redirect()->route('manager.dashboard');
        case 3: // agent
            return redirect()->route('agent.dashboard');
        default:
            return redirect('/');
    }
 })->name('dashboard');

Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});

Another was to edit the AuthenticatedSessionController which looked promising but both produced a number of errors which we tried to solve but ended up going around in circles.

 protected function redirectBasedOnUserType(): RedirectResponse
  {
    $user = Auth::user();
    $userType = $user->user_type;

    switch ($userType) {
        case 0: // admin
            return redirect()->route('admin.dashboard');
        case 1: // user
            return redirect()->route('user.dashboard');
        case 2: // manager
            return redirect()->route('manager.dashboard');
        case 3: // agent
            return redirect()->route('agent.dashboard');
        default:
            return redirect('/');
    }
}

Does anyone have a solution to this or a guide someone has created, I did google but nothing that helped, I don't want multi tables, just the user_type

thanks

0 likes
9 replies
jlrdw's avatar

Use many guards, or make things simple and use authorization to determine who can and cannot do something.

You can make custom dashboards for certain role types, I have one separate for accounting and one for admin in one app.

2 likes
Mikejs's avatar

@jlrdw What did you use for the auth - are you using an extra field in your user table or a different method?

jlrdw's avatar

@Mikejs

  • Authentication = is logged in
  • Authorization = what can the logged in user with role /s do or not do

Example:

  • Bob is an admin

  • Suzy is admin and does bookkeeping

  • Mary is a bookkeeper only

  • If Bob is logged in, Bob can only do admin stuff and all access to user stuff. But Bob cannot mess with bookkeeping.

  • If Suzy is logged in she can access admin stuff and bookkeeping and accounting stuff.

  • If Mary is logged in she cannot mess with admin stuff, but has access to bookkeeping and accounting stuff.

So I just check at method level if the logged in users role can or cannot access that method / function.

And use query scopes to let a user edit / view their own data or an admin can access all users data.

Each app will be different as to who can do what.

So in pseudocode:

public function makeInvoice()
    {
        if (a required role of bkeep is not true here) {   // bkeep = bookkeeper
            return redirect('somewhere'); // whereever you redirect to if not authorized
        }
        // Rest of method here is accomplished if 
        // the logged in user has the required role of 'bkeep'.
    }

Again just examples.

Also a Spatie example I saw:

public function update(Request $request, Post $post) {
    if ($post->author !== auth()->user()->id || auth()->user()->cannot('edit posts'))
        abort(404);// or redirect, or whatever action 
    }
    //rest of method if all okay
}

In summary RBAC is at least 3 main steps:

  • A login required
  • An authorization implementation to determine what the logged in person with role can or cannot do
  • Protection of URL and parameters, checking that the logged in users id matches the id used in a query

Each application will require unique tweaks in RBAC, no two apps are exactly the same.

2 likes
NoLAstNamE's avatar

@jlrdw I think what @mikejs wants to do is the correct redirection of users to their intended dashboard based on their roles.

1 like
jlrdw's avatar

@benjamin1509 I just make home a redirect endpoint, or change to another name. The endpoint handles redirection depending on role.

For example if bookkeeper, then redirect to that dashboard. A little more involved (dual roles) but that's the idea.

Just my opinion, but after trying every starter kit, I went back to manual Auth as per the documentation.

https://laravel.com/docs/10.x/authentication#authenticating-users

Seems much less restrictive. Breeze seems to think you will only have one user type thus one dashboard. A real App has multiple "landing pages" depending on role.

1 like
NoLAstNamE's avatar

In default Laravel, there's one constant responsible for the redirection of logged-in users:

app/Providers/RouteServiceProvider.php:

class RouteServiceProvider extends ServiceProvider
{
    /**
     * The path to the "home" route for your application.
     * Typically, users are redirected here after authentication.
     */
    public const HOME = '/home';

Laravel itself uses that RouteServiceProvider::HOME in the Middleware which is fired if the user is already logged in.

app/Http/Middleware/RedirectIfAuthenticated.php:

class RedirectIfAuthenticated
{
    public function handle(Request $request, Closure $next, ...$guards)
    {
        $guards = empty($guards) ? [null] : $guards;
 
        foreach ($guards as $guard) {
            if (Auth::guard($guard)->check()) {
                return redirect(RouteServiceProvider::HOME);
            }
        }
 
        return $next($request);
    }
}

So, first, you need to change that redirect() to your custom logic.

Let's say that your logic will be inside of your User model, like this:

app/Models/User.php:

class User extends Authenticatable
{
    // ...
 
    public function getRedirectRoute()
    {
        return match((int)$this->role_id) {
            1 => 'student.dashboard',
            2 => 'teacher.dashboard',
            // ...
        };
    }
}

Then, in the RedirectIfAuthenticated Middleware, you change it to this:

if (Auth::guard($guard)->check()) {
    return redirect(Auth::user()->getRedirectRoute());
}

Laravel Breeze

Laravel Breeze uses the same RouteServiceProvider::HOME in two places separately: Controller for the Registration and for the Login.

app/Http/Controllers/Auth/RegisteredUserController.php:

public function store(Request $request): RedirectResponse
{
    // ...
 
    Auth::login($user);
 
    return redirect(RouteServiceProvider::HOME);
}

Change the last line to:

return redirect(auth()->user()->getRedirectRoute());

And then the Login Controller.

app/Http/Controllers/Auth/AuthenticatedSessionController.php:

public function store(LoginRequest $request): RedirectResponse
{
    $request->authenticate();
 
    $request->session()->regenerate();
 
    return redirect()->intended(RouteServiceProvider::HOME);
}

Change the last line to:

return redirect()->intended(auth()->user()->getRedirectRoute());
Tray2's avatar

@mikejs like @jlrdw says, there are two parts to this.

  1. Authentication
  2. Authorization

The first one is handled by breeze, and the users table.

The second part is handled with roles, and I suggest that you keep the users table intact, and don't add any columns to it. I would create a roles table, and a role_user table to keep track of that roles a user have, since it's quite likely that a user have more than one role.

Then it all comes down to using guards and scopes just like @jlrdw says.

You can use the laravel permission package from Spatie if you want some help and not write everything from scratch.

https://spatie.be/docs/laravel-permission/v5/introduction

2 likes

Please or to participate in this conversation.