Laravel 9 Sanctum Authentication + CRUD REST API Tutorial

Throughout this extensive guide, you will learn how to create Laravel REST API using Laravel Sanctum. Not only but also, you will be taught how to test Laravel Sanctum authentication and CRUD (create, read, update, delete) REST APIs with the help of Postman.

Laravel Sanctum is useful for building token-based APIs and tedious authentication systems for single-page applications, mobile applications. The laravel sanctum may generate multiple API tokens; every token can be assigned different roles, which decides what action the tokens are permitted to perform.

This laravel sanctum API tutorial will show you how to create APIs in laravel using the laravel sanctum package. Laravel Sanctum stores user API tokens in a single database table and authenticates incoming HTTP requests through the Authorization header, which holds the valid API token.

Sanctum provides a manageable method to authenticate single-page applications (SPAs) that smoothly communicates with a Laravel powered API. This laravel sanctum example is also great for single-page apps; after going through this step by step guide, you will be understood how valuable this detailed laravel sanctum spa example will be for you.

How to Build Laravel Auth and CRUD REST APIs using Laravel 9 Sanctum

  • Step 1: Download Laravel App
  • Step 2: Update Database Credentials
  • Step 3: Add Laravel Sanctum/li>
  • Step 4: Add Table in Database
  • Step 5: Make Laravel API Resources
  • Step 6: Build Auth Controllers
  • Step 7: Register New Routes
  • Step 8: Test Laravel Auth APIs

Download Laravel App

The first step starts with downloading of new laravel app, use the provided command.

composer create-project --prefer-dist laravel/laravel my-app

Update Database Credentials

Update the database credentials in the .env and connect app and the database.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_name
DB_USERNAME=db_username
DB_PASSWORD=db_password

Add Laravel Sanctum Library in Laravel

Adding laravel sanctum is the required step; run command to install the package in the laravel.

composer require laravel/sanctum

Sanctum library has been added to laravel, and now you need to add the sanctum provider. Consequently, publish sanctum configuration with the help of vendor publish.

Subsequently, go ahead and publish the Sanctum configuration and migration files using the vendor:publish Artisan command. The given command will publish the sanctum configuration file in app’s config directory.

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

Further, add Sanctum’s middleware to your api middleware group within your application’s app/Http/Kernel.php file:

'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

The provided command will create a table for storing the API toke and evoke the database migration.

php artisan migrate

All set, one more thing import the sanctum HasApiTokens service within the app/Models/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;

// import sanctum api
use Laravel\Sanctum\HasApiTokens;


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

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

Add Table in Database

Move to console, use the migration command to create task model and migration files; both the files allow you to run database migration.

php artisan make:model Task -m

After invoking the provided command, place the suggested values into the app/Models/Task.php file.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    use HasFactory;

    protected $fillable = [
        'name', 
        'details'
    ];    
}

Head over to database/migrations/create_tasks_table.php and update the recommended code.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTasksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('details');            
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('tasks');
    }
}

You are now ready to migrate the new table into the database.

php artisan migrate

Build API Resources

In this section, you will use the make:resource Artisan command to generate a resource class. FYI, all the resources get into the app/Http/Resources directory of your app.

php artisan make:resource Task

Head over to app/Http/Resources/Task.php and replace with the provided code.

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class Task extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'details' => $this->details,
            'created_at' => $this->created_at->format('d/m/Y'),
            'updated_at' => $this->updated_at->format('d/m/Y'),
        ];
    }
}

Build Auth Controller

This step guides on creating and organizing the needed controllers with essential functions to handle auth in laravel significantly. You have to make the API folder in the controllers’ directory; after that, create three new controllers files.

=> app/Http/Controllers/API/BaseController.php
=> app/Http/Controllers/API/TaskController.php
=> app/Http/Controllers/API/AuthController.php

Use code to create functions in app/Http/Controllers/API/BaseController.php.

<?php


namespace App\Http\Controllers\API;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller as Controller;


class BaseController extends Controller
{

    public function handleResponse($result, $msg)
    {
    	$res = [
            'success' => true,
            'data'    => $result,
            'message' => $msg,
        ];
        return response()->json($res, 200);
    }

    public function handleError($error, $errorMsg = [], $code = 404)
    {
    	$res = [
            'success' => false,
            'message' => $error,
        ];
        if(!empty($errorMsg)){
            $res['data'] = $errorMsg;
        }
        return response()->json($res, $code);
    }
}

Update app/Http/Controllers/API/TaskController.php.

