Secure API Endpoints with Laravel Passport Personal Access Tokens and Scopes
Learn how to set up Laravel Passport personal access tokens with fine‑grained scopes, protect routes, and avoid common mistakes. A step‑by‑step guide with code examples and best‑practice tips.
06 Dec 2025, 07:56 UTC

Why Personal Access Tokens Matter
When building an API that needs to authenticate users without the overhead of OAuth2 flows, Laravel Passport’s Personal Access Tokens give you a lightweight, token‑only solution. They are ideal for mobile apps, SPA front‑ends, or internal services where the user is already known and you don’t want to expose client credentials.
Getting the Tokens Working – The Quick Answer
1. Install Passport and run migrations.
2. Register the personal access client.
3. Add the HasApiTokens trait to your User model.
4. Create a token with the desired scopes.
5. Protect routes with auth:api and scopes middleware.
Step 1: Install and Configure Passport
# In your project root
php artisan migrate
php artisan passport:install
The passport:install command generates the encryption keys and inserts two clients into oauth_clients – one for password grant and one for personal access. The personal access client id and secret are stored in the database and can be retrieved via App\Models\Client::personalAccessClient().
Step 2: Update Your User Model
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
}
Also ensure your config/auth.php has an api guard using the passport driver:
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
Step 3: Create a Personal Access Token with Scopes
In a controller or tinker session you can issue a token like this:
$user = App\Models\User::find(1);
$tokenResult = $user->createToken('MyToken', ['read', 'write']);
$accessToken = $tokenResult->accessToken;
// Optional: set a custom expiration
$accessToken->expires_at = now()->addHours(2);
$accessToken->save();
return ['token' => $tokenResult->accessToken->plainTextToken];
The abilities (scopes) are stored as a JSON array in the oauth_access_tokens table. If you omit the array, the token inherits all abilities of the client, which can unintentionally grant full access.
Step 4: Protect Routes with Middleware
Route::middleware(['auth:api', 'scopes:read'])->get('/api/profile', function (Request $request) {
return $request->user();
});
The scopes middleware checks that the bearer token contains the required ability. A missing scope results in a 401 Unauthorized response.
Step 5: Verify Token Creation
After issuing a token, confirm it exists in the database:
SELECT * FROM oauth_access_tokens WHERE token = '';
Check the abilities column shows ['read','write'] and expires_at matches your custom value.
Limitations & Common Pitfalls
- No Default Expiration – Personal access tokens live forever unless you set
expires_ator configureconfig/passport.php’spersonal_access_token_expiration. - Broad Access Without Scopes – Creating a token without specifying scopes grants the token all permissions of the client/user. Always list the minimal scopes needed.
- Missing
passport:installStep – Without this,oauth_clientsis empty and any token request throws a runtime exception. - Revocation Not Automatic – Tokens are not revoked on logout. Call
$token->accessToken->revoke()or delete fromoauth_access_tokensto enforce session expiry. - Laravel Version Assumptions – The examples target Laravel 9+. Earlier versions may have slightly different config keys.
Best Practices Checklist
- Always run
php artisan passport:installafter fresh migrations. - Define explicit scopes when creating tokens.
- Set
expires_ator use the config option for time‑bounded access. - Revoke tokens on logout or when a user’s privileges change.
- Use the
scopesmiddleware on all protected routes. - Audit the
oauth_access_tokenstable regularly for orphaned tokens.
Conclusion
Laravel Passport’s personal access tokens, combined with scope enforcement, provide a robust, developer‑friendly way to secure API endpoints. By following the steps above and watching out for the common pitfalls, you can give your clients a minimal‑privilege, time‑bounded authentication mechanism that scales with your application’s growth.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.