Introduction
Building Secure RESTful APIs with Laravel Sanctum
Complete Guide to API Authentication and Security in Laravel Applications
In today’s interconnected digital landscape, building secure and scalable RESTful APIs is crucial for modern web applications. Laravel Sanctum (formerly known as Laravel Airlock) provides a featherweight authentication system for SPAs (Single Page Applications), mobile applications, and simple token-based APIs. Unlike Laravel Passport, which provides a full OAuth2 implementation, Sanctum offers a simpler, more focused approach to API authentication that’s perfect for most projects. In this comprehensive guide, we’ll explore how to build, secure, and optimize RESTful APIs using Laravel Sanctum.
Getting Started: Installation & Configuration
Setting up Laravel Sanctum for your API development journey
Installation Process
First, install Laravel Sanctum via Composer and run the necessary migrations to set up your database tables.
Terminal Commands
# Install Laravel Sanctum via Composer
composer require laravel/sanctum
# Publish the Sanctum configuration and migration files
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
# Run database migrations
php artisan migrate
# Add Sanctum middleware to API routes in app/Http/Kernel.php
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
User Model Configuration
Update your User model to use the HasApiTokens trait provided by Sanctum.
User.php Model
<?php
namespace App\Models;
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;
// Custom token creation with abilities
public function createApiToken(string $name, array $abilities = ['*'])
{
return $this->createToken($name, $abilities)->plainTextToken;
}
// Get all active API tokens
public function getActiveTokens()
{
return $this->tokens()->where('last_used_at', '>', now()->subDays(30))->get();
}
}
Building API Authentication Endpoints
Registration & Login Controllers
Create authentication endpoints for user registration, login, and token management.
AuthController.php
<?php
namespace App\Http\Controllers\Api;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class AuthController extends Controller
{
// User Registration
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|confirmed',
]);
if ($validator->fails()) {
return response()->json([
'message' => 'Validation failed',
'errors' => $validator->errors()
], 422);
}
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password)
]);
$token = $user->createApiToken('api-token');
return response()->json([
'message' => 'User registered successfully',
'user' => $user,
'token' => $token
], 201);
}
// User Login
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required'
]);
$user = User::where('email', $request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
return response()->json([
'message' => 'Invalid credentials'
], 401);
}
$token = $user->createApiToken('login-token');
return response()->json([
'message' => 'Login successful',
'token' => $token,
'user' => $user
]);
}
// User Logout
public function logout(Request $request)
{
$request->user()->currentAccessToken()->delete();
return response()->json([
'message' => 'Logged out successfully'
]);
}
// Get Current User
public function user(Request $request)
{
return response()->json($request->user());
}
}
API Routes Configuration
Define your API routes with proper authentication middleware.
api.php (Routes)
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\AuthController;
use App\Http\Controllers\Api\PostController;
// Public routes (no authentication required)
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
// Protected routes (require authentication)
Route::middleware(['auth:sanctum'])->group(function () {
// Auth routes
Route::post('/logout', [AuthController::class, 'logout']);
Route::get('/user', [AuthController::class, 'user']);
// Token management
Route::get('/tokens', function (Request $request) {
return $request->user()->tokens;
});
// CRUD Resources (RESTful API endpoints)
Route::apiResource('posts', PostController::class);
Route::apiResource('categories', CategoryController::class);
// Custom routes with additional middleware
Route::middleware(['can:admin'])->group(function () {
Route::get('/admin/stats', AdminController::class);
Route::apiResource('users', UserController::class)->except(['store']);
});
});
// Public API endpoints (read-only)
Route::get('/public/posts', [PostController::class, 'index']);
Route::get('/public/posts/{id}', [PostController::class, 'show']);
Advanced Sanctum Features
Token Abilities & Scopes
Sanctum allows you to assign abilities (scopes) to tokens for fine-grained access control.
TokenAbilitiesController.php
<?php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Models\User;
class TokenAbilitiesController extends Controller
{
// Create token with specific abilities
public function createTokenWithAbilities(Request $request)
{
$request->validate([
'name' => 'required|string',
'abilities' => 'required|array'
]);
$user = $request->user();
$token = $user->createToken($request->name, $request->abilities)->plainTextToken;
return response()->json([
'message' => 'Token created with abilities',
'token' => $token,
'abilities' => $request->abilities
]);
}
// Route protected by token ability middleware
public function adminOnly(Request $request)
{
return response()->json([
'message' => 'Admin access granted',
'user' => $request->user()
]);
}
}
Middleware for Token Abilities
Create custom middleware to protect routes based on token abilities.
Testing & Security Best Practices
API Testing with Sanctum
Learn how to properly test your Sanctum-protected APIs.
AuthTest.php
<?php
namespace Tests\Feature\Api;
use Tests\TestCase;
use App\Models\User;
use Laravel\Sanctum\Sanctum;
class AuthTest extends TestCase
{
// Test user registration
public function test_user_can_register()
{
$response = $this->postJson('/api/register', [
'name' => 'Test User',
'email' => 'test@example.com',
'password' => 'password123',
'password_confirmation' => 'password123'
]);
$response->assertStatus(201)
->assertJsonStructure([
'message',
'user' => ['id', 'name', 'email'],
'token'
]);
}
// Test protected route access
public function test_protected_route_requires_authentication()
{
// Attempt to access protected route without token
$response = $this->getJson('/api/user');
$response->assertStatus(401);
}
// Test authenticated route access
public function test_authenticated_user_can_access_protected_route()
{
// Create and authenticate a user
$user = User::factory()->create();
Sanctum::actingAs($user);
$response = $this->getJson('/api/user');
$response->assertStatus(200)
->assertJson([
'id' => $user->id,
'name' => $user->name,
'email' => $user->email
]);
}
// Test token abilities
public function test_token_with_abilities()
{
$user = User::factory()->create();
$token = $user->createToken('test-token', ['read', 'write']);
$response = $this->withToken($token->plainTextToken)
->getJson('/api/user');
$response->assertStatus(200);
}
}
Conclusion
Laravel Sanctum provides an elegant solution for API authentication in modern Laravel applications.
Whether you’re building a simple token-based API, a SPA with session authentication, or a mobile app backend, Sanctum offers the flexibility and security you need. Its lightweight nature compared to Passport makes it ideal for most projects while maintaining robust security features.
Key Takeaways:
- Sanctum is perfect for simple API token authentication and SPA authentication
- Use token abilities for fine-grained access control in your APIs
Laravel Sanctum is a lightweight authentication system for SPAs, mobile applications, and simple token-based APIs. Use it when you need a simpler alternative to Passport for API authentication without the complexity of OAuth2.
How does Sanctum differ from Laravel Passport?
Sanctum is lightweight and designed for simple token-based APIs, while Passport provides full OAuth2 implementation. Sanctum is easier to set up and maintain for most projects, while Passport is better for complex OAuth2 requirements.
Can I use Sanctum for both API tokens and SPA authentication?
Yes! Sanctum uniquely supports both token-based API authentication and traditional session-based authentication for SPAs, making it versatile for different application types.

Leave a Reply