web-application-framework laravel

Let’s try API token authentication using Laravel Sanctum.

References

What is Laravel Sanctum?

Laravel Sanctum is an authentication system used for SPAs (single page applications), mobile applications, and simple token-based APIs.
It allows authentication using API tokens even when cookies are not available.

Environment

  • Ubuntu 22.04.3 LTS (running via WSL)
  • Docker Engine 26.0.0
  • Amazon Linux 2023(OS of Docker container)
  • PHP 8.2.15 (fpm-fcgi)
  • Composer 2.7.6
  • NGINX 1.24.0
  • Laravel 11

Prerequisites

  • A Docker container running a Laravel project (For details on how to run Laravel with NGINX, see this guide)
  • Composer is installed in the Docker container (For how to install Composer, see this guide)

Table of Contents

  1. Install Laravel Sanctum
  2. Enable API Token Generation
  3. Define Routes
  4. Test API Token Authentication

1. Install Laravel Sanctum

First, install Laravel Sanctum.

Run the following command:

php artisan install:api

This will publish the personal_access_tokens table.
You may be prompted to run the database migrations.
Type yes to proceed, or no to skip.
The default is yes.

One new database migration has been published. Would you like to run all pending database migrations? (yes/no) [yes]:

If Composer is not installed, you’ll get the following error:

sh: line 1: exec: composer: not found

2. Enable API Token Generation

You need to enable the Eloquent model used for authentication to generate API tokens.

We’ll use the default User model that comes with a fresh Laravel installation.
Add the Laravel\Sanctum\HasApiTokens trait to app/Models/User.php.

User.php :

<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens; // Added

class User extends Authenticatable
{
    // Add HasApiTokens
    use HasApiTokens, HasFactory, Notifiable;

...

By adding the HasApiTokens trait, the User model can now generate API tokens using the createToken method.

3. Define Routes

Let’s define the routes to issue and authenticate using API tokens.

Open routes/api.php, which was generated by running php artisan install:api, and add the following routes:
The /user route may already exist.

api.php :

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

Route::post('/register', function (Request $request) {
    // Add user to the database
    $user = User::create([
        'name' => $request->name,
        'email' => $request->email,
        'password' => $request->password
    ]);

    // Issue API token
    $token = $user->createToken('TestToken');

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

The /user route returns user information after authentication.
The auth:sanctum middleware enables authentication using either cookies or API tokens.
If no auth cookies are found, API token authentication is used.

The /register route registers a new user and returns an API token.
The token is issued using the createToken method.

4. Test API Token Authentication

We’ll test token-based authentication using the routes defined above.
Let’s use the curl command on Ubuntu to send HTTP requests to our Laravel project running on localhost:8080.

At first, register a User and get an API Token.
Run the following command:

$ curl -X POST -H "Content-Type: application/json" -d '{"name":"Test", "email":"test@example.com", "password":"test"}' localhost:8080/api/register

Use any values for name, email, and password in the request body.

The response should include an API token like this:

{"token":"1|RsrpmTepTJsUTfaosnVsE097WHaucLhZ5Vn7aPrV103b57d7"}

The token is stored in the personal_access_tokens table in your database.
If you inspect the table, you’ll see the token stored as a SHA-256 hash:

+----+-----------------+--------------+-----------+------------------------------------------------------------------+-----------+---------------------+------------+---------------------+---------------------+
| id | tokenable_type  | tokenable_id | name      | token                                                            | abilities | last_used_at        | expires_at | created_at          | updated_at          |
+----+-----------------+--------------+-----------+------------------------------------------------------------------+-----------+---------------------+------------+---------------------+---------------------+
|  1 | App\Models\User |            1 | TestToken | 0cb255c4ed077c5b0a3709b64810bb95dc97ad078793eaaef7f0c8f01bc9ef92 | ["*"]     | 2024-05-21 09:18:26 | NULL       | 2024-05-21 09:17:53 | 2024-05-21 09:18:26 |
+----+-----------------+--------------+-----------+------------------------------------------------------------------+-----------+---------------------+------------+---------------------+---------------------+

Next, use the token you received to authenticate the user.

Run the following command:

$ curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer 1|RsrpmTepTJsUTfaosnVsE097WHaucLhZ5Vn7aPrV103b57d7" localhost:8080/api/user

This sets the Authorization header with the token using the Bearer scheme.

The response should return user information, indicating successful authentication:

{"id":1,"name":"Test","email":"test@example.com","email_verified_at":null,"created_at":"2024-05-21T09:17:53.000000Z","updated_at":"2024-05-21T09:17:53.000000Z"}