Case: I'm building a forum using Laravel's Authorization as a backbone using policies. Examples of checks I run are stuff like @can('view', $forum)
, and @can('reply', $topic)
, Gate::allows('create_topic', $forum)
etc. These checks basically checks if the users role has that permission for the specific forum, topic or post. That way I can give roles very specific permissions for each forum in my application.
The issue is that all of these checks go through the Gate class, specifically a method called raw()
which in its first line does this:
if (! $user = $this->resolveUser()) {
return false;
}
This presents an issue when dealing with forums. Guests to my application should also be allowed to view my forum, however as you can see from the code above, Laravels Gate class automatically returns false if the user is not logged in.
I need to be able to trigger my policies even if there is no user. Say in my ForumPolicy@view
method, I do if(User::guest() && $forum->hasGuestViewAccess()) { return true }
But as you can see, this method will never trigger.
Is there a way for me to still use Laravel's authorization feature with guest users?
The guest user selects Send code: A passcode is sent to the user's email address. The user retrieves the passcode from the email and enters it in the browser window: The guest user is now authenticated, and they can see the shared resource or continue signing in.
MFA policies can be enforced at the tenant, app, or individual guest user level, the same way that they are enabled for members of your own organization.
Guest user permissions Guest users have default restricted directory permissions. They can manage their own profile, change their own password, and retrieve some information about other users, groups, and apps. However, they can't read all directory information.
Only users assigned to specific admin roles can invite guest users: To allow only those users with administrator roles to invite guests, select this radio button. The administrator roles include Global Administrator, User Administrator, and Guest Inviter.
I'm not aware of a super natural way to accomplish this, but if it's necessary, you could change the gate's user resolver, which is responsible for finding users (by default it reads from Auth::user()
).
Since the resolver is protected and has no setters, you'll need to modify it on creation. The gate is instantiated in Laravel's AuthServiceProvider
. You can extend this class and replace the reference to it in the app.providers
config with your subclass.
It's going to be up to you what kind of guest object to return (as long as it's truthy), but I'd probably use something like an empty User
model:
protected function registerAccessGate()
{
$this->app->singleton(GateContract::class, function ($app) {
return new Gate($app, function () use ($app) {
$user = $app['auth']->user();
if ($user) {
return $user;
}
return new \App\User;
});
});
}
You could go a step further and set a special property on it like $user->isGuest
, or even define a special guest class or constant.
Alternatively you could adjust your process at the Auth
level so that all logged-out sessions are wrapped in a call to Auth::setUser($guestUserObject)
.
I just released a package that allows permission logic to be applied to guest users. It slightly modifies Laravel's Authorization to return a Guest
object instead of null
when no user is resolved. Also every authorization check now makes it to the Gate instead of failing authorization instantly because there isn't an authenticated user.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With