Skip to main content

Cloudsoft Zone Build, deploy and scale with practical guides to PHP, Node.js, React, DevOps and AI automation. Explore the guides

Cloudsoft Zone
LaravelComparison

Laravel Sanctum vs Passport: which API authentication package to use

Sanctum and Passport both authenticate Laravel APIs, but they solve different problems. This comparison explains tokens, SPA cookies, OAuth2 grants, expiry and clean-up in Laravel 13, and when each package is the right choice.

Cloudsoft Zone

8 min read

Blue plush elephant toy, the PHP community mascot known as the elePHPant
Photograph: Atomic Taco from Seattle, WA, USA / CC BY-SA 2.0, via Wikimedia Commons
In this article

Almost every Laravel project that grows beyond a website needs API authentication sooner or later: a mobile app, a single-page front end, a partner integration or a command-line tool. Laravel offers two first-party packages for this, Sanctum and Passport, and teams regularly pick the heavier one when the lighter one would do, or the other way round.

This article explains what each package actually does in Laravel 13, where they overlap, and which one fits common situations. It is based on the official Laravel 13.x documentation for both packages, read on 7 October 2026. The short version from that documentation: if you truly need OAuth2, use Passport; for single-page applications, mobile apps and simple API tokens, use Sanctum.

The core difference in one paragraph

Laravel Sanctum is a lightweight authentication system. It issues personal API tokens that your own users create and send as bearer tokens, and it can authenticate your own single-page application using Laravel's normal session cookies. It does not implement OAuth2. Laravel Passport is a full OAuth2 server built on the League OAuth2 server library. It lets other applications obtain tokens on behalf of your users through standard OAuth2 grants, with clients, scopes, refresh tokens and consent screens.

So the deciding question is not "which is more secure" but "who are the clients?" If the clients are your own front end, your own mobile app or your users' scripts, Sanctum is usually enough. If third-party developers will build applications that ask your users for permission, you need an OAuth2 server, which is Passport.

Laravel framework logo with its red geometric mark and wordmark
Sanctum and Passport are both first-party Laravel packages installed with the install:api command.

Laravel Sanctum in Laravel 13

Installation

Sanctum is installed by the same command that enables API routing:

Shell
php artisan install:api

This creates routes/api.php and installs Sanctum. Protect routes with the auth:sanctum middleware.

API tokens

Add the Laravel\Sanctum\HasApiTokens trait to your User model, then issue tokens with createToken(). Sanctum stores tokens hashed with SHA-256 in a single database table, so the plain-text value is available only once, at creation time:

PHP
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::post('/tokens', function (Request $request) {
    $request->validate(['token_name' => ['required', 'string', 'max:100']]);

    $token = $request->user()->createToken(
        $request-$request->string('token_name')gt;input('token_name'),
        ['orders:read'],
        now()->addDays(90),
    );

    return ['token' => $token->plainTextToken];
})->middleware('auth:sanctum');

The second argument lists abilities, which play the same role as OAuth scopes. Check them with $user->tokenCan('orders:read'), or with the abilities and ability middleware after registering their aliases in bootstrap/app.php. The third argument sets an expiry for that token.

By default, Sanctum tokens never expire; they remain valid until revoked. You can set a global expiration in minutes in the Sanctum configuration file, or per token as shown above. If you use expiry, schedule the prune command so old rows do not pile up:

PHP
use Illuminate\Support\Facades\Schedule;

Schedule::command('sanctum:prune-expired --hours=24')->daily();

Revoking is a database delete: $user->tokens()->delete() removes all of a user's tokens, and $request->user()->currentAccessToken()->delete() removes the one used for the current request.

SPA authentication

Sanctum's second feature authenticates your own single-page application without tokens at all. It uses Laravel's cookie-based session, which brings CSRF protection and keeps credentials out of JavaScript-readable storage. The requirements, per the documentation:

  • The SPA and the API must share the same top-level domain (they may be on different subdomains).
  • List the SPA's domains in Sanctum's stateful configuration.
  • Call $middleware->statefulApi() in bootstrap/app.php.
  • Configure CORS to allow credentials (supports_credentials set to true after publishing config/cors.php).

The Sanctum documentation is explicit that you should not use API tokens to authenticate your own first-party SPA; use the cookie-based SPA authentication instead.

Laravel Passport in Laravel 13

Installation

Passport also installs through install:api, with a flag:

Shell
php artisan install:api --passport

The command publishes and runs the migrations for OAuth2 clients and tokens and generates the encryption keys used to sign access tokens. You then add the Laravel\Passport\HasApiTokens trait and the Laravel\Passport\Contracts\OAuthenticatable interface to the User model and define an api guard with the passport driver in config/auth.php.

When deploying for the first time, run php artisan passport:keys. The generated keys are normally kept out of source control, so plan how they reach each server.

Grants

Passport's value lies in its OAuth2 grants. The Laravel 13 documentation covers:

GrantTypical useStatus in the docs
Authorization codeThird-party web apps acting for a userStandard
Authorization code with PKCESPAs and mobile apps that cannot keep a client secretDocumented for SPAs and mobile apps
Device authorizationTVs, consoles and other devices with limited inputSupported
Client credentialsMachine-to-machine calls with no userSupported
Personal access tokensUsers creating their own tokensSupported
PasswordFirst-party clients sending username and password"We no longer recommend"
ImplicitLegacy browser clients"We no longer recommend"

If an older tutorial tells you to use Passport's password grant for your mobile app, note that the current documentation advises against it. For a first-party mobile app, Sanctum tokens or Passport's authorization code with PKCE are the documented paths.

Tokens and housekeeping

