Laravel Sanctum is a lightweight API authentication system provided by Laravel. It offers a simple and robust way to authenticate single-page applications (SPAs), mobile applications, and simple, token-based APIs.
Key Features and Use Cases:
1. SPA Authentication: For SPAs (like Vue.js, React, or Angular frontends) that interact with a Laravel backend, Sanctum leverages Laravel's existing session-based authentication. When a SPA makes a request, Sanctum attempts to authenticate via a session cookie. This requires proper Cross-Origin Resource Sharing (CORS) configuration, sending credentials (`withCredentials`), and handling CSRF tokens on the frontend.
2. Mobile Application & Token-Based API Authentication: For mobile applications or third-party APIs, Sanctum provides a system for issuing API tokens (also known as "personal access tokens"). These tokens are issued to users and stored in the database. When a mobile app or another API client makes a request, it sends this token in the `Authorization` header as a Bearer token. Sanctum then authenticates the request using this token.
How it Works (API Tokens):
* Token Issuance: Users can generate API tokens through an endpoint in your application. These tokens are stored in the `personal_access_tokens` table in your database.
* Abilities (Scopes): Each token can be assigned a specific set of "abilities" or scopes, defining what actions the token is authorized to perform. For example, a token might have `['read', 'write']` abilities for a specific resource, allowing fine-grained access control.
* Authentication: When an incoming request includes an `Authorization: Bearer {token}` header, Sanctum retrieves the associated token from the database, authenticates the user, and makes the authenticated user available via `Auth::user()`.
* Token Revocation: Tokens can be revoked by the user or an administrator, instantly invalidating them and preventing further unauthorized access.
Installation and Setup:
1. Install Sanctum:
```bash
composer require laravel/sanctum
```
2. Publish Configuration and Run Migrations:
```bash
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
```
This command creates the `personal_access_tokens` table and publishes the `sanctum.php` configuration file.
3. Middleware: For SPA authentication, ensure the `EnsureFrontendRequestsAreStateful` middleware is uncommented in your `app/Http/Kernel.php` within the `api` middleware group. For API token authentication, ensure your API routes use the `auth:sanctum` guard.
4. User Model Trait: Add the `HasApiTokens` trait to your `App\Models\User` model:
```php
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
// ...
}
```
SPA Statefulness Configuration:
For SPAs, you must configure the `SANCTUM_STATEFUL_DOMAINS` environment variable in your `.env` file to include the domain of your frontend application (e.g., `http://localhost:3000`). This tells Sanctum to treat requests from these domains as stateful, using session cookies.
Example Code
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use App\Models\User;
use Illuminate\Validation\ValidationException;
class AuthController extends Controller
{
/
* Register a new user.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function register(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|confirmed',
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
return response()->json([
'message' => 'User registered successfully!'
], 201);
}
/
* Authenticate user and create a new personal access token.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException
*/
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
'device_name' => 'required', // e.g., 'iPhone_12_Pro', 'My_Web_Browser'
]);
$user = User::where('email', $request->email)->first();
if (! $user || ! Hash::check($request->password, $user->password)) {
throw ValidationException::withMessages([
'email' => ['The provided credentials are incorrect.'],
]);
}
// Create a token with specific abilities (scopes)
// For example, ['post:create', 'post:read'], or ['*'] for all abilities
$token = $user->createToken($request->device_name, ['post:create', 'post:read'])->plainTextToken;
return response()->json([
'token' => $token
]);
}
/
* Get the authenticated user's details.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function user(Request $request)
{
return response()->json($request->user());
}
/
* Logout the authenticated user (revoke current token).
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function logout(Request $request)
{
// Revoke the current token that was used for the request
$request->user()->currentAccessToken()->delete();
// Optionally, to revoke ALL tokens for the user:
// $request->user()->tokens()->delete();
return response()->json([
'message' => 'Logged out successfully.'
]);
}
}
/*
|--------------------------------------------------------------------------
| Example API Routes (in routes/api.php)
|--------------------------------------------------------------------------
*/
// Public routes (accessible without authentication)
// Route::post('/register', [AuthController::class, 'register']);
// Route::post('/login', [AuthController::class, 'login']);
// Protected routes (require a valid Sanctum token)
// Route::middleware('auth:sanctum')->group(function () {
// Route::get('/user', [AuthController::class, 'user']);
// Route::post('/logout', [AuthController::class, 'logout']);
// // Example of route protection by token ability (scope)
// Route::post('/posts', function () {
// // This route can only be accessed by tokens with 'post:create' ability
// return response()->json(['message' => 'Post created successfully!']);
// })->middleware('abilities:post:create'); // Or ->middleware('can:create,Post') if using gates/policies
// Route::get('/posts', function () {
// // This route can only be accessed by tokens with 'post:read' ability
// return response()->json(['message' => 'List of posts.']);
// })->middleware('abilities:post:read');
// });
/*
|--------------------------------------------------------------------------
| How to make requests using the token
|--------------------------------------------------------------------------
*/
// After a successful login, your API will return a token.
// Send this token in the Authorization header for subsequent protected requests:
//
// HTTP Request Example (using a tool like Postman, Insomnia, or Axios in JS):
//
// GET /api/user
// Headers:
// Authorization: Bearer <YOUR_GENERATED_TOKEN>
// Accept: application/json
//
// POST /api/posts
// Headers:
// Authorization: Bearer <YOUR_GENERATED_TOKEN>
// Accept: application/json
// Body: {"title": "New Post", "content": "This is a new post."}








laravel/sanctum