<?php
   
namespace App\Http\Controllers\API;
   
use Illuminate\Http\Request;
use App\Http\Controllers\API\BaseController as BaseController;
use App\Http\Resources\Task as TaskResource;
use App\Models\Task;
use Validator;


class TaskController extends BaseController
{

    public function index()
    {
        $tasks = Task::all();
        return $this->handleResponse(TaskResource::collection($tasks), 'Tasks have been retrieved!');
    }

    
    public function store(Request $request)
    {
        $input = $request->all();
        $validator = Validator::make($input, [
            'name' => 'required',
            'details' => 'required'
        ]);
        if($validator->fails()){
            return $this->handleError($validator->errors());       
        }
        $task = Task::create($input);
        return $this->handleResponse(new TaskResource($task), 'Task created!');
    }

   
    public function show($id)
    {
        $task = Task::find($id);
        if (is_null($task)) {
            return $this->handleError('Task not found!');
        }
        return $this->handleResponse(new TaskResource($task), 'Task retrieved.');
    }
    

    public function update(Request $request, Task $task)
    {
        $input = $request->all();

        $validator = Validator::make($input, [
            'name' => 'required',
            'details' => 'required'
        ]);

        if($validator->fails()){
            return $this->handleError($validator->errors());       
        }

        $task->name = $input['name'];
        $task->details = $input['details'];
        $task->save();
        
        return $this->handleResponse(new TaskResource($task), 'Task successfully updated!');
    }
   
    public function destroy(Task $task)
    {
        $task->delete();
        return $this->handleResponse([], 'Task deleted!');
    }
}

Eventually, open and update app/Http/Controllers/API/AuthController.php file.

<?php
   
namespace App\Http\Controllers\API;
   use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\API\BaseController as BaseController;
use App\Models\User;
use Validator;

   
class AuthController extends BaseController
{

    public function login(Request $request)
    {
        if(Auth::attempt(['email' => $request->email, 'password' => $request->password])){ 
            $auth = Auth::user(); 
            $success['token'] =  $auth->createToken('LaravelSanctumAuth')->plainTextToken; 
            $success['name'] =  $auth->name;
   
            return $this->handleResponse($success, 'User logged-in!');
        } 
        else{ 
            return $this->handleError('Unauthorised.', ['error'=>'Unauthorised']);
        } 
    }

    public function register(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required',
            'email' => 'required|email',
            'password' => 'required',
            'confirm_password' => 'required|same:password',
        ]);
   
        if($validator->fails()){
            return $this->handleError($validator->errors());       
        }
   
        $input = $request->all();
        $input['password'] = bcrypt($input['password']);
        $user = User::create($input);
        $success['token'] =  $user->createToken('LaravelSanctumAuth')->plainTextToken;
        $success['name'] =  $user->name;
   
        return $this->handleResponse($success, 'User successfully registered!');
    }
   
}

Register New Routes

In general, app routes are often defined inside the web.php; however, laravel gives you a separate file for creating API routes.

Get into the routes/api.php file, define authentication as well as crud routes for task management project.

<?php

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

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::middleware('auth:sanctum')->group( function () {
    Route::resource('tasks', TaskController::class);
});

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

Test Laravel Auth APIs

To test the APIs, you should run the laravel app, after that start the postman app, probably the best app for testing the APIs,

php artisan serve

In the Postman dashboard, select the POST method, enter the provided API in the input box, click on Body section, provide name, email, password and, confirm the password and hit send.

Laravel Sanctum Register API

Likewise, enter the login API, registered email and password and click on the send button.

Laravel Sanctum Login API

After testing auth APIs, further, we can test the Laravel Sanctum CRUD APIs, but before that, move to “Authorization” tab, select “Bearer Token” and define the token which you received after logging-in in the previous step.

Similarly, you can get all the items, just set the GET method and let the postman do its job.

Laravel Sanctum CRUD API

In this section, we will show you how you can use the Update API to update the data through Postman.

Laravel Sanctum CRUD APIs

In this final step, you will see how to consume the delete REST API; go ahead enter the API in the Postman input box to see the result.

Laravel Sanctum Auth API Example

Conclusion

Laravel Sanctum is an ultimate elixir if you want to create a secure, fast and reliable auth system in laravel. It gives not just one but multiple reasons to use it for the laravel auth API project.

It is easy to install and configure, generate a multi-token, with the specific role given to every token, works best with single page application.

Finally, the Laravel Sanctum API example is ended, hope you will like it.