Build a Restful API in PHP with Laravel Sanctum

February 26, 2021
Written by
Chimezie Enyinnaya
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by

Laravel Sanctum, formerly known as Airlock, is a Laravel package created for the authentication of Single Page Applications (SPAs), mobile applications, and basic token-based APIs. It can be used to issue API Tokens to your users and authenticate Single Page Applications using Laravel’s session. Laravel Sanctum poses as a simple alternative to the existing Laravel Passport package. Here are some reasons you might want to choose Sanctum over Passport:

  1. Passport is implemented with OAuth2 authentication. If you are not using that, then Sanctum is your go-to for issuing API tokens.
  2. Sanctum is a featherweight, meaning it is light and simple to implement.
  3. Sanctum works with SPAs (Single Page Applications like Vue, Angular, and React) and supports mobile application authentication.

Prerequisites

In order to complete this tutorial, you will need the following:

  1. Knowledge of Laravel.
  2. Basic knowledge of using an HTTP client such as Insomnia.

As you can see Laravel Sanctum does much more, but in this tutorial, we will be using Laravel Sanctum to create APIs.

Getting started

Let’s start by creating a new Laravel application. We’ll do that by running the command below in our terminal:

composer create-project --prefer-dist laravel/laravel laravel_sanctum

With laravel_sanctum being the name of the application. This will create a new folder named laravel_sanctum containing our Laravel application.

Now would be a good time to start the Laravel application to make sure everything is working as expected:

cd laravel_sanctum
php artisan serve

Installation and Setup

With the Laravel application in place, let’s add Laravel Sanctum to it. First, we need to install Laravel Sanctum into our application using Composer:

composer require laravel/sanctum

This will create a sanctum.php file in the config directory, as well as the necessary migration files in the migrations directory.

Before we run the migrations the database will need to be set up. Create a database.sqlite file:

touch database/database.sqlite

NOTE: Windows users won’t be able to use the touch command so use your IDE to generate the file if needed.

Then update the .env file as below:

DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite

Building the API

For the sake of simplicity, the API will have only three endpoints. The first endpoint will allow users to register an account, while the second endpoint will allow users to login/authenticate themselves. The third endpoint will fetch the currently authenticated user.

Let’s start with registering for an account. In your terminal create the controller responsible for authentication by running the following Artisan command:

php artisan make:controller AuthController

A new file will be generated in the app/Http/Controllers folder called AuthController.php.

Now open the routes/api.php file to create the route responsible for registering a user:

// routes/api.php
use App\Http\Controllers\AuthController;

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

Open up the AuthController and add the code snippet below in it to create the method to register a user:

// app/Http/Controllers/AuthController.php
use Illuminate\Support\Facades\Hash;

public function register(Request $request)
{
$validatedData = $request->validate([
'name' => 'required|string|max:255',
                   'email' => 'required|string|email|max:255|unique:users',
                   'password' => 'required|string|min:8',
]);

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

$token = $user->createToken('auth_token')->plainTextToken;

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

First, we validate the incoming request to make sure all required variables are present. Then we persist the supplied details into the database. Once a user has been created, we create a new personal access token for them using the createToken() method and give the token a name of auth_token. Because createToken() will return an instance of Laravel\Sanctum\NewAccessToken, we call the plainTextTokenproperty on the instance to access the plain-text value of the token. Finally, we return a JSON response containing the generated token as well as the type of the token.

Next, let’s add the implementation for returning users to login. Add the code below inside routes/api.php:

// routes/api.php

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

Then add the login() method inside of the AuthController:

// app/Http/Controllers/AuthController.php

use App\Models\User;
use Illuminate\Support\Facades\Auth;

public function login(Request $request)
{
if (!Auth::attempt($request->only('email', 'password'))) {
return response()->json([
'message' => 'Invalid login details'
           ], 401);
       }

$user = User::where('email', $request['email'])->firstOrFail();

$token = $user->createToken('auth_token')->plainTextToken;

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

In the above code, we are checking if the email and password supplied actually match any from the users table and then creating a new personal access token for the user.

Let’s add the last functionality, which is for fetching the currently authenticated user. Add the code below inside routes/api.php:

// routes/api.php

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

Next, add the following code to the AuthController:

// app/Http/Controllers/AuthController.php

public function me(Request $request)
{
return $request->user();
}

This code is pretty straightforward. We simply return the currently authenticated user.

Restricting the Endpoint to Only Authenticated Users

As you might have guessed, the /me endpoint needs to be accessible to only authenticated users. Luckily for us, we can do that using the sanctum authenticated guard.

So let’s update the route as below:

// routes/api.php

Route::post('/me', [AuthController::class, 'me'])->middleware('auth:sanctum');

This will make sure requests to this endpoint contain a valid API token in the header.

Before we test the API, let’s uncomment the line below inside app/Providers/RouteServiceProvider.php:

// app/Providers/RouteServiceProvider.php

protected $namespace = 'App\\Http\\Controllers';

Testing the API

It’s time to test what we have been building. I’ll be showing instructions using Insomnia, but you’re free to use any HTTP client you are comfortable with.

First, let’s make sure the application is running:

php artisan serve

The application should be running on http://127.0.0.1:8000 and we can access the API on http://127.0.0.1:8000/api.

Now, we can make the requests in Insomnia as in the following examples.

Create a new User

To create a new user, make a POST request to http://127.0.0.1:8001/api/register with a name, email, and password. Make sure that your password is at least 8 characters long.

Register

Login the user

To login, make a POST request to http://127.0.0.1:8001/api/login with your email and password (in plain text format.

Login

If we try to access the /me endpoint with a valid token, we should get something similar to the image below:

Fetch authentication without token

Otherwise, we should get user details as in the image below:

Fetch authentication

Conclusion

In this tutorial, we looked at what Laravel Sanctum is and what it does. Also, we looked at how it is different from Laravel Passport and when to use it. Finally, we covered how to use Laravel Sanctum to give access to users by creating tokens that can be used to authenticate and give access to users to consume Laravel APIs.

To learn more about Laravel Sanctum, check out the docs.

You can find the complete source code for this tutorial on GitHub.

Chimezie Enyinnaya is a software developer and instructor. You can learn more about him here:

Website: https://adonismastery.com

Twitter: https://twitter.com/ammezie

Email: meziemichael@gmail.com

GitHub: https://github.com/ammezie