Laravel Sanctum vs Passport which to use: A Practical Guide

We earn commissions when you shop through the links below.

If you’ve spent any time building Laravel APIs, you’ve inevitably hit the question of Laravel Sanctum vs Passport which to use. Both are official Laravel packages for API authentication, both are well-maintained, and both can get the job done — but they’re built for very different scenarios. Picking the wrong one can mean unnecessary complexity or missing features you’ll need later. Let me break it down clearly so you can make the right call without second-guessing yourself.

What Is Laravel Sanctum?

Sanctum is Laravel’s lightweight authentication package. It provides two main features: simple token-based authentication for SPAs and mobile apps, and a dead-simple way to issue personal access tokens. Under the hood, tokens are stored in your database and matched against a hashed value on each request. There’s no OAuth server, no authorization codes, no refresh token dance — just clean, minimal API token management.

Sanctum also handles cookie-based session authentication for first-party SPAs, which means if your React or Vue frontend is on the same domain as your Laravel backend, Sanctum can authenticate requests using Laravel’s session cookies rather than tokens. This is genuinely elegant when it fits your architecture.

What Is Laravel Passport?

Passport is a full OAuth2 server implementation built on top of the League OAuth2 Server library. It supports authorization codes, client credentials, personal access tokens, implicit grants, and password grants. It’s significantly heavier than Sanctum and requires additional setup — migrations, encryption keys, and a proper understanding of OAuth2 flows.

Passport shines when you need to act as an OAuth2 provider: letting third-party applications authenticate your users, issuing tokens with fine-grained scopes, or building a platform where external developers integrate via your API.

The Core Difference

Here’s the blunt truth: Sanctum is for your own apps authenticating your own users. Passport is for building an OAuth2 provider that lets external apps authenticate your users or act on their behalf.

Most SaaS products, mobile backends, and SPAs don’t need OAuth2. They need a reliable way to issue and revoke tokens — and Sanctum does that with zero ceremony. The question of Laravel Sanctum vs Passport which to use really comes down to: are you building for third-party integrations or not?

When to Use Sanctum

  • You’re building a SPA (React, Vue, Next.js) that consumes your own Laravel API
  • You’re building a mobile app (iOS, Android) that needs API token authentication
  • You need personal access tokens that users can generate and revoke
  • You want simple token scopes without full OAuth2 complexity
  • Your frontend and backend share a domain or subdomain

When to Use Passport

  • You’re building an OAuth2 provider (think: “Login with YourApp”)
  • Third-party developers need to request access to user accounts via authorization codes
  • You need machine-to-machine authentication with client credentials flow
  • Your platform requires token introspection or strict RFC-compliant OAuth2 behavior

Setting Up Sanctum (Quick Example)

Install and configure Sanctum in minutes:

composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate

Add the HasApiTokens trait to your User model:

use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
}

Issue a token on login:

public function login(Request $request)
{
    $request->validate([
        'email' => 'required|email',
        'password' => 'required',
    ]);

    $user = User::where('email', $request->email)->first();

    if (!$user || !Hash::check($request->password, $user->password)) {
        return response()->json(['message' => 'Invalid credentials'], 401);
    }

    $token = $user->createToken('api-token', ['read', 'write'])->plainTextToken;

    return response()->json(['token' => $token]);
}

Protect routes using the sanctum guard:

Route::middleware('auth:sanctum')->group(function () {
    Route::get('/user', fn(Request $r) => $r->user());
    Route::apiResource('posts', PostController::class);
});

That’s the entire flow. No keys to generate, no OAuth dance, no additional infrastructure.

Setting Up Passport (Key Steps)

Passport requires more upfront work:

composer require laravel/passport
php artisan migrate
php artisan passport:install

The passport:install command generates encryption keys and creates the default OAuth clients. You then add HasApiTokens from Passport (not Sanctum) to your User model and register routes in your AuthServiceProvider:

use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
}
// In AuthServiceProvider::boot()
Passport::routes();
Passport::tokensExpireIn(now()->addDays(15));
Passport::refreshTokensExpireIn(now()->addDays(30));
Passport::personalAccessTokensExpireIn(now()->addMonths(6));

You then configure your auth.php guards to use passport as the driver. From here, you get full OAuth2 endpoints: /oauth/authorize, /oauth/token, /oauth/token/refresh, and more.

Performance and Overhead

Sanctum tokens are validated with a single database lookup per request — fast and predictable. Passport’s JWT-based tokens (when using personal access tokens) don’t require a database hit on every request, but setting up and maintaining the OAuth infrastructure adds operational complexity. If you’re running a high-traffic API, the difference is minimal, but the complexity difference is real regardless of traffic.

For most teams, deploying Passport when Sanctum would suffice is genuine over-engineering. I’ve seen projects spend days debugging OAuth flows that they never actually needed.

Token Scopes: Sanctum vs Passport

Both packages support token scopes, but they work differently. Sanctum scopes are simple strings you define yourself and check manually:

// Check scope on a request
if ($request->user()->tokenCan('write')) {
    // Allow action
}

// Or use middleware
Route::middleware(['auth:sanctum', 'abilities:read,write'])->group(...);

Passport scopes are part of the OAuth2 spec — clients request specific scopes during the authorization flow, and they’re enforced at the middleware level with proper RFC behavior. If you need scopes enforced across third-party clients, Passport handles this more rigorously. For internal use, Sanctum’s approach is more than adequate.

The Honest Decision Framework

When developers ask me about Laravel Sanctum vs Passport which to use, I ask them three questions:

  1. Will third parties need OAuth2 authorization codes to access your users’ data? If yes, use Passport.
  2. Is this a first-party SPA or mobile app? If yes, use Sanctum.
  3. Are you unsure? Start with Sanctum. You can always migrate.

Migrating from Sanctum to Passport is painful but doable. Starting with Passport when you didn’t need it wastes engineering time every week maintaining OAuth infrastructure that adds no user value.

Learning More

If you’re newer to Laravel authentication concepts and want structured learning, Udemy has solid Laravel courses that cover both Sanctum and Passport in depth with real project examples — worth the investment if you’re building production systems and want to understand the full picture.

For hosting your Laravel application once you’ve nailed authentication, Railway makes deploying Laravel APIs straightforward with minimal DevOps overhead — great if you want to focus on the application rather than the infrastructure.

Final Verdict

The answer to Laravel Sanctum vs Passport which to use is almost always Sanctum — for the vast majority of Laravel projects. It’s simpler, faster to implement, and easier to maintain. Passport is a powerful tool, but it solves a specific problem: building an OAuth2 authorization server. If that’s not your problem, Sanctum is your answer.

Don’t let OAuth2 complexity creep into projects that don’t need it. Ship the simpler thing. Your future self will thank you.