Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Laravel Sanctum vs Passport: Which API Auth to Pick

By Kokil Thapa | Last reviewed: August 2026

Choosing between Laravel Sanctum vs Passport: Which API Auth to Pick is often the first architectural decision you make when building a new backend. The wrong choice leads to unnecessary complexity or security gaps later. If you are starting a fresh project today, understanding the specific trade-offs prevents costly refactors down the line. This guide breaks down exactly when to use each package based on real-world implementation patterns.

Making this decision correctly early saves significant time. I recently outlined broader backend strategies in my article on Laravel API best practices, where authentication choice is foundational. Getting this wrong means either wrestling with OAuth2 flows for a simple mobile app or hitting a feature wall when your SaaS needs third-party integrations. Let’s look at how these packages actually function in production.

How does Laravel Sanctum handle API authentication?

Sanctum provides a straightforward authentication system for SPAs, mobile applications, and simple token-based APIs. It solves two distinct problems with minimal configuration overhead. In my experience shipping legal-tech portals and eCommerce platforms, Sanctum covers about 90% of use cases without the weight of a full OAuth2 server.

SPA Authentication via Session Cookies

For single-page applications living on the same top-level domain as your API, Sanctum uses standard Laravel session cookies. You do not manage tokens manually. The frontend makes a request to /sanctum/csrf-cookie to initialize CSRF protection, then authenticates via /login. Subsequent requests carry the session cookie automatically. This is identical to traditional server-side auth but works seamlessly with Vue, React, or Alpine.js frontends.

// Example: Axios setup for SPA authentication axios.defaults.withCredentials = true; axios.defaults.withXSRFToken = true; // Initialize CSRF + Login flow await axios.get('/sanctum/csrf-cookie'); await axios.post('/login', { email, password }); // Protected route works automatically const user = await axios.get('/api/user');

API Token Authentication for Mobile & Third Parties

When cookies won’t work (mobile apps, external services), Sanctum issues plain bearer tokens stored in a personal_access_tokens table. These tokens have no expiration by default—you control lifecycle through ability flags or manual revocation. Unlike JWTs, they are opaque strings validated against the database on every request. This eliminates token refresh complexity and makes revocation instant.

Sanctum Dual Authentication ModesSPA Mode (Same Domain)Session Cookie + CSRF TokenNo token management neededAutomatic browser handlingToken Mode (Mobile/API)Bearer Token (Opaque String)Stored in personal_access_tokensManual issuance & revocationShared Validation LayerAuth Middleware Checks IdentityUser context available identically
Sanctum supports both session-based SPA auth and token-based API auth through a unified middleware layer

On a recent Nepal Gift Card platform build, we used Sanctum tokens for the mobile app while the admin panel used session auth. The unified middleware meant controllers didn’t care which method authenticated the user. This simplicity is why Sanctum is now the default recommendation for most Laravel API work.

When should you choose Laravel Passport over Sanctum?

Passport implements a complete OAuth2 authorization server. This is powerful but comes with operational cost. You should only choose Passport when your requirements explicitly demand OAuth2 protocol features. On legal-tech platforms like Court Marriage In Nepal, we’ve never needed Passport because clients authenticate directly—there’s no ecosystem of third-party apps requesting delegated access.

OAuth2 Authorization Code Grant

If users need to authorize third-party applications to act on their behalf (think "Login with YourApp" or granting a reporting tool access to their data), Passport handles the authorization code flow natively. Sanctum cannot do this. This pattern requires consent screens, redirect URIs, and code exchange—the full OAuth2 dance.

Client Credentials for Machine-to-Machine

When external systems need to access your API without a user context (inventory sync, webhook processors, partner integrations), Passport’s client credentials grant provides scoped access tied to a client rather than a user. Sanctum tokens always belong to a user model. If your architecture requires non-user actors with granular permissions, Passport fits.

Short-Lived Access Tokens with Refresh

Passport issues JWT access tokens with configurable expiration plus refresh tokens for renewal. This adds complexity (token rotation, refresh logic on clients) but enables stateless validation and automatic expiry. Sanctum tokens are long-lived by design. For high-security financial or healthcare APIs where mandatory token rotation is a compliance requirement, Passport’s built-in lifecycle management may be necessary.

For deeper context on securing authentication systems beyond package selection, see the ultimate guide to building secure authentication systems. Security posture matters more than which package you pick.

What are the key differences between Laravel Sanctum and Passport?

Understanding the concrete trade-offs helps avoid misalignment. This comparison reflects actual production behavior in 2026, not theoretical feature lists.

