Restful API in Laravel with sanctum authentication

What are REST APIs?

A REST API (also known as RESTful API) is an application programming interface (API or web API) that conforms to the constraints of REST architectural style and allows for interaction with RESTful web services. REST stands for representational state transfer.

REST is a set of architectural constraints, not a protocol or a standard. API developers can implement REST in a variety of ways.

For web developers, we need to authenticate our users via API requests. In Laravel itself, besides its full-stack development, we have many options on how to authenticate the requests. For example, we have the Laravel Passport package to do the authentication and OAuth processes. But, if you don’t want to use the OAuth feature that Passport offers, then the Laravel Sanctum may be a choice for you.

What is Laravel Sanctum?

Laravel Sanctum provides a featherweight authentication system for SPAs (single-page applications), mobile applications, and simple, token-based APIs. Sanctum allows each user of your application to generate multiple API tokens for their account. These tokens may be granted abilities/scopes that specify which actions the tokens are allowed to perform.

Sanctum provides two options. The first is API Token Authentication, and the second is SPA Authentication.

HTTP Verbs Represent Actions

  • GET: retrieve resources
  • POST: create resources
  • PUT: update resources
  • DELETE: delete resources

Setting Up a Laravel Web Service Project

Let’s begin to create our fresh Laravel application for API Authentication using Laravel Sanctum.

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

This will create a new folder named LaravelSanctum containing our Laravel application. Now would be a good time to start the Laravel application to make sure everything is working as expected:

cd LaravelSanctum
php artisan serve

Installation and Setup of Laravel Sanctum

First of all, let’s add Laravel Sanctum to it. We need to install Laravel Sanctum into our application using Composer:

composer require laravel/sanctum

The next thing we need to do is publish Laravel sanctum assets for that let’s run the following command:

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

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

Database Configuration

Let’s configure a database for our application. If you don’t have a database then create a new one. After creating the database open the .env file from the root directory of your project. if the .env file is missing from the project then copy content from the .env.example and create the file. .env file defines many common environment variables

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=**********
DB_USERNAME=*********
DB_PASSWORD=*********

Replace * with your actual configuration in the above code.

After database configuration, run database migrations :

php artisan migrate

One very last thing we need to update the User model before starting API development.

Open the app/Models/User.php file and add the following modifications:

<?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;

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


    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    protected $hidden = [
        'password',
        'remember_token',
    ];

    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

Building Authentication API

First, let’s start with the basic endpoint scaffolding. Open routes/api.php and modify it.

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\AuthController;

Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::post('/logout', [AuthController::class, 'logout']);
Route::get('/user_name', [AuthController::class, 'UserName'])->middleware('auth:sanctum');

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

php artisan make:controller AuthController

This will generate the AuthController.php file in the app/Http/Controllers folder.

Open AuthController and add the following code snippet below in it. This function will handle requests for registered users:

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',
    ]);
}

Here, first of all, we validate input data make sure all required parameters are in request, and check the length of input data.

After validating data we store data in our database. Once the user is created, we create a personal access token for that user using createtoken() method. Here, we call the plainTextTokenproperty on the instance to access the plain-text value of the token.

Finally, we return a JSON response that contains the generated token with its type.

Now, let’s add a method for logging in to the user. For that add the following code into AuthController :

public function login(Request $request)
{
    if (!Auth::attempt($request->only('email', 'password'))) {
        return response()->json([
            'message' => 'Invalid login credentials.'
        ], 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 login credentials from the request. if the login credentials match then we return a new access token else we return a message for that.

Let’s add logout functionality to our API. Add the below code into AuthController :

public function logout()
{
    auth()->user()->tokens()->delete();

    return [
        'message' => 'Tokens Revoked'
    ];
}

For the logout() function itself, we can just revoke the token. Then the token will automatically be invalid if the client requests with revoked/deleted token.

Now our login functionality is created. Let’s create another endpoint that can only be accessed by authenticated users. We have already created a route for that now open AuthController and add the below code :

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

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

Restricting Routes to Only Authenticated Users

We have already assigned middleware to our user_name route like :

Route::get('/user_name', [AuthController::class, 'UserName'])->middleware('auth:sanctum');

We can also assign middleware to route groups For example :

Route::group(['middleware' => 'auth:sanctum'], function()
{
    //All the routes that belongs to the group goes here
});

Testing the API

For Running or Testing API applications enter the below command :

php artisan serve

It will produce output like the below :

Starting Laravel development server: http://127.0.0.1:8000
PHP 7.4.6 Development Server (http://127.0.0.1:8000) started

Now we can test our API endpoints using any API testing tool like Postman or any other.