6 min read

Laravel Sanctum 101: A Developer’s Guide to Easy Authentication (2026 Guide)

Konstantine Milorava

Delivery Manager & Software Architect

Laravel sanctum 101

Most Laravel Sanctum tutorials hand you a createToken() snippet and call it authentication. Then you wire it into a React or Vue frontend on the same domain, and you have quietly built the wrong thing - Sanctum's own docs tell you not to use API tokens to authenticate your own first-party SPA.

We run Sanctum in production across our own SaaS backends - including a multi-tenant platform where users live on per-tenant subdomains, and an internal tool that mints Sanctum tokens against a non-User model and rotates them on a schedule. The single decision that determines whether Sanctum is effortless or a week of CORS debugging is the one most guides skip: which of Sanctum's two modes you actually need.

This guide leads with that, then gives you the current, correct setup for each.

Key Features of Laravel Sanctum

Here are some of the standout features of Laravel Sanctum that highlight why you should consider using this tool to simplify authentication.

Token-Based Authentication

Sanctum allows users to issue API tokens without the complexity of OAuth. These tokens can be scoped, restricting the actions they can perform. This is particularly useful for managing API access for different parts of your application or for external services.

SPA Authentication

For SPAs, Sanctum uses cookie-based session authentication, which allows your JavaScript front end to authenticate using the same Laravel session cookies. This approach provides a seamless and secure authentication mechanism for SPAs.

CSRF Protection

Sanctum offers robust CSRF protection for your application. When using Sanctum, your API requests are protected against CSRF attacks, ensuring the security of your application.

How do I install Sanctum in Laravel (2026)?

On Laravel 11, 12, and 13 there is a single Artisan command that installs Sanctum, publishes its config, and adds the migration:

php artisan install:api

Run your migrations, and Sanctum is ready. If you are authenticating an SPA, also complete the SPA configuration section below. 

Using Sanctum for API Token Authentication

To issue a token to a user, first, you need to update the User model:

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

Creating token:

$token = $request->user()->createToken($request->token_name);

return ['token' => $token->plainTextToken];

Revoking tokens:

// Revoke all tokens...
$user->tokens()->delete();
// Revoke the token that was used to authenticate the current request...
$request->user()->currentAccessToken()->delete();
// Revoke a specific token...
$user->tokens()->where('id', $tokenId)->delete();

Token Scopes

Tokens can have scopes that define their permissions. When creating a token, you can specify the scopes:

$token = $user->createToken('token-name', ['view-posts', 'create-posts'])
->plainTextToken;

You can then check the token’s scopes in your routes or controllers:

if ($user->tokenCan('create-posts')) {
   // ...
}

Protecting Routes with Laravel Sanctum

Sanctum provides powerful middleware to check incoming requests if it is authenticated and have the token ability:

use Laravel\Sanctum\Http\Middleware\CheckAbilities;
use Laravel\Sanctum\Http\Middleware\CheckForAnyAbility;
 
->withMiddleware(function (Middleware $middleware) {
    $middleware->alias([
        'abilities' => CheckAbilities::class,
        'ability' => CheckForAnyAbility::class,
    ]);
})

To protect routes, you should use the auth:sanctum and ability (abilities) middleware:

Route::middleware(['auth:sanctum', 'abilities: create-post'])
    ->post('/posts/create', function (Request $request) {
        //
    });

The difference between ability and abilities is quite simple:

  • ability middleware checks if the token has at least one ability
  • abilities middleware checks if the token has every listed ability

SPA Authentication

For SPAs, you need to set up session-based authentication. Typically, you will have a login route that your SPA will use to authenticate:

Route::post('/login', function (Request $request) {
    $credentials = $request->only('email', 'password');

    if (Auth::attempt($credentials)) {
        $request->session()->regenerate();
        return response()->json(['message' => 'Logged in successfully']);
    }

    return response()->json(['message' => 'Invalid credentials'], 401);
});

After logging in, your SPA can make authenticated requests using the session cookie.

Handling in frontend

When issuing a request for the sanctum route, first, you need to make a request on /sanctum/csrf-cookie to init CSRF protection:

axios.get('/sanctum/csrf-cookie').then(response => {
    axios.post('/login', {
        email: 'user@example.com',
        password: 'password'
    }).then(response => {
        // Handle successful authentication
    }).catch(error => {
        // Handle authentication failure
    });
});

The gotcha that eats a week (from our own production)