CriteriaLaravel SanctumLaravel Passport
Primary Use CaseSPAs, mobile apps, simple APIsOAuth2 server, third-party apps, M2M
Token TypeOpaque string (DB lookup)JWT (stateless validation)
SPA SupportNative session cookiesPassword grant (deprecated) or auth code
Third-Party AuthNot supportedFull authorization code flow
Machine-to-MachineUser-bound tokens onlyClient credentials grant
Token ExpiryNone by default (manual revoke)Configurable + refresh tokens
Setup ComplexityMinimal (migration + middleware)Significant (keys, clients, scopes)
Database LoadQuery per requestStateless (no DB for validation)
Revocation SpeedInstant (delete row)Delayed (blacklist or wait for expiry)
Laravel DefaultYes (since Laravel 8+)No (opt-in package)

The database load difference matters at scale. Sanctum validates every token against MySQL or PostgreSQL. At thousands of requests per second, this becomes a bottleneck requiring Redis caching or read replicas. Passport’s JWT validation happens in-memory using public keys—no database hit. However, for most Nepal-based projects serving regional traffic, Sanctum’s DB lookup is perfectly adequate and far simpler to debug.

Sanctum vs Passport Decision PathStart: New Laravel API ProjectNeed third-party app authorization?Require client credentials (M2M)?Mandatory short-lived JWT + refresh?Use SanctumSimple, secure, maintainableUse PassportFull OAuth2 server capabilitiesNoYesNoYesYesNo
Follow this decision path to determine whether Sanctum or Passport fits your authentication requirements

How do you implement Laravel Sanctum in a production application?

Implementation is deliberately minimal. On Laravel 12.x with PHP 8.2+, Sanctum ships pre-configured. Here’s the actual workflow I use on client projects, stripped of documentation fluff.

Installation and Migration

Sanctum is included by default in new Laravel installations. If upgrading or working with an older skeleton:

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

This creates the personal_access_tokens table. No encryption keys, no OAuth clients, no configuration files to edit unless you want to customize token abilities or expiration.

Issuing Tokens for Mobile Clients

Create tokens via the HasApiTokens trait on your User model. Always specify abilities for least-privilege access:

// In authentication controller $token = $user->createToken( name: 'mobile-app', abilities: ['orders:read', 'profile:update'], expiresAt: now()->addYear() // Optional explicit expiry ); return response()->json([ 'token' => $token->plainTextToken, 'abilities' => $token->accessToken->abilities, ]);

The plainTextToken is shown once. Store it securely on the client. All subsequent requests validate against the hashed value in your database.

Protecting Routes and Checking Abilities

Apply the auth:sanctum middleware globally or per-route. Check abilities inline when needed:

// routes/api.php Route::middleware('auth:sanctum')->group(function () { Route::get('/user', fn (Request $request) => $request->user()); Route::get('/orders', function (Request $request) { if (! $request->user()->tokenCan('orders:read')) { abort(403, 'Insufficient permissions'); } return Order::where('user_id', $request->user()->id)->get(); }); });

This pattern keeps authorization logic explicit and auditable. For complex permission matrices, combine Sanctum with Spatie Laravel Permission rather than overloading token abilities.

What are common mistakes when implementing API authentication?

After debugging numerous inherited projects, certain anti-patterns appear repeatedly. Avoiding these saves days of troubleshooting.

  • Using Passport for simple mobile apps: The OAuth2 password grant was deprecated for good reason. If your mobile app owns user credentials directly, Sanctum tokens are safer and simpler. Passport adds attack surface without benefit here.
  • Never expiring Sanctum tokens without a strategy: Default Sanctum tokens live forever. Implement either explicit expiration on creation, periodic rotation via background jobs, or user-initiated token management UI. Forever-tokens are a security liability on lost devices.
  • Storing tokens in localStorage: For SPAs, rely on Sanctum’s session cookie mode instead. If you must use tokens (hybrid apps), store them in httpOnly cookies or secure native storage—never accessible JavaScript variables.
  • Skipping ability checks: Issuing tokens with wildcard ['*'] abilities defeats the purpose. Define granular scopes matching your actual API surface. Audit token usage periodically and revoke unused ones.
  • Ignoring CORS configuration: Sanctum’s SPA auth requires precise CORS setup. The config/cors.php paths must include /sanctum/csrf-cookie and your API prefix. Misconfigured CORS is the #1 cause of "works locally, fails in production" Sanctum issues.
  • Forgetting to hash tokens in custom implementations: Never roll your own token storage. Sanctum hashes tokens before persisting. If you extend or replace this, ensure equivalent hashing. Plaintext tokens in databases are a critical vulnerability.
Token Validation: Sanctum vs PassportSanctum (DB Lookup)1. Receive Bearer Token2. Hash token + query personal_access_tokens3. Load user relationship + check abilities⚠ Database hit on EVERY request✓ Instant revocation + simple debuggingPassport (JWT Verify)1. Receive Bearer JWT2. Verify signature with public key (in-memory)3. Extract claims + validate scopes/expiry✓ Stateless + no DB per request⚠ Revocation requires blacklist/cache
Sanctum trades database queries for simplicity; Passport trades setup complexity for stateless validation

Which authentication package scales better for growing applications?

