Profile    Mohammed Shiroz Status   Loading  
Logo
Share This
Back to blog
Filter by:
Tags
//Article title

Laravel Sanctum vs Passport: Which Auth Package Do You Actually Need?

About Post

You need API authentication in Laravel. You search, and two official packages come up: Sanctum and Passport. Both issue tokens. Both protect routes. Both have long documentation pages.

So people pick one almost at random, or pick Passport because "OAuth sounds more serious". And then they spend a week configuring clients, grants and encryption keys for an app that only ever needed a login screen.

The choice is much simpler than it looks. It comes down to one question, and I'll get to it. First, what each package actually is.

Sanctum: simple auth for your own apps

Sanctum does two separate jobs, and mixing them up is the source of most confusion.

Job 1: SPA authentication with cookies

If your React or Vue front end runs on the same top-level domain as your Laravel API (say app.example.com and api.example.com), Sanctum doesn't use tokens at all. It uses Laravel's normal session cookie, with CSRF protection. No token in localStorage for an XSS bug to steal.

In Laravel 12 you turn it on in bootstrap/app.php and list your front-end domain in the SANCTUM_STATEFUL_DOMAINS env variable:

->withMiddleware(function (Middleware $middleware) {
    $middleware->statefulApi();
})

The front end first asks for a CSRF cookie, then logs in normally:

axios.defaults.withCredentials = true;
axios.defaults.withXSRFToken = true;

await axios.get('/sanctum/csrf-cookie');
await axios.post('/login', { email, password });
// From now on, the session cookie authenticates API calls

Job 2: API tokens for mobile apps and scripts

A React Native app can't rely on browser cookies the same way, so Sanctum also issues simple API tokens. The user logs in, you create a token, and the app sends it as a Bearer header:

Route::post('/mobile/token', function (Request $request) {
    $request->validate([
        'email' => 'required|email',
        'password' => 'required',
        'device_name' => 'required',
    ]);

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

    if (! $user || ! Hash::check($request->password, $user->password)) {
        throw ValidationException::withMessages([
            'email' => ['The provided credentials are incorrect.'],
        ]);
    }

    return $user->createToken($request->device_name, ['contracts:read'])
        ->plainTextToken;
});

Tokens are random strings, stored as a SHA-256 hash in the personal_access_tokens table. You can give them abilities ($request->user()->tokenCan('contracts:read')), set expiry, and revoke one device without logging out the others. Protect routes with auth:sanctum and you're done. (Simplified: add rate limiting to that login route in a real app.)

Passport: a full OAuth2 server

Passport is a different kind of tool. It turns your Laravel app into an OAuth2 authorization server, the same kind of system behind "Sign in with..." buttons and "Allow this app to access your account?" screens.

That means it supports OAuth2 grant types:

  • Authorization code (with PKCE): a third-party app sends the user to your login page, the user approves access, and the app receives a token. The app never sees the user's password.
  • Client credentials: machine-to-machine access, where a partner's server authenticates as itself, not as a user.
  • Refresh tokens, OAuth scopes, client registration and consent screens.

It also brings real moving parts: encryption keys to generate and protect, OAuth clients to manage, more tables, and a protocol with plenty of ways to misconfigure it. That's a fair price when you need OAuth. It's pure overhead when you don't.

Side by side

SanctumPassport
What it isLightweight auth for your own clientsFull OAuth2 server
SPA on same domainCookie sessions + CSRFPossible, but not its strength
Mobile app (your own)Personal access tokensWorks, more setup
Third-party apps acting for your usersNoYes (authorization code + PKCE)
Machine-to-machineToken on a service userClient credentials grant
Setup in Laravel 12php artisan install:apiphp artisan install:api --passport
ComplexityLowHigh

The one question

Will apps that you don't own need to access your users' data on their behalf? If yes, you need an OAuth2 server: use Passport. If no, use Sanctum.

Almost everything else falls out of that. A typical setup with a web portal, a staff app and a tenant app, all built by the same team, is a Sanctum project: cookie auth for the web, tokens for the mobile apps, abilities and policies for permissions. No third party is asking your users for consent, so there's no OAuth flow to support.

Passport earns its place when you're building a platform: partners integrating with your API on behalf of shared customers, a developer portal, or "Connect your account to X" flows.

Mistakes I see with both

  • Choosing Passport "for the future". If OAuth becomes a requirement, you can add it then. You'll pay the complexity cost every day until then.
  • Using Sanctum tokens in a browser SPA when cookie auth was available. Tokens in localStorage are readable by any injected script.
  • Forgetting SANCTUM_STATEFUL_DOMAINS and the CORS supports_credentials setting, then wondering why the SPA gets 401s right after logging in.
  • Tokens that never expire. Set an expiry that fits your app, and schedule sanctum:prune-expired to clean old rows.
  • Treating abilities as authorisation. A token ability says what the token may do. Policies still decide whether this user may touch this record.

The short version

  • Your own SPA on the same domain: Sanctum, cookie mode.
  • Your own mobile app: Sanctum tokens.
  • Other people's apps acting for your users: Passport.
  • Not sure: Sanctum, until a real OAuth requirement shows up.

Have you ever migrated from one to the other? I'm curious which direction it went, and what pushed you to do it.

Comments (0)
Leave your review

Thanks for your valuable comments. Your comments has been updated and appreciate your getting in touch...

01. About Shiroz

Mohammed Shiroz

Hi, I'm Mohammed Shiroz, a software engineer and AI enthusiast from Sri Lanka who turns ideas into intelligent, real-world solutions. With over 9 years of hands-on experience, I currently lead real estate ERP development at Kate Group, a...

03.My Projects

04. Categories

Ready To order Your Project ?

Get in Touch
Close