Authorization Boundaries
Laravel Access checks roles and permissions in a scoped or global context. Your application still owns authentication, membership, and rules for individual records.
Use Laravel policies for object-specific rules. Use middleware for simple route checks. A frontend permission map can hide or show interface elements, but it cannot authorize a server request.
Keep Membership and Access Checks Separate
The membership tables generated by access:scope belong to your application. Laravel Access assignments belong to the package. A role assignment does not add a user to your application scope, and membership does not grant Laravel Access permissions.
When an action requires both membership and permission, check both in the policy:
public function invite(User $user, Company $company): bool
{
return $user->belongsToCompany($company)
&& $user->in($company)->can(Permission::CompanyMembersInvite);
}2
3
4
5
The membership check answers whether the user belongs to the company. The scoped permission check answers whether the user can invite members in that company.
Check the Resource's Scope
Check that a record belongs to the scope being authorized. Do not compare only numeric IDs when records can belong to different model types. A Company and a Team can have the same ID.
For dynamic roles, compare both the role's scope_type and scope_id with the supplied scope. See Dynamic Roles for a policy example.
Keep Scoped and Global Access Separate
Use $user->in($company)->can(...) for permissions inside a company. Use $user->canGlobally(...) for app-wide permissions. A global role has no scope and does not prove membership in a company.
If a platform administrator must bypass a company permission, add a separate, explicit global permission check to the policy. Do not use a global role as a substitute for normal scoped access checks.
Authorize on the Server
Check access in a policy, middleware, or controller for every protected server action. Use frontend permission maps only to shape the interface. A hidden button does not prevent a direct request to the route.
For route middleware, pass the route parameter that identifies the scope. When the action also requires application membership, enforce that membership separately. See Middleware and Use Policies.
Review Generated Application Code
access:scope generates first-party application files. Review and maintain those files as application code. Later package versions do not rewrite files that were generated earlier.
For generated invitation routes, use the scoped invitation permission and the app-owned membership check together. If you generated the route before that permission check was added, update the route yourself. See Scaffold Team Scopes.
Seed privileged assignments only for existing, trusted accounts provisioned by your application. Do not create an Owner or Admin account from fixed credentials. See Seed Roles and Permissions.