How can I bring a session variable into the AuthServiceProvider in this Laravel 8 application?

Viewed 286

I am working on a Laravel 8 app with users, roles and permissions. I use Microsoft Azure for user sign-up and sign-in. I began by following this tutorial on their website.

I use a custom middleware in routes\web.php to discriminate authenticated users from guests:

Route::group(['prefix' => 'dashboard', 'middleware' => ['checkSignedIn']], function() {
    Route::get('/', [DashboardContoller::class, 'index'])->name('dashboard');
    //More routes
}); 

I get a list of comma-separated user permissions specific to every user role, from a permissions MySQL table.

I store the userPermissions variable in a session like this:

public function storeTokens($accessToken, $user, $user_role, $user_permissions) {
 session([
  'accessToken' => $accessToken->getToken(),
  'refreshToken' => $accessToken->getRefreshToken(),
  'tokenExpires' => $accessToken->getExpires(),
  'userName' => $user->getDisplayName(),
  'firstName' => $user->getGivenName(),
  'lastName' => $user->getSurname(),
  'userRole' => $user_role,
  'userPermissions' => $user_permissions,
  'userEmail' => null !== $user->getMail() ? $user->getMail() : $user->getUserPrincipalName(),
  'userTimeZone' => $user->getMailboxSettings()->getTimeZone()
 ]);
}

This alows me to output the current (signed in) user's list of permissions in a view (the navbar.blade.php partial), directly from the session, like this:

@if(session('userPermissions'))
  <ul>
    @foreach (session('userPermissions') as $up)
      <li>{{ $up }}</li>
    @endforeach
  </ul>
@endif 

The goal

My intention (the purpose of creating session('userPermissions')) is to use the user's permissions in Gates. For this purpose, in app\Providers\AuthServiceProvider.php I have:

// More code
use Illuminate\Support\Facades\Gate;
// More code

/* View Users */
Gate::define('view-users', function() {
  return in_array('view-users', session('userPermissions'));
});

In the base-controller (app\Http\Controllers\Controller.php) I have imported the Gate facade with use Illuminate\Support\Facades\Gate and then, in users.blade.php

@can('view-users') 
    <h2>Users</h2>
    <table class="table">
        <thead>
            <tr>
                <th>Name</th>
                <th>Email</th>
                <th>Role</th>
            </tr>
        </thead>
        @if ($users)
        <tbody>
            @foreach ($users as $user)
            <tr>
                <td>{{ $user->first_name }} {{ $user->last_name }}</td>
                <td>{{ $user->email }}</td>
                <td>{{ $user->role }}</td>
            </tr>
            @endforeach
        </tbody>
        @endif
    </table>
@endcan 

The problem

Evan if the current user does have the view-users permission (and that is visible in the navbar), the Users table is not present and doing dd(session('userPermissions')) in AuthServiceProvider.php returns null.

Where is my mistake?

1 Answers

Assuming you have Policy & Gate registered in App\Providers\AuthServiceProvider.

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        User::class => UserPolicy::class,
    ];
 
    /**
     * Register any application authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        // this merely maps the name of the gate
        Gate::define('view-users', [UserPolicy::class, 'index']);
    }
}

CLI command:

php artisan make:policy UserPolicy --model=User

Then in class UserPolicy, you have to implement method index().


One can check in the controller already, before even rendering any Blade template.

For your use case ... see the examples for: Methods Without Models or Guest Users.

It's pointless to depend on session(), when the Gate knows User $user ...

Related