Skip to main content
Create your own
Lesson illustration

Laravel Sanctum for API Authentication

Hello! Welcome to your next lesson in the "Authentication & Authorization" module.

In our previous lesson, we built a complete session-based authentication system using Laravel Breeze. This approach is perfect for traditional, stateful web applications where the server and browser maintain a persistent session. However, modern development often involves "stateless" clients like mobile apps or JavaScript Single Page Applications (SPAs) that communicate with a backend via an API. These clients can't rely on web sessions and cookies in the same way.

This lesson addresses that exact scenario. We'll explore how to implement a secure, token-based authentication system for a stateless API. Our tool for this will be Laravel Sanctum, a lightweight and powerful package designed for this purpose. Your goal is to build and understand the full authentication lifecycle for an API: registering a user, logging in to receive a token, using that token to access protected data, and logging out by revoking the token.

1. From Stateful Sessions to Stateless Tokens

Before diving in, let's clarify the conceptual shift from our last lesson. In a session-based system, the server creates a session for a user upon login and stores its ID in a cookie. For every subsequent request, the browser sends the cookie, and the server uses it to retrieve the user's session data. The server "remembers" the user.

In a stateless API, the server remembers nothing about previous requests. Each request must contain all the information needed to process it, including authentication credentials. This is where tokens come in.

Laravel Sanctum API Token Authentication Flow
This diagram illustrates the core concept of stateless authentication. The client sends a request with a "Bearer Token" in the header, which the server (our Laravel application) uses to identify and authenticate the user.

Let's get a formal introduction to Laravel Sanctum and its role in this process.

Laravel Sanctum - Laravel 12.x

The official Laravel documentation provides the best starting point. It explains what Sanctum is and the problems it solves.

Read the 'Introduction' section, focusing on the 'How it Works' part for 'API Tokens'. Note how it describes Sanctum as a simpler alternative to OAuth for issuing 'personal access tokens'.

As the documentation states, Sanctum is designed for first-party applications where you control both the frontend and backend. It's much simpler than a full OAuth2 implementation like Laravel Passport, making it the perfect choice for most API projects.

2. Setting Up Laravel Sanctum

Just like with Breeze, our first step is to install and configure the package. This involves pulling it in with Composer, publishing its assets, and running a migration.

Laravel API Crash Course With Sanctum | Laravel Sanctum Full Tutorial | How to Build Laravel API

This video from 'Code With Dary' provides a clear, step-by-step guide to installing Sanctum and setting up the database. We will follow these initial steps.

Watch from 02:54 to 07:06. Follow along in your own Laravel project. The key steps are summarized below.

Here's a summary of the commands and steps from the video to execute in your project terminal:

  1. Install Sanctum via Composer:

    composer require laravel/sanctum
    
  2. Publish Configuration and Migrations: This command copies Sanctum's configuration file (config/sanctum.php) and its migration file to your application.

    php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
    
  3. Run Migrations: This will create the personal_access_tokens table in your database, which Sanctum uses to store the generated tokens. Remember to have your .env file configured for your MSSQL database.

    php artisan migrate
    
  4. Update the User Model: Finally, you need to add the HasApiTokens trait to your User model. This trait provides the methods we'll use to create and manage tokens (e.g., createToken, tokens).

    Open app/Models/User.php and add the trait:

    <?php
    
    namespace App\Models;
    
    // ... other use statements
    use Laravel\Sanctum\HasApiTokens; // <-- Import the trait
    
    class User extends Authenticatable
    {
        use HasApiTokens, HasFactory, Notifiable; // <-- Use the trait
    
        // ... rest of the model
    }
    

With these steps, Sanctum is installed and ready to use.

3. Building the Authentication Endpoints

Now for the core logic. We'll create an AuthController to handle registration, login, and logout. All our routes will live in routes/api.php.

First, create the controller:

php artisan make:controller Auth/AuthController

The Registration Flow

Our register endpoint will validate the user's details, create a new user account, and immediately issue an API token.

Laravel API Crash Course With Sanctum | Laravel Sanctum Full Tutorial | How to Build Laravel API

Let's implement the registration logic. This video segment covers creating a Form Request for validation, creating the user, and most importantly, generating the first API token.

Watch from 25:11 to 30:37. Pay close attention to the use of $user->createToken(...) and the retrieval of the $token->plainTextToken. This is the token your API client will need to store.

Here is a summary of the routes and controller logic you'll build.

Define the Route in routes/api.php:

use App\Http\Controllers\Auth\AuthController;

Route::post('/register', [AuthController::class, 'register']);

Implement the register method in app/Http/Controllers/Auth/AuthController.php:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules;

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'confirmed', Rules\Password::defaults()],
        ]);

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        $token = $user->createToken('api-token-of-'.$user->name)->plainTextToken;

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

Key points:

  • The createToken() method generates a new token for the user. The string argument is just a descriptive name for the token.
  • The token is hashed before being stored in the database. You can only see the plain text version once, right after creation, using the plainTextToken property. This is what you must return to the client.