Passport issues access tokens that, by default, expire after one year; you can change lifetimes with Passport::tokensExpireIn(), refreshTokensExpireIn() and personalAccessTokensExpireIn() in AppServiceProvider. Revoked and expired tokens, authorization codes and device codes can be removed with php artisan passport:purge, which is a good candidate for the scheduler.

PHP source code displayed in a text editor with syntax highlighting
Sanctum tokens are created in a few lines of PHP; Passport adds clients, grants and signing keys.

Side-by-side comparison

QuestionSanctumPassport
Implements OAuth2?NoYes, full server
Install commandphp artisan install:apiphp artisan install:api --passport
Token storageSHA-256 hashed rows in one tableOAuth2 tables for clients, tokens, codes
Token permissionsAbilitiesScopes
Default token expiryNever (configurable)One year (configurable)
Refresh tokensNoYes
First-party SPACookie session auth, built inAuthorization code with PKCE
Third-party apps with consent screenNot supportedSupported
Signing keys to manageNoneYes (passport:keys)
Cleanup commandsanctum:prune-expiredpassport:purge

Which one should you choose?

Choose Sanctum when

  • You are building an SPA (for example with Next.js, Nuxt, React or Vue) on the same top-level domain as the API.
  • You ship your own mobile app and want each device to hold its own revocable token.
  • Your users need "personal access tokens" for scripts, similar to the tokens developer platforms let you generate in account settings.
  • You want the smallest amount of moving parts to secure and maintain.

Choose Passport when

  • Other companies or developers will register applications that act on behalf of your users, and you need consent screens, client IDs and scopes.
  • You must interoperate with tools that expect a standard OAuth2 authorization server.
  • You need machine-to-machine access via the client credentials grant, or the device authorization grant.
  • You need refresh tokens and short-lived access tokens as part of an OAuth2 design.

When neither is the answer

If you want users to sign in with Google, GitHub or another provider, that is the job of Laravel Socialite, not Sanctum or Passport. And if your organisation already runs an identity provider for single sign-on, you may only need to validate its tokens rather than run your own OAuth2 server. Avoid adding Passport "just in case": every OAuth2 grant you enable is extra surface to secure.

Migration notes

Moving from Sanctum to Passport later is possible, but tokens are not shared between the two, so existing clients must obtain new tokens. Plan a transition period in which both guards are accepted on the relevant routes, communicate the change to API consumers, and remove the old guard once traffic has moved. Moving from Passport to Sanctum is usually done when a team realises no third-party clients ever materialised; the same dual-guard approach applies.

Security checklist for either package

  • Set expiry on tokens and prune expired ones on a schedule.
  • Grant the narrowest abilities or scopes a client needs, and check them in your policies, not only in middleware.
  • Give users a screen to see and revoke their tokens.
  • Rate-limit login and token-issuing routes.
  • Serve the API only over HTTPS and never log bearer tokens.
  • For Passport, keep signing keys out of the repository and restrict file permissions on the server.

A worked decision for a small SaaS team

Consider a typical small product: a Laravel back end, a React front end served from app.example.com, an API at api.example.com, and a request from a few customers to automate exports with scripts. Both front end and API share the top-level domain example.com, so Sanctum's cookie-based SPA authentication fits the web app, and Sanctum personal access tokens with an exports:read ability fit the customer scripts. No third party needs delegated access, so there is nothing for Passport to do.

Now suppose that a year later a partner wants to build an integration that its own customers connect to your product with a "Connect" button. That is delegated access with user consent, the classic OAuth2 case, and it is the point where adding Passport (or an external authorization server) becomes justified. Making the decision this way, from actual clients rather than anticipated ones, keeps the system as simple as it can be for as long as possible.

Summary

Sanctum and Passport solve different problems. Sanctum is the default for authenticating your own SPA, mobile app and user-generated API tokens; it is simpler to run and has fewer parts to get wrong. Passport is the right tool when you need a real OAuth2 server for third-party applications, machine clients or devices. Start by listing who will call your API, and the choice usually becomes obvious.

Frequently asked questions

  • Is Sanctum less secure than Passport?

    Not inherently. They cover different needs. Sanctum hashes tokens with SHA-256 and uses Laravel's session cookies for first-party SPAs. Passport implements OAuth2 for third-party clients. Security depends mainly on configuration: expiry, narrow abilities or scopes, HTTPS and rate limits.

  • Do Sanctum tokens expire?

    By default, no. Set an expiration value in the Sanctum configuration or pass an expiry date to createToken(), and schedule sanctum:prune-expired.

  • Should I use Passport's password grant for my mobile app?

    The Laravel 13 Passport documentation says it no longer recommends the password grant. Use Sanctum tokens or Passport's authorization code grant with PKCE instead.

  • What should I use for 'Sign in with Google'?

    Laravel Socialite, which handles authentication with OAuth providers such as Google, GitHub and others. Sanctum or Passport then secure your own API.

Advertise on CloudSoftZone

Your next customer could start right here.

Introduce your tool, product or business to readers exploring technology.

Advertise with us

Explore placements and request a private quote

Sources

  1. Laravel Sanctum (Laravel 13.x) — Laravel
  2. Laravel Passport (Laravel 13.x) — Laravel
  3. Routing: API Routes (Laravel 13.x) — Laravel
  4. Laravel Socialite (Laravel 13.x) — Laravel

Written with substantial AI assistance. Facts checked against cited sources. Editorial policy.

Comments

No comments yet. Be the first to join the conversation.

Leave a comment

Every comment is read by a moderator before it appears. Your email address is never published; it is used only to contact you about this comment.

Never published. Used only to contact you about this comment.

Loading the security check…

Comments are moderated before publication.