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

KimAndersen's avatar

User roles in Laravel 6

I've been searching the net empty, and still haven't figured out what I am doing wrong!

I am trying to make a simple middleware where I decide if users has the expected roles for specific routes/Controllers. He's the data:

  1. The roles and user attachment of those roles is working.
  2. I created a middleware called "CheckRole" and in my controller I use the middleware in the constructor, i.e. $this->middleware(['role:writer', 'role:admin']);
  3. In Kernel.php in the $routeMiddleware array, I added 'role' => CheckRole::class,

All of this is working. if I log in as admin or writer, the CheckRole class passes the permission check, and proceeds to the return $next($request);

BUT - here it has already been decided that I don't have permission or something else is going wrong that denies me access to the url, and I get a "403 permission denied" request. The $request->url() is the url I asked for, but $next($request))is this 403 request.

What am I missing?

0 likes
7 replies
NoTimeForCaution's avatar

It sounds as though it's working as intended. You say if you login as admin and send a request you are allowed to proceed. If you don't have permission, a 403 is returned.

That's the concept of route middleware.

Please post your middleware code.

KimAndersen's avatar

Wow - that was quick - thanks :) Here's the code:

<?php

namespace App\Http\Middleware;

use App\Models\Role;
use Closure;
use Illuminate\Support\Facades\App;

class CheckRole
{
    public function handle($request, Closure $next, string $role)
    {
        $roleId = Role::whereTitle(ucfirst($role))->first()->id;

        if (!$request->user()) {
            return redirect('login');
        } else if (!$request->user()->hasRole($roleId)) {
            return App::abort(403);
        }

       // This is where I stand before getting redirected

        return $next($request);
    }
}
Sinnbeck's avatar
Sinnbeck
Best Answer
Level 102

Venter på Mortens and så skulle bruge tiden på noget :)

It seems that the issue is that it runs the middleware twice and fails at the second iteration. (once for writer and one for admin). You could probably do something like this

$this->middleware(['role:writer|admin']);
else if (!$request->user()->hasAnyRole(explode("|", $role))
KimAndersen's avatar

AMAZING - and I am shouting :) Of cause it runs twice. It escaped my attention.

I was assuming from the documentation that this did apply to my case too:

Route::get('/', function () {
    //
})->middleware('first', 'second');

So, I definitely need to find another way to handle multiple roles. Your idea is good, and I'll base the solution on that.

Thanks a lot!

And bon appétit with Mortens and :) Tak for hjælpen Sinnbeck :)

Sinnbeck's avatar

Happy to help. If it helped you solve the issue, please mark "best answer"

KimAndersen's avatar

The final solution was simple, when I understood the problem - and is more of a DOH than an AHA.

Problem: Users with roles admin and writershould have access to the controller.

Solution: The middleware must require the "lowest" role, i.e. role:writer. So now the writer has acces. The admin must have writer access too - and also admin access, so admin gets both roles.

And the code from the middleware class CheckRole:

$usersRoles = $request->user()->roles->pluck('id')->toArray();

 if (!$request->user()) {
     return redirect('login');
 } else if (!in_array($roleId, $usersRoles)) {
     return App::abort(403);
 }

 return $next($request);

And in the controller's constructor:

$this->middleware(['role:writer']);

Please or to participate in this conversation.