The Login Flow

The login endpoint will verify a user's credentials and, if correct, issue a new token for them to use.

Laravel API Crash Course With Sanctum | Laravel Sanctum Full Tutorial | How to Build Laravel API

Now for the login endpoint. This part is crucial as it involves validating existing credentials and handling both success and failure cases.

Watch from 34:01 to 40:10. Notice how the logic first attempts to authenticate the user and returns a 401 Unauthorized error if it fails. If successful, it generates and returns a new token.

Define the Route in routes/api.php:

// Add this route alongside your register route
Route::post('/login', [AuthController::class, 'login']);

Implement the login method in app/Http/Controllers/Auth/AuthController.php:

use Illuminate\Validation\ValidationException;

// ... inside AuthController

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)) {
        throw ValidationException::withMessages([
            'email' => ['The provided credentials are incorrect.'],
        ]);
    }

    $token = $user->createToken('api-token-of-'.$user->name)->plainTextToken;

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

4. Protecting Routes and Authenticating Requests

With login and registration working, we now have a way to get tokens. The next step is to protect certain API endpoints so that only authenticated users can access them.

This is done using the auth:sanctum middleware. Any route or group of routes protected by this middleware will require a valid Sanctum token in the request header.

Laravel API Crash Course With Sanctum | Laravel Sanctum Full Tutorial | How to Build Laravel API

Let's see how to protect our routes and how a client application would use the token. This video demonstrates using Postman to simulate an API client.

This is a key practical section. Watch from 10:55 to 14:14 to see how to set up Postman, then watch from 40:10 to 45:49. Focus on: Creating a route group with the auth:sanctum middleware. Placing a protected route inside the group. Making a request with the Authorization: Bearer <token> header in Postman to access the protected route.

Update routes/api.php to protect routes:

// Public routes
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);

// Protected routes
Route::middleware('auth:sanctum')->group(function () {
    // This route returns the currently authenticated user
    Route::get('/user', function (Request $request) {
        return $request->user();
    });

    // We will add the logout route here later
});

To test this:

  1. Use an API client like Postman to hit your /api/login endpoint with correct credentials.
  2. Copy the token value from the JSON response.
  3. Create a new request to /api/user.
  4. In the "Authorization" tab, select "Bearer Token" and paste the token you copied.
  5. Send the request. You should receive the authenticated user's data with a 200 OK status. If you try without the token, you'll get a 401 Unauthorized error.

5. Implementing Logout by Revoking Tokens

A user logging out should invalidate their token so it can no longer be used. This is a server-side action.

Laravel API Crash Course With Sanctum | Laravel Sanctum Full Tutorial | How to Build Laravel API

Finally, let's implement a secure logout. This involves more than just deleting the token on the client; we need to revoke it in our database.

Watch from 01:14:18 to 01:17:32. The key line of code is $request->user()->currentAccessToken()->delete(). Understand that this deletes the specific token that was used to make the logout request.

Define the logout route within the protected group in routes/api.php:

Route::middleware('auth:sanctum')->group(function () {
    Route::get('/user', function (Request $request) {
        return $request->user();
    });

    // Add the logout route here
    Route::post('/logout', [AuthController::class, 'logout']);
});

Implement the logout method in app/Http/Controllers/Auth/AuthController.php:

// ... inside AuthController

public function logout(Request $request)
{
    // Revoke the token that was used to authenticate the current request...
    $request->user()->currentAccessToken()->delete();

    return response()->json([
        'message' => 'Successfully logged out'
    ]);
}

Now, if you make a POST request to /api/logout with a valid Bearer token, you will get a success message. If you try to use that same token again to access /api/user, it will fail with a 401 Unauthorized error because the token no longer exists in the personal_access_tokens table.

Conclusion

Congratulations! You have successfully implemented a complete token-based authentication system for a stateless API using Laravel Sanctum. You now have the tools to secure APIs for mobile applications, JavaScript frontends, or any other service that needs to communicate with your Laravel backend.

Key Takeaways:

  • Stateless APIs require authentication information (like a token) to be sent with every request.
  • Laravel Sanctum provides a lightweight and simple way to issue and manage API tokens for first-party applications.
  • The HasApiTokens trait adds token management capabilities to your User model.
  • Tokens are generated via $user->createToken() and the plain text version is only available once upon creation.
  • The auth:sanctum middleware is used to protect routes, requiring a valid Bearer token in the Authorization header.
  • Secure logout is achieved by revoking the token on the server-side using $request->user()->currentAccessToken()->delete().

Up Next:

So far, our authentication system can answer the question: "Who is this user?". Now, we need to start answering the next logical question: "What is this user allowed to do?".

In the next lesson, we will dive into Authorization by defining access rules for different users using Gates. This will allow us to create fine-grained permission logic within our application.

Can't find a good explanation? Sign up and we'll make it for you

Sign up