Scalability isn’t just about raw throughput—it’s about operational complexity as your team and user base grow. Both packages scale, but differently.

Sanctum’s database dependency becomes relevant around 5,000–10,000 concurrent authenticated requests per second. At that point, add Redis caching for token lookups or move to read replicas. For most Nepal-focused applications serving domestic and diaspora users, you’ll hit business scaling challenges long before Sanctum’s DB lookup becomes the bottleneck. I’ve run Sanctum on legal-tech portals handling thousands of daily document submissions without performance issues.

Passport scales horizontally without database coordination for validation, making it theoretically superior for massive multi-region deployments. However, the operational overhead of managing OAuth2 clients, key rotation, and token blacklists adds cognitive load. Every developer joining your team must understand OAuth2 flows. Debugging token issues requires tracing through multiple abstraction layers.

For teams building SaaS products targeting global markets with third-party integration ecosystems, Passport’s complexity pays off. For everything else—including most eCommerce, booking systems, internal tools, and direct-consumer APIs—Sanctum’s simplicity compounds into faster iteration and fewer production incidents. Start with Sanctum. Migrate to Passport only when you hit a concrete requirement Sanctum cannot fulfill, not because you anticipate needing OAuth2 someday.

If you’re evaluating authentication for a new project and want hands-on guidance tailored to your specific architecture, reach out to discuss your requirements. Getting this decision right upfront prevents expensive rewrites six months later.

Frequently Asked Questions

Sanctum issues simple API tokens or SPA session cookies without OAuth2. Passport implements a full OAuth2 server with authorization codes, client credentials, and refresh tokens for complex third-party integrations.

Choose Sanctum for SPAs, mobile apps, or simple microservices where users authenticate directly. It avoids OAuth2 complexity while providing secure token-based and cookie-based authentication suitable for most internal application needs.

Yes, but they are OAuth2 access tokens tied to clients. Sanctum personal tokens are simpler database records without OAuth overhead, making them easier to manage for first-party mobile app or script authentication scenarios.

Yes, significantly. Sanctum checks a single indexed database table or validates session cookies. Passport performs cryptographic signature verification and OAuth2 scope resolution on every request, adding measurable latency to high-traffic endpoints.

Yes, but it requires replacing OAuth2 flows with token or session auth. You must update frontend login logic, revoke existing OAuth tokens, and adjust middleware. Plan this as a breaking change requiring coordinated deployment and client updates.

Sanctum uses Laravel's built-in session cookie with SameSite=Lax and HttpOnly flags. The /sanctum/csrf-cookie endpoint establishes CSRF protection before login, preventing cross-site request forgery without exposing tokens to JavaScript storage.

Tokens stored insecurely in mobile apps or exposed via logs can be compromised. Unlike OAuth2 refresh tokens, Sanctum tokens lack expiration by default. Always set expiry dates, hash tokens in production, and implement revocation endpoints for lost devices.

Yes, Passport 13.x supports Laravel 12 and PHP 8.2 through 8.4. Ensure you run composer require laravel/passport:^13.0 and publish fresh migrations. Older Passport versions may fail on PHP 8.4 due to deprecated dynamic properties.

Install Sanctum, add EnsureFrontendRequestsAreStateful middleware to api group, and configure SESSION_DOMAIN and SANCTUM_STATEFUL_DOMAINS in .env. Your Vue app must call /sanctum/csrf-cookie before login and include credentials: 'include' in fetch requests.

No. Sanctum authenticates your own users only. For integrating external OAuth2 providers like Google or Facebook, use Socialite for login or Passport if you need to act as an OAuth2 authorization server for third-party clients.

Passport signs and verifies JWTs or encrypts access tokens using RSA or AES on every request. On shared hosting or low-resource servers, this adds 5-15ms per API call. Sanctum's database lookup typically completes in under 1ms with proper indexing.

Sanctum deletes the token record from personal_access_tokens table or invalidates the session. Passport revokes via oauth_access_tokens.revoked flag or refresh token deletion. Both support middleware enforcement, but Sanctum revocation is immediate without cache invalidation concerns.

Yes, if tenants authenticate as users within your system. Add tenant_id to personal_access_tokens and scope queries via global scopes. For tenant-to-tenant OAuth2 delegation or external partner API access, Passport's client credentials grant is more appropriate.

Missing SANCTUM_STATEFUL_DOMAINS, incorrect session driver, or omitting credentials: 'include' in axios/fetch. Also verify APP_URL matches your actual domain exactly. In my experience, 90% of Sanctum SPA issues trace to these three configuration values being wrong or mismatched.

Sanctum setup typically takes 4-8 hours (Rs 8,000-16,000, ~USD 60-120). Passport requires 12-24 hours (Rs 24,000-48,000, ~USD 180-360) due to OAuth2 client management, scope design, and testing. For most Nepal SMB projects, Sanctum delivers sufficient security at lower cost.

Share this article

Quick Contact Options
Choose how you want to connect me: