minaremonshaker's avatar

Managing Authorization with Sanctum and Spatie Permissions

When integrating authorization using the Spatie Permission package alongside Sanctum token-based authentication in my API, should I modify the abilities column in the personal_access_tokens table, or rely solely on the Spatie package for handling authorization?

0 likes
7 replies
LaryAI's avatar
Level 58

When integrating Sanctum for authentication and the Spatie Permission package for authorization, it’s generally best to let each package do what it’s designed for:

  • Sanctum: Handles authentication (who the user is), and can optionally restrict tokens to certain abilities/scopes.
  • Spatie Permission: Handles authorization (what the user can do), such as assigning roles and permissions.

Best Practice:

  • Use Sanctum to authenticate API requests.
  • Use Spatie Permission to check if the authenticated user has the required roles/permissions.

There’s no need to modify the abilities column of personal_access_tokens unless you have a use-case for token-specific capabilities (rare if you’re fully using Spatie for authz). The abilities column is for restricting what each token can do, similar to OAuth2 scopes.

Typical Setup Example:

// In your route or controller
use Illuminate\Http\Request;

Route::middleware(['auth:sanctum'])->group(function() {
    Route::get('/admin', function(Request $request) {
        if ($request->user()->can('view admin dashboard')) {
            // Authorized via Spatie Permission
            return 'Welcome Admin!';
        }
        abort(403, 'Unauthorized.');
    });
});

Summary Table:

Concern Package Used What to Do
Authentication Sanctum Don't modify abilities unless you want scoped tokens
Authorization Spatie Permission Use roles/permissions checks ($user->can('...'))

Only use Sanctum’s abilities/scopes if you want some tokens for limited purposes, separate from Spatie’s role/permission system.

Reference:

Summary:
You should rely on the Spatie package to check permissions/roles, and let Sanctum handle authentication, without needing to alter the abilities column unless your app has a specific need for token abilities.

martinbean's avatar

should I modify the abilities column in the personal_access_tokens table

@minaremonshaker I don’t really know what you mean by this, but it certainly sounds the wrong way to do anything.

A Sanctum token is just a token to say, “authorise the request as this user”. Your application should be defining what that user can and cannot do, regardless if they’re authentication via a session, a Sanctum token, an OAuth token, or any other mechanism.

minaremonshaker's avatar

hi @martinbean
What I mean is that without using the Spatie permissions package, I would need to assign specific abilities to each user token, and update those abilities whenever I want the token to perform certain actions. However, when using Spatie permissions, this process is overridden — meaning there’s no need to manually assign abilities to the token.

martinbean's avatar
Level 80

What I mean is that without using the Spatie permissions package, I would need to assign specific abilities to each user token, and update those abilities whenever I want the token to perform certain actions.

@minaremonshaker Why would you? The permissions should be held server-side. If a user without Permission X then uses their token to do something that requires Permission X, your application should return a 403 Forbidden error because they don’t have the ability to do that.

This is what should happen regardless of what you use for authorisation, be it Spatie’s package, Laravel’s built-in policies, or something else.

A token should not be declaring its own permissions otherwise you can open your application up to privilege escalation vulnerabilities where someone can issue themselves a token with more permissions than they normally would have.

JussiMannisto's avatar

@minaremonshaker @martinbean

Sanctum's token abilities are analogous to scopes in OAuth 2. They can be used to limit what a token can do, but they're not meant as a replacement for other forms of authorization.

martinbean's avatar

@jussimannisto I wouldn’t rely on them, though.

For example, imagine there are two roles in an app: editor and administrator. User only has “editor” role. What if they manage to issue themselves a Sanctum token (or OAuth token) with the “administrator” scope as well? This should not be allowed, and is why the application should be trusted for authorisation instead.

JussiMannisto's avatar

You wouldn't use abilities as a replacement for roles. They're just an additional layer of authorization. Since you can issue tokens for all sorts of things from API integrations to mobile apps, it's good to scope what each token can do.

Route::get('/something', SomeMobileEndpointController::class)
	->middleware(['auth:sanctum', 'ability:mobile-app'])
	->name('foo');

Tokens and their abilities are granted server-side and stored in a database. The token itself is just an opaque string. If a user manages to issue a token with arbitrary abilities, that's a server-side security bug.

Please or to participate in this conversation.