Laravel Sanctum: Membuat Authentication untuk REST API
Laravel Sanctum merupakan salah satu solusi authentication yang disediakan Laravel untuk aplikasi yang membutuhkan autentikasi berbasis session maupun API token. Sanctum dapat digunakan untuk melindungi REST API sehingga hanya pengguna yang sudah terautentikasi yang dapat mengakses endpoint tertentu.
Dalam tutorial ini, kita akan membuat authentication REST API menggunakan Laravel Sanctum dari nol. Pembahasan mencakup instalasi Sanctum, konfigurasi database, register user, login, logout, pembuatan API token, middleware authentication, protected route, hingga pengujian menggunakan HTTP client atau curl.
Tutorial ini cocok untuk pemula yang sedang membangun backend Laravel untuk aplikasi web, mobile, frontend SPA, maupun client lain yang membutuhkan REST API authentication.
Apa Itu Laravel Sanctum?
adalah package authentication Laravel yang menyediakan mekanisme authentication sederhana untuk aplikasi yang membutuhkan session authentication atau personal access token.
Untuk REST API berbasis token, Sanctum memungkinkan aplikasi membuat token untuk user yang berhasil login. Client kemudian mengirimkan token tersebut pada request berikutnya.
Alur sederhananya:
User
│
│ Register
▼
Laravel API
│
▼
Database
│
│ Login
▼
Access Token
│
▼
Client menyimpan token
│
│ Authorization: Bearer TOKEN
▼
Protected API
Dengan mekanisme tersebut, endpoint tertentu dapat dibatasi hanya untuk user yang sudah memiliki token valid.
Kapan Menggunakan Laravel Sanctum?
Sanctum cocok digunakan ketika aplikasi membutuhkan authentication yang relatif sederhana dan terintegrasi dengan ekosistem Laravel.
Beberapa contoh penggunaannya:
- REST API untuk aplikasi mobile.
- Backend untuk frontend JavaScript.
- API untuk aplikasi internal.
- Personal access token.
- Authentication untuk SPA yang menggunakan mekanisme cookie dan session.
- API dengan endpoint publik dan endpoint privat.
Untuk tutorial ini, kita akan menggunakan personal access token agar konsep authentication REST API lebih mudah dipahami.
Persiapan
Pastikan project Laravel sudah tersedia.
Jika belum, buat project baru:
composer create-project laravel/laravel laravel-sanctum
Masuk ke direktori project:
cd laravel-sanctum
Jalankan development server:
php artisan serve
Periksa versi PHP dan Laravel sesuai dengan requirement versi Laravel yang digunakan:
php -v
php artisan --version
Instal Laravel Sanctum
Pada Laravel modern, Sanctum dapat dipasang menggunakan Artisan:
php artisan install:api
Perintah tersebut menyiapkan kebutuhan API Laravel dan Sanctum pada project.
Jika menggunakan metode instalasi manual, Sanctum juga dapat dipasang melalui Composer:
composer require laravel/sanctum
Setelah package terpasang, periksa konfigurasi dan migration yang tersedia.
Konfigurasi Database
Authentication membutuhkan database untuk menyimpan data user dan token.
Buka file:
.env
Contoh konfigurasi MySQL:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_sanctum
DB_USERNAME=root
DB_PASSWORD=
Buat database dengan nama laravel_sanctum, kemudian jalankan migration:
php artisan migrate
Laravel akan membuat tabel bawaan yang diperlukan, termasuk tabel users dan tabel untuk token Sanctum.
Memahami Tabel Personal Access Tokens
Sanctum menggunakan tabel personal_access_tokens untuk menyimpan informasi token.
Secara konseptual, data token berkaitan dengan:
- User pemilik token.
- Nama token.
- Token yang telah di-hash.
- Waktu token dibuat.
- Waktu token digunakan.
- Waktu token kedaluwarsa jika expiration digunakan.
Client tidak perlu mengetahui nilai token yang tersimpan di database. Token asli hanya diberikan kepada client ketika token dibuat.
Konfigurasi Model User
Buka:
app/Models/User.php
Tambahkan trait HasApiTokens:
use Laravel\Sanctum\HasApiTokens;
Kemudian gunakan trait tersebut pada model:
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
// ...
}
Contoh model User:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
protected $fillable = [
'name',
'email',
'password',
];
protected $hidden = [
'password',
'remember_token',
];
}
Trait HasApiTokens menyediakan kemampuan yang diperlukan model User untuk membuat dan mengelola personal access token Sanctum.
Membuat Authentication Controller
Buat controller khusus authentication:
php artisan make:controller Api/AuthController
File controller akan berada di:
app/Http/Controllers/Api/AuthController.php
Controller ini akan menangani register, login, dan logout.
Membuat Endpoint Register
Tambahkan import yang diperlukan:
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
Kemudian buat method register():
public function register(Request $request)
{
$validated = $request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'max:255', 'unique:users,email'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
$user = User::create([
'name' => $validated['name'],
'email' => $validated['email'],
'password' => Hash::make($validated['password']),
]);
$token = $user->createToken('api-token')->plainTextToken;
return response()->json([
'success' => true,
'message' => 'Registrasi berhasil.',
'user' => $user,
'token' => $token,
], 201);
}
Pada contoh tersebut, password tidak disimpan dalam bentuk plain text. Hash::make() digunakan untuk menghasilkan password hash sebelum disimpan ke database.
Field password_confirmation dibutuhkan karena menggunakan validation rule confirmed.
Contoh request:
{
"name": "Budi",
"email": "[email protected]",
"password": "password123",
"password_confirmation": "password123"
}
Endpoint:
POST /api/register
Membuat Endpoint Login
Selanjutnya buat method login():
public function login(Request $request)
{
$validated = $request->validate([
'email' => ['required', 'email'],
'password' => ['required', 'string'],
]);
$user = User::where('email', $validated['email'])->first();
if (! $user || ! Hash::check($validated['password'], $user->password)) {
return response()->json([
'message' => 'Email atau password salah.',
], 401);
}
$token = $user->createToken('api-token')->plainTextToken;
return response()->json([
'success' => true,
'message' => 'Login berhasil.',
'user' => $user,
'token' => $token,
]);
}
Client mengirim request:
POST /api/login
Dengan body:
{
"email": "[email protected]",
"password": "password123"
}
Jika kredensial benar, server mengembalikan access token.
Mengapa Password Menggunakan Hash?
Password tidak boleh disimpan langsung dalam database.
Contoh yang salah:
'password' => $request->password
Gunakan hashing:
'password' => Hash::make($request->password)
Ketika login, Laravel membandingkan password yang diberikan dengan hash yang tersimpan menggunakan:
Hash::check($password, $user->password)
Dengan demikian, database tidak menyimpan password asli pengguna.
Membuat Protected Route
Setelah user mendapatkan token, kita dapat melindungi endpoint menggunakan middleware:
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', function (Request $request) {
return $request->user();
});
});
Ketika request dikirim dengan token yang valid, $request->user() akan mengembalikan user yang terautentikasi.
Membuat Endpoint User
Daripada menggunakan closure, kita juga dapat membuat endpoint sederhana:
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return response()->json([
'success' => true,
'data' => $request->user(),
]);
});
Request harus menyertakan header:
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json
Ganti YOUR_ACCESS_TOKEN dengan token yang diperoleh ketika login.
Membuat Endpoint Logout
Logout pada personal access token Sanctum dapat dilakukan dengan menghapus token yang sedang digunakan.
Tambahkan method:
public function logout(Request $request)
{
$request->user()->currentAccessToken()->delete();
return response()->json([
'success' => true,
'message' => 'Logout berhasil.',
]);
}
Kemudian buat route:
Route::middleware('auth:sanctum')->post('/logout', [
AuthController::class,
'logout',
]);
Setelah logout, token yang digunakan untuk request tersebut tidak lagi dapat digunakan.
Route API Lengkap
Buka:
routes/api.php
Kemudian susun route authentication:
<?php
use App\Http\Controllers\Api\AuthController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', function (Request $request) {
return response()->json([
'success' => true,
'data' => $request->user(),
]);
});
Route::post('/logout', [AuthController::class, 'logout']);
});
Struktur endpoint:
POST /api/register
POST /api/login
GET /api/user
POST /api/logout
Dua endpoint pertama bersifat publik, sedangkan /api/user dan /api/logout membutuhkan authentication.
Controller Authentication Lengkap
Jika digabungkan, AuthController dapat dibuat seperti berikut:
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
class AuthController extends Controller
{
public function register(Request $request)
{
$validated = $request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'max:255', 'unique:users,email'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
$user = User::create([
'name' => $validated['name'],
'email' => $validated['email'],
'password' => Hash::make($validated['password']),
]);
$token = $user->createToken('api-token')->plainTextToken;
return response()->json([
'success' => true,
'message' => 'Registrasi berhasil.',
'user' => $user,
'token' => $token,
], 201);
}
public function login(Request $request)
{
$validated = $request->validate([
'email' => ['required', 'email'],
'password' => ['required', 'string'],
]);
$user = User::where('email', $validated['email'])->first();
if (! $user || ! Hash::check($validated['password'], $user->password)) {
return response()->json([
'message' => 'Email atau password salah.',
], 401);
}
$token = $user->createToken('api-token')->plainTextToken;
return response()->json([
'success' => true,
'message' => 'Login berhasil.',
'user' => $user,
'token' => $token,
]);
}
public function logout(Request $request)
{
$request->user()->currentAccessToken()->delete();
return response()->json([
'success' => true,
'message' => 'Logout berhasil.',
]);
}
}
Menguji Register API
Gunakan curl untuk menguji endpoint register:
curl -X POST http://127.0.0.1:8000/api/register \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name":"Budi","email":"[email protected]","password":"password123","password_confirmation":"password123"}'
Jika berhasil, response akan berisi data user dan token.
Contoh response:
{
"success": true,
"message": "Registrasi berhasil.",
"user": {
"name": "Budi",
"email": "[email protected]"
},
"token": "1|xxxxxxxxxxxxxxxxxxxxxxxx"
}
Token tersebut harus dianggap sebagai credential rahasia.
Menguji Login API
Login menggunakan:
curl -X POST http://127.0.0.1:8000/api/login \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"password123"}'
Simpan token dari response untuk pengujian endpoint berikutnya.
Mengakses Protected Endpoint
Misalnya token yang diperoleh adalah YOUR_ACCESS_TOKEN.
Request:
curl http://127.0.0.1:8000/api/user \
-H "Accept: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Jika token valid, API akan mengembalikan data user.
Tanpa token:
curl http://127.0.0.1:8000/api/user \
-H "Accept: application/json"
Request tersebut seharusnya ditolak karena endpoint membutuhkan authentication.
Menguji Logout
Logout dapat dilakukan dengan:
curl -X POST http://127.0.0.1:8000/api/logout \
-H "Accept: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Setelah logout, token yang sedang digunakan telah dihapus sehingga tidak dapat digunakan lagi untuk mengakses endpoint yang dilindungi.
Menghapus Semua Token User
Dalam kondisi tertentu, administrator atau aplikasi mungkin perlu mencabut seluruh token milik user.
Contohnya:
$user->tokens()->delete();
Cara ini akan menghapus seluruh personal access token milik user tersebut.
Hal ini dapat berguna ketika akun diduga mengalami kompromi atau ketika semua sesi API perlu dicabut.
Memberikan Nama Berbeda untuk Token
Sanctum memungkinkan token diberi nama.
Contohnya:
$token = $user->createToken('mobile-app')->plainTextToken;
Nama token dapat membantu mengidentifikasi asal token ketika seorang user memiliki beberapa token.
Contoh lainnya:
$user->createToken('android-app');
$user->createToken('ios-app');
$user->createToken('web-app');
Dengan pendekatan tersebut, token dapat dikelola berdasarkan perangkat atau aplikasi client.
Menggunakan Token Ability
Sanctum juga mendukung abilities untuk membatasi tindakan yang dapat dilakukan oleh token.
Contoh pembuatan token:
$token = $user->createToken(
'admin-token',
['server:update', 'server:delete']
)->plainTextToken;
Endpoint kemudian dapat dibatasi menggunakan middleware:
Route::middleware(['auth:sanctum', 'abilities:server:update'])
->put('/server/{server}', function () {
// Update server
});
Pendekatan ini berguna ketika satu user memiliki beberapa token dengan hak akses berbeda.
Authentication vs Authorization
Authentication dan authorization merupakan dua konsep berbeda.
Authentication menjawab pertanyaan:
Siapa user ini?
Contohnya adalah proses login menggunakan email dan password.
Authorization menjawab pertanyaan:
Apa yang boleh dilakukan user ini?
Contohnya adalah user biasa hanya boleh membaca data, sedangkan administrator dapat membuat, mengubah, atau menghapus data.
Laravel Sanctum terutama membantu authentication token. Authorization tetap perlu dirancang sesuai kebutuhan aplikasi, misalnya menggunakan policies, gates, atau abilities.
Praktik Keamanan Laravel Sanctum
Token API harus diperlakukan seperti password karena siapa pun yang memiliki token yang masih valid dapat menggunakannya sesuai hak akses token tersebut.
Beberapa praktik keamanan yang sebaiknya diterapkan:
- Gunakan HTTPS pada production.
- Jangan menyimpan token di source code.
- Jangan mengirim token melalui URL.
- Jangan mencetak token ke log aplikasi.
- Gunakan password hashing.
- Validasi semua input.
- Batasi akses endpoint menggunakan middleware.
- Gunakan authorization untuk resource privat.
- Cabut token yang tidak lagi digunakan.
- Pertimbangkan expiration sesuai kebutuhan aplikasi.
- Gunakan rate limiting untuk endpoint login dan endpoint sensitif.
Jangan mengirim credential melalui koneksi HTTP biasa pada production karena request dapat disadap.
Rate Limiting untuk Login
Endpoint login merupakan salah satu target yang perlu dilindungi dari brute force.
Laravel menyediakan rate limiting yang dapat digunakan untuk membatasi jumlah request dalam periode tertentu.
Contoh sederhana menggunakan middleware throttle:
Route::middleware('throttle:login')->post('/login', [
AuthController::class,
'login',
]);
Nama dan konfigurasi limiter dapat disesuaikan dengan versi Laravel dan kebutuhan aplikasi.
Rate limiting sebaiknya diterapkan terutama pada endpoint yang memproses credential atau melakukan operasi yang mahal.
Jangan Mengembalikan Password ke API
Meskipun password sudah di-hash, field tersebut tidak perlu dikirim ke client.
Model User dapat menyembunyikannya:
protected $hidden = [
'password',
'remember_token',
];
Untuk API production yang kompleks, penggunaan API Resource juga disarankan agar field yang dikembalikan dapat dikontrol secara eksplisit.
Struktur Project
Setelah mengikuti tutorial, struktur bagian utama project dapat terlihat seperti:
laravel-sanctum/
├── app/
│ ├── Http/
│ │ └── Controllers/
│ │ └── Api/
│ │ └── AuthController.php
│ └── Models/
│ └── User.php
├── database/
│ └── migrations/
├── routes/
│ └── api.php
└── .env
Struktur tersebut masih sederhana dan dapat dikembangkan sesuai kebutuhan aplikasi.
Alur Authentication Laravel Sanctum
Secara keseluruhan, alurnya adalah:
1. User melakukan register
2. Laravel membuat user
3. Password di-hash
4. Laravel membuat personal access token
5. Token diberikan kepada client
6. Client menyimpan token secara aman
7. Client mengirim Bearer token
8. Middleware auth:sanctum memvalidasi token
9. Laravel mengidentifikasi user
10. Protected endpoint dijalankan
Ketika user logout, token yang sedang digunakan dapat dicabut dari database.
Kesimpulan
Laravel Sanctum menyediakan cara yang praktis untuk menambahkan authentication berbasis token pada REST API Laravel. Dengan Sanctum, aplikasi dapat membuat personal access token, melindungi endpoint menggunakan auth:sanctum, mencabut token saat logout, serta menerapkan abilities untuk kebutuhan authorization yang lebih spesifik.
Untuk implementasi production, authentication sebaiknya tidak berdiri sendiri. Gunakan HTTPS, validasi input, rate limiting, authorization, password hashing, pengelolaan token yang aman, dan monitoring sesuai kebutuhan aplikasi.
Dengan memahami konsep token, middleware, authentication, dan authorization, Anda sudah memiliki fondasi yang cukup untuk membangun REST API Laravel yang dapat digunakan oleh frontend web maupun aplikasi mobile.
FAQ
Apa itu Laravel Sanctum?
Laravel Sanctum adalah solusi authentication dari ekosistem Laravel yang mendukung session authentication dan personal access token untuk API.
Apakah Laravel Sanctum cocok untuk REST API?
Ya. Sanctum dapat digunakan untuk REST API yang membutuhkan personal access token dan endpoint yang dilindungi authentication.
Apakah token Sanctum sama dengan password?
Tidak, tetapi token harus diperlakukan sebagai credential rahasia. Jika token valid jatuh ke tangan orang lain, token tersebut dapat digunakan untuk mengakses API sesuai hak aksesnya.
Bagaimana cara logout menggunakan Laravel Sanctum?
Untuk personal access token, logout dapat dilakukan dengan menghapus token yang sedang digunakan melalui currentAccessToken()->delete().
Apakah Laravel Sanctum bisa digunakan untuk aplikasi mobile?
Bisa. Personal access token Sanctum dapat digunakan oleh aplikasi mobile sebagai credential untuk mengakses endpoint API yang dilindungi.
Apakah Sanctum menyediakan authorization?
Sanctum menyediakan fitur abilities untuk membatasi kemampuan token, tetapi authorization pada level resource atau user tetap perlu dirancang menggunakan mekanisme Laravel seperti policies atau gates.
Apakah token Sanctum perlu kedaluwarsa?
Tergantung kebutuhan keamanan aplikasi. Untuk aplikasi production, expiration dan mekanisme pencabutan token perlu dipertimbangkan agar token lama tidak memiliki akses tanpa batas waktu.

