Authentication with Sanctum
LaravelLaravel Sanctum provides a lightweight authentication system for SPAs, mobile apps, and simple token-based APIs. It's the most common auth solution for modern Laravel apps.
Install Sanctum
Terminal
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrateSetup User Model
app/Models/User.php
<?php
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
}Auth Controller (Register + Login + Logout)
app/Http/Controllers/Api/AuthController.php
<?php
namespace App\Http\Controllers\Api;
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|unique:users',
'password' => 'required|min:8|confirmed',
]);
$user = User::create([
'name' => $validated['name'],
'email' => $validated['email'],
'password' => Hash::make($validated['password']),
]);
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json([
'user' => $user,
'access_token' => $token,
'token_type' => 'Bearer',
], 201);
}
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->createToken('auth_token')->plainTextToken;
return response()->json([
'user' => $user,
'access_token' => $token,
'token_type' => 'Bearer',
]);
}
public function logout(Request $request)
{
$request->user()->currentAccessToken()->delete();
return response()->json(['message' => 'Logged out']);
}
public function me(Request $request)
{
return response()->json($request->user());
}
}Routes
routes/api.php
<?php
use App\Http\Controllers\Api\AuthController;
// Public routes
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
// Protected routes
Route::middleware('auth:sanctum')->group(function () {
Route::post('/logout', [AuthController::class, 'logout']);
Route::get('/me', [AuthController::class, 'me']);
Route::apiResource('posts', PostController::class);
});Testing with Postman
HTTP Requests
# Register
POST /api/register
{
"name": "John Doe",
"email": "john@example.com",
"password": "password123",
"password_confirmation": "password123"
}
# Login — get token
POST /api/login
{ "email": "john@example.com", "password": "password123" }
# Use token in header for protected routes
GET /api/me
Authorization: Bearer 1|abc123xyz...Token Abilities (Scopes)
PHP
<?php
// Create token with specific abilities
$token = $user->createToken('mobile-app', ['posts:read', 'posts:write'])->plainTextToken;
// Check ability in controller
if ($request->user()->tokenCan('posts:write')) {
// allowed
}💡
Sanctum vs Passport: Use Sanctum for most apps — it's simpler. Use Passport only if you need full OAuth2 with authorization codes (e.g., "Login with MyApp" functionality).
Test your knowledge!
Take the Laravel quiz.