This document discusses Laravel's authorization features including gates, AuthServiceProvider, and policies. It provides an example scenario of a user community website to demonstrate how these features can be used to control authorization for different user and community roles and actions. Key points covered include defining gates in the AuthServiceProvider, creating policies to group related authorization logic, and checking abilities in controllers, views, and elsewhere using the Gate facade, user model, or policy helpers. Overall these features provide a clean, organized way to handle authorization in Laravel applications.
2. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
WHOAMI
▸ Alison Gianotto (aka “snipe”, aka @snipeyhead)
▸ One of the original members of SDPHP ;)
▸ Working with PHP for 15+ years
▸ CTO/Co-Founder of AnySha.re
▸ Founder of Grokability, Inc.
▸ Creator of Snipe-IT and other internet things
3. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
PROBLEMS THE AUTHSERVICEPROVIDER SOLVES
▸ Much cleaner syntax in blades (@can and @cannot)
▸ One unified place to keep authorization rules
▸ Assumes a user instance. If no user available, it fails to false
▸ Can handle basic authorization (“does the user own this
thing?”) or much more sophisticated rules based off your
model methods.
4. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/PROVIDERS/AUTHSERVICEPROVIDER.PHP
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
// --------------------------------
// BEFORE ANYTHING ELSE
// --------------------------------
$gate->before(function ($user, $ability) {
if ($user->superadmin=='1') {
return true;
}
});
5. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
SCENARIO: USER COMMUNITY WEBSITE
▸ users table
▸ communities table with user_id for creator
▸ communities_users pivot table
▸ boolean is_admin
▸ entries table with created_by for creator
6. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
SCENARIO: USER COMMUNITY WEBSITE: USERS
▸ Users CAN update their own posts
▸ Users CAN delete their own posts
▸ Users CANNOT update other users’ posts
▸ Uses CAN see other posts in a community
▸ … (etc)
▸ Users CAN message other users if they are not blocked
▸ Users CANNOT messages other users if they are blocked
7. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/PROVIDERS/AUTHSERVICEPROVIDER.PHP
// Check if the user can update an entry
$gate->define('update-entry', function ($user, $entry) {
return $user->id === $entry->created_by;
});
8. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/USER.PHP (USER MODEL)
/**
* Checks if a user is a member of a community
*
* @param Community $community
* @return boolean
*/
public function isMemberOfCommunity($community)
{
return $this->communities()
->where('community_id', '=', $community->id)
->count() > 0;
}
9. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/HTTP/ENTRIESCONTROLLER.PHP (VIA GATE FACADE)
public function getEdit(Request $request, $id)
{
if ($entry = Entry::find($id)) {
if (Gate::denies('update-entry', $entry)) {
// You can return a 403 or whatever you want here
abort(403);
}
return view('entries.edit');
}
return redirect()->back()->with('error', 'Invalid entry.');
}
10. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/HTTP/ENTRIESCONTROLLER.PHP (VIA USER MODEL)
public function getEdit(Request $request, $id)
{
if ($entry = Entry::find($id)) {
if ($request->user()->cannot('update-entry', $entry)) {
// You could return a 403 response here, etc.
abort(403);
}
return view('entries.edit');
}
return redirect()->back()->with('error', 'Invalid entry.');
}
12. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/HTTP/ENTRIESCONTROLLER.PHP (VIA FORM REQUEST)
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$entryId = $this->route('entry');
return Gate::allows('update', Entry::findOrFail($entryId));
}
13. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
SCENARIO: USER COMMUNITY WEBSITE: COMMUNITY ADMINS
▸ Community admins CAN edit their own community
settings
▸ … (etc)
▸ Community admins CAN update user posts
▸ Community admins CAN add/remove users from
community
14. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/USER.PHP (USER MODEL)
/**
* Returns whether or not the user is an admin of a community
*
* @param object $community
* @return boolean
*/
public function isAdminOfCommunity($community)
{
return $this->communities()
->where('community_id', '=', $community->id)
->where('is_admin', '=', '1')
->count() > 0;
}
15. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/PROVIDERS/AUTHSERVICEPROVIDER.PHP
// Check if the user can join a community
// (they are not already a member)
$gate->define('join-community', function ($user, $community) {
if (!$user->isMemberOfCommunity($community)) {
return true;
}
});
// Check if the user can update the community settings
// (they are an admin)
$gate->define('update-community', function ($user, $community) {
if ($user->isAdminOfCommunity($community) ) {
return true;
}
});
16. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
THIS COULD GET OUT OF HAND QUICKLY.
ENTER POLICIES.
17. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
CREATING A POLICY
> php artisan make:policy EntryPolicy
Policy created successfully.
> php artisan make:policy CommunityPolicy
Policy created successfully.
18. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/POLICIES/ENTRYPOLICY.PHP
<?php
namespace AppPolicies;
use AppUser;
use AppEntry;
use IlluminateAuthAccessHandlesAuthorization;
class EntryPolicy
{
use HandlesAuthorization;
public function update(User $user, Entry $entry)
{
return $user->id === $entry->created_by;
}
public function delete(User $user, Entry $entry)
{
// etc
}
}
19. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/POLICIES/COMMUNITYPOLICY.PHP
<?php
namespace AppPolicies;
use AppUser;
use AppCommunity;
use IlluminateAuthAccessHandlesAuthorization;
class CommunityPolicy
{
use HandlesAuthorization;
public function update(User $user, Community $community)
{
return $user->id === $community->created_by;
}
public function delete(User $user, Community $community)
{
// etc
}
}
20. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/PROVIDERS/AUTHSERVICEPROVIDER.PHP
<?php
namespace AppProviders;
use AppPoliciesEntryPolicy;
use AppPoliciesCommunityPolicy;
use IlluminateContractsAuthAccessGate as GateContract;
use IlluminateFoundationSupportProvidersAuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
Entry::class => EntryPolicy::class,
Community::class => CommunityPolicy::class,
];
/**
* Register any application authentication / authorization services.
*
* @param IlluminateContractsAuthAccessGate $gate
* @return void
*/
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
}
21. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/PROVIDERS/AUTHSERVICEPROVIDER.PHP
<?php
namespace AppProviders;
use AppPoliciesEntryPolicy;
use AppPoliciesCommunityPolicy;
use IlluminateContractsAuthAccessGate as GateContract;
use IlluminateFoundationSupportProvidersAuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
Entry::class => EntryPolicy::class,
Community::class => CommunityPolicy::class,
];
/**
* Register any application authentication / authorization services.
*
* @param IlluminateContractsAuthAccessGate $gate
* @return void
*/
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
}
22. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
CHECKING POLICIES
▸ Via Gate facade
▸ Via User Model
if (Gate::denies('update', $entry)) {
//
}
if ($user->can('update', $entry)) {
//
}
23. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
CHECKING POLICIES
▸ Via Blade shortcut:
▸ Via Policy Helper:
@can('update', $entry)
@endcan
if (policy($entry)->update($user, $entry)) {
//
}
24. LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
CONCLUSION: THE AUTHSERVICEPROVIDER + POLICIES LETS YOU
▸ Use existing model methods to determine authorization
▸ Group related authorization rules together for
maintainability
▸ Use nifty shortcuts in your blades