When SPA auth "just returns 401/419 and no one knows why," it is almost always one of these, and we have hit each in real Redberry projects.

  • A stateful-domain / CORS / session-domain mismatch. All four settings above have to agree. If supports_credentials is false, or the SPA origin is not instateful, or the session domain is missing its leading dot, the browser silently drops the cookie, and every request looks logged out. Change all four together, then clear cookies before retesting.
  • A 419 on POST means the X-XSRF-TOKEN header is missing or not URL-decoded - you skipped the /sanctum/csrf-cookie call or withXSRFToken is off.
  • Multi-tenant subdomains: with users on per-tenant subdomains, the session cookie domain must cover the parent (.example.com) or a tenant cannot stay logged in across its own subdomain. We ship exactly this pattern in production, and it is invisible until it breaks.
  • Laravel Octane: long-lived workers can leak container state between requests; if you run Sanctum's stateful middleware under Octane, treat per-request auth state as something to reset, not to assume fresh. [VERIFY] behavior against your Octane + Sanctum versions.
  • Tokens on a non-User model: HasApiTokens works on any Eloquent model, not just User. We mint Sanctum tokens on a repository/integration model and rotate them, leaning on Sanctum's expires_at to keep the old token valid during a short grace-period overlap so nothing breaks mid-rotation. [VERIFY] Exact Sanctum major version that introduced native expires_at.

Sanctum vs Passport vs the Laravel starter kits - which do I need?

  • Building your own first-party web app UI (login, register, password reset)? You probably do not touch Sanctum's token features directly at all - use a Laravel starter kit (React, Vue, Svelte, or Livewire), which uses Laravel Fortify for session auth out of the box. WorkOS AuthKit-powered variants add social login, passkeys, and SSO.
  • Need API tokens or a decoupled SPA? Use Sanctum - this guide.
  • Need full OAuth2 (you are an identity provider issuing tokens to third parties with authorization codes, refresh tokens, etc.)? Use Laravel Passport. Sanctum is deliberately not OAuth.For the overwhelming majority of SPA + API apps, Sanctum is the right, lightest-weight answer.

Testing Sanctum

Authenticate a fake user (with abilities) in tests without minting a real token:

use Laravel\Sanctum\Sanctum;

Sanctum::actingAs(User::factory()->create(), ['view-tasks']);
// use ['*'] to grant all abilities

 

Final Thoughts on Laravel Sanctum

Laravel Sanctum provides a simple yet powerful solution for API token management and SPA authentication. Its ease of use, combined with Laravel’s robust features, makes it an excellent choice for developers looking to implement secure authentication mechanisms. It doesn’t matter whether you’re building an API, a mobile app, or a SPA; Laravel Sanctum offers the flexibility and simplicity you need to manage authentication effectively.

Updated on by

Konstantine Milorava

First published on

Konstantine Milorava

About the author

Konstantine Milorava

Delivery Manager at Redberry

Architected CapGain Investor Platform

Architected Tavistock Platforms

Konstantine (Kosta) is a Software Architect at Redberry with over a decade of experience in PHP, Laravel, TypeScript, and Vue.js. He owns architecture and tooling decisions across the team, with hands-on backend delivery. He's architected platforms including CapGain, an investor management system for Arboris Capital, and leads Redberry's work on Tavistock's finance-automation and wealth tech products.

Latest News

Aug
13

Number One Again: Redberry Tops Clutch's Spring 2026 Top Laravel Developers

Redberry tops Clutch's Top 15 Laravel Developers list in the 2026 Clutch Global Awards - several years running.

Aug
11

Sponsoring Laravel Live Denmark 2026 in Copenhagen

Redberry is a sponsor of Laravel Live Denmark 2026, held August 20-21 at Werkstatt on Reffen in Copenhagen - the first year we have sponsored this event. Two of us will be there for it: Gaga Darsalia, our CEO, and Dati Chkhikvishvili, our Chief of Business.

Aug
5

Redberry on Laravel News at Laracon US 2026

At Laracon US 2026 our CEO Gaga Darsalia sat down with Eric Barnes of Laravel News to talk regulated fintech, AI-led legacy modernization, and why Redberry keeps coming back to Laracon.

img

Meet the authors

We are a 200+ people agency and provide product design, software development, and creative growth marketing services to companies ranging from fresh startups to established enterprises. Our work has earned us 100+ international awards, partnerships with Laravel, Vue, Meta, and Google, and the title of Georgia’s agency of the year in 2019 and 2021.

CONTACT US
img

Get in touch

Dati Chkhikvishvili

Chief Business Officer