Kritim Yantra
Apr 04, 2025
Laravel Sanctum is like a Swiss Army knife for authentication in modern web apps. Whether you're building a single-page application (SPA), mobile app, or API, Sanctum handles authentication securely and elegantly. In this guide, we'll create a food delivery app to demonstrate user registration, login, and logout using Sanctum. No prior Sanctum experience required!
Imagine "Foodly," a food delivery service with:
localhost:3000
localhost:8000
php artisan install:api
In config/sanctum.php
:
'stateful' => [
'localhost:3000', // Your SPA domain
'foodly-app://' // Mobile app deep link
],
In config/cors.php
:
'supports_credentials' => true,
In bootstrap/app.php
:
->withMiddleware(function (Middleware $middleware) {
$middleware->statefulApi(); // Enable SPA auth
})
// routes/api.php
Route::post('/register', [AuthController::class, 'register']);
public function register(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|confirmed|min:8',
]);
$user = User::create([
'name' => $validated['name'],
'email' => $validated['email'],
'password' => Hash::make($validated['password']),
]);
return response()->json(['message' => 'Registration successful!'], 201);
}
Example Registration Request (Postman):
POST /api/register
{
"name": "Foodie User",
"email": "user@foodly.com",
"password": "secret123",
"password_confirmation": "secret123"
}
1. Initialize CSRF Protection (React Example):
// LoginComponent.jsx
useEffect(() => {
axios.get('http://localhost:8000/sanctum/csrf-cookie');
}, []);
2. Login Route
// routes/api.php
Route::post('/login', [AuthController::class, 'login']);
3. Login Method
public function login(Request $request)
{
$credentials = $request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if (Auth::attempt($credentials)) {
return response()->json(['user' => Auth::user()]);
}
return response()->json(['error' => 'Invalid credentials'], 401);
}
React Login Form:
const handleLogin = async () => {
await axios.post('/login', {
email: 'user@foodly.com',
password: 'secret123'
});
// Subsequent requests automatically include session cookies
const profile = await axios.get('/api/profile');
};
1. Token Generation Endpoint
// routes/api.php
Route::post('/mobile/login', [AuthController::class, 'mobileLogin']);
2. Mobile Login Logic
public function mobileLogin(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
'device_name' => 'required',
]);
$user = User::where('email', $request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
return response()->json(['error' => 'Invalid credentials'], 401);
}
return response()->json([
'token' => $user->createToken($request->device_name)->plainTextToken
]);
}
Mobile Usage Example:
// Flutter API call
var response = await http.post(
Uri.parse('http://localhost:8000/api/mobile/login'),
body: {
'email': 'user@foodly.com',
'password': 'secret123',
'device_name': 'Pixel 6',
},
);
String token = response.body['token'];
// routes/api.php
Route::middleware('auth:sanctum')->group(function () {
Route::get('/profile', function () {
return auth()->user();
});
Route::post('/orders', [OrderController::class, 'store']);
});
Web (Automatic Cookie Auth):
axios.get('/api/profile') // Cookies automatically included
Mobile (Bearer Token):
http.get(
Uri.parse('http://localhost:8000/api/profile'),
headers: {'Authorization': 'Bearer $token'},
);
// routes/api.php
Route::post('/logout', [AuthController::class, 'logout']);
public function logout(Request $request)
{
Auth::guard('web')->logout();
$request->session()->invalidate();
return response()->json(['message' => 'Logged out']);
}
public function mobileLogout(Request $request)
{
$request->user()->currentAccessToken()->delete();
return response()->json(['message' => 'Token revoked']);
}
// config/sanctum.php
'expiration' => 525600, // 1 year in minutes
$token = $user->createToken('pos-terminal', ['orders:create']);
php artisan sanctum:prune-expired
SESSION_SECURE_COOKIE=true
SESSION_SAME_SITE=lax
Web Flow Test:
Mobile Flow Test:
Scenario | Authentication Method |
---|---|
Same-domain SPA | Session Cookies |
Mobile Apps | API Tokens |
Third-party APIs | Tokens with Scopes |
By following this guide, you've created a robust authentication system for multiple client types. Sanctum's dual approach ensures your web users get seamless cookie-based auth while mobile apps use secure tokens. Remember to always validate user input and implement rate limiting in production!
Ready to take it further? Explore Sanctum's channel authentication for real-time features or implement OAuth2 for third-party integrations!
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google