Laravel REST API Authentication with Sanctum
Overview & Context
When building decoupled modern web applications—such as pairing a React or Next.js client with a Laravel backend—securing API communication without heavy OAuth2 infrastructure overhead is a critical architectural requirement. Laravel Sanctum provides a lightweight, token-based authentication system tailored for mobile apps, SPAs, and simple token-driven REST APIs.
Why Laravel Sanctum for REST APIs?
Traditional session-based authentication relies on browser cookies and CSRF tokens tied to the same domain. In decoupled full-stack architectures, client applications frequently run on separate domains or mobile viewports where stateless Bearer tokens are required.
Laravel Sanctum solves this by issuing cryptographically secure personal access tokens stored in your database. Each incoming HTTP request validates the Bearer token against the personal_access_tokens table without requiring the complexity of a full OAuth2 server like Laravel Passport.
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\LoginRequest;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
class AuthController extends Controller
{
public function login(LoginRequest $request)
{
$user = User::where('email', $request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
throw ValidationException::withMessages([
'email' => ['The provided credentials do not match our records.'],
]);
}
// Issue a plaintext Sanctum Bearer Token with specific abilities
$token = $user->createToken('auth-token', ['read', 'write'])->plainTextToken;
return response()->json([
'status' => 'success',
'token' => $token,
'user' => [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'role' => $user->role,
],
]);
}
public function logout()
{
// Revoke the current token that authenticated the active request
request()->user()->currentAccessToken()->delete();
return response()->json(['message' => 'Logged out successfully.']);
}
}Protecting Endpoints with Route Middleware
Once tokens are generated, endpoints are secured using the auth:sanctum route middleware in routes/api.php. Any unauthorized requests automatically receive an HTTP 401 Unauthorized response.
<?php
use App\Http\Controllers\Api\AuthController;
use App\Http\Controllers\Api\StudentController;
use Illuminate\Support\Facades\Route;
// Public authentication routes
Route::post('/auth/login', [AuthController::class, 'login']);
// Authenticated route group protected by Sanctum
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', fn (Request $request) => $request->user());
Route::get('/students', [StudentController::class, 'index']);
Route::post('/students', [StudentController::class, 'store']);
Route::post('/auth/logout', [AuthController::class, 'logout']);
});Client Integration: Handling Bearer Tokens in React
On the frontend client (React or Next.js), the issued token is persisted (e.g., in secure storage or memory) and attached to the Authorization header of all outgoing HTTP requests.
export async function fetchWithAuth<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
const token = localStorage.getItem('auth_token')
const response = await fetch(`https://api.example.com${endpoint}`, {
...options,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...options.headers,
},
})
if (response.status === 401) {
// Handle expired token or unauthorized access
localStorage.removeItem('auth_token')
window.location.href = '/login'
throw new Error('Session expired. Please log in again.')
}
return response.json()
}Production Application
Real-World Use Case: Decoupled Academic Platform (AI Smart Campus)
Engineering Scenario
A university management system with a standalone React/Vite client communicating with a Laravel 12 API backend across different subdomains.
Technical Implementation
Configured Laravel Sanctum personal access tokens. When students and faculty authenticate, Sanctum issues scoped Bearer tokens that the React application attaches to asynchronous query requests and AI assistant proxy endpoints.
Architectural Impact
Eliminated cross-origin cookie synchronization bugs while providing instant token revocation on logout and preventing unauthorized database access.
Summary
Key Engineering Takeaways
- Sanctum delivers lightweight personal access tokens without the configuration overhead of OAuth2 Passport servers.
- Always validate requests using dedicated FormRequest classes before issuing authentication tokens.
- Revoke specific tokens using $user->currentAccessToken()->delete() during logout to enforce strict session invalidation.
- Leverage Sanctum abilities (token scopes) to restrict write permissions for read-only clients.