Back to Dev Notes
8 min read

Membangun REST API menggunakan Laravel 11 & Sanctum

Membangun REST API menggunakan Laravel 11 & Sanctum

Laravel has long been the go-to framework for PHP developers who need to ship production-quality APIs fast. With Laravel 11 and the built-in Sanctum package, setting up stateless token authentication is smoother than ever. In this guide we will go from a fresh project to a fully working, protected REST API.

Prerequisites

  • PHP 8.2+ and Composer installed
  • A database (MySQL 8 or PostgreSQL 15 recommended)
  • An HTTP client such as Postman or Bruno

1. Create the Project

Spin up a fresh Laravel 11 project and install Sanctum:

composer create-project laravel/laravel my-api
cd my-api
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate

2. Configure the Database

Open .env and point it at your database:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_api
DB_USERNAME=root
DB_PASSWORD=secret

3. Create the User Model & Controller

Generate an API controller for authentication:

php artisan make:controller Api/AuthController
<?php

namespace App\Http\Controllers\Api;

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

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

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

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

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

    public function login(Request $request)
    {
        $data = $request->validate([
            'email'    => ['required', 'email'],
            'password' => ['required'],
        ]);

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

        if (!$user || !Hash::check($data['password'], $user->password)) {
            throw ValidationException::withMessages([
                'email' => ['The provided credentials are incorrect.'],
            ]);
        }

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

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

    public function logout(Request $request)
    {
        $request->user()->currentAccessToken()->delete();

        return response()->json(['message' => 'Logged out successfully.']);
    }
}

4. Define the Routes

In routes/api.php, register your endpoints:

use App\Http\Controllers\Api\AuthController;

Route::prefix('auth')->group(function () {
    Route::post('register', [AuthController::class, 'register']);
    Route::post('login',    [AuthController::class, 'login']);

    Route::middleware('auth:sanctum')->group(function () {
        Route::post('logout', [AuthController::class, 'logout']);
        Route::get('me',     fn ($req) => response()->json($req->user()));
    });
});

5. Test with Postman

Start the dev server and hit your first endpoint:

php artisan serve

Send a POST request to http://localhost:8000/api/auth/register with a JSON body:

{
  "name": "Didik Prabowo",
  "email": "didik@example.com",
  "password": "password",
  "password_confirmation": "password"
}

You will receive a Bearer token that you can attach to all subsequent authenticated requests. The same token can be verified on GET /api/auth/me.

Wrapping Up

You now have a secure, token-based REST API ready for production. From here, consider adding rate limiting via throttle middleware, response resources with php artisan make:resource, and proper API versioning under a v1 prefix.

Tags
Back to Dev Notes

Are You Ready to kickstart your project with a touch of magic?

Reach out and let's make it happen ✨. I'm also available for full-time or part-time opportunities to push the boundaries of design and deliver exceptional work.

LaravelNuxt.jsVue.jsTypeScriptNext.jsPrismaTailwindBootstrapSuSupabase
PostgreSQLERPNextExpress.jsLinuxMySQLMongoDBRedisDockerGitHub