# ๐Ÿ“˜ Lecture 8: Authentication with Laravel Sanctum > Duration: \~3 hours\ > Target: Beginner to Intermediate\ > Stack: Laravel 12, RESTful APIs, Sanctum\ > Context: Using our **Expert Platform** backend APIs --- ## ๐ŸŒŸ Objectives By the end of this lecture, trainees will: - Understand **what authentication and authorization** mean in APIs - Learn **what tokens and API keys** are - Use **Laravel Sanctum** to secure APIs - Implement **registration**, **login**, and **logout** endpoints - Protect existing endpoints like `/api/experts` and `/api/bookings` - Build an authenticated `/api/me` route to get user info --- ## ๐Ÿง Theory: What is Authentication & Authorization? | Concept | Explanation | | ------------------ | -------------------------------------------------------------------------------------------------------------------- | | **Authentication** | Who are you? Proving your identity via credentials (email/password). | | **Authorization** | What can you do? Checking if you're allowed to access certain resources. | | **Access Token** | A secret key given after login, used to access protected APIs. | | **API Key** | A static token (not tied to login) used by clients to identify themselves. We use **access tokens** in this lecture. | ### ๐Ÿงน Sanctum vs Passport Laravel has two main options for API auth: - **Sanctum** (simple token-based, great for SPAs, mobile, basic APIs โœ…) - **Passport** (full OAuth2 server, more complex โŒ for now) ๐ŸŸข We use **Sanctum** because it's lightweight, easy, and perfect for our **Expert Platform**. --- ## ๐Ÿงช Step 1: Install Sanctum ```bash composer require laravel/sanctum ``` Then publish Sanctum's config and migration: ```bash php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider" php artisan migrate ``` This creates a new table: `personal_access_tokens`. --- ## โš™๏ธ Step 2: Configure Sanctum In `app/Http/Kernel.php`, add middleware: ```php 'api' => [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ``` Then in `config/sanctum.php`: ```php // leave as default for now ``` --- ## ๐Ÿ‘ค Step 3: Prepare the `User` Model Open `app/Models/User.php` and add the `HasApiTokens` trait: ```php use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { use HasApiTokens, HasFactory, Notifiable; } ``` --- ## โœ๏ธ Step 4: Create Auth Controller ```bash php artisan make:controller Api/AuthController ``` Inside `app/Http/Controllers/Api/AuthController.php`: ```php use Illuminate\Http\Request; use App\Models\User; use Illuminate\Support\Facades\Hash; use Illuminate\Validation\ValidationException; class AuthController extends Controller { public function register(Request $request) { $fields = $request->validate([ 'name' => 'required|string', 'email' => 'required|string|email|unique:users,email', 'password' => 'required|string|confirmed', ]); $user = User::create([ 'name' => $fields['name'], 'email' => $fields['email'], 'password' => bcrypt($fields['password']), ]); $token = $user->createToken('expert-platform-token')->plainTextToken; return response()->json([ 'user' => $user, 'token' => $token, ], 201); } public function login(Request $request) { $fields = $request->validate([ 'email' => 'required|string|email', 'password' => 'required|string', ]); $user = User::where('email', $fields['email'])->first(); if (!$user || !Hash::check($fields['password'], $user->password)) { throw ValidationException::withMessages([ 'email' => ['The credentials are incorrect'], ]); } $token = $user->createToken('expert-platform-token')->plainTextToken; return response()->json([ 'user' => $user, 'token' => $token, ]); } public function logout(Request $request) { $request->user()->tokens()->delete(); return response()->json(['message' => 'Logged out']); } public function me(Request $request) { return response()->json($request->user()); } } ``` --- ## ๐Ÿ”’ Step 5: Register Auth Routes In `routes/api.php`: ```php use App\Http\Controllers\Api\AuthController; Route::post('/register', [AuthController::class, 'register']); Route::post('/login', [AuthController::class, 'login']); Route::middleware('auth:sanctum')->group(function () { Route::post('/logout', [AuthController::class, 'logout']); Route::get('/me', [AuthController::class, 'me']); }); ``` --- ## ๐Ÿ” Step 6: Protect Existing APIs For example, in your `routes/api.php`: ```php use App\Http\Controllers\Api\ExpertController; Route::middleware('auth:sanctum')->group(function () { Route::apiResource('/experts', ExpertController::class); Route::post('/bookings', [BookingController::class, 'store']); // more protected routes... }); ``` Now, users must be logged in and send `Authorization: Bearer <token>` header. --- ## ๐Ÿ”Ž Step 7: Testing with Postman 1. **Register:** ```http POST /api/register Content-Type: application/json { "name": "John Doe", "email": "john@example.com", "password": "password", "password_confirmation": "password" } ``` 2. **Login:** ```http POST /api/login ``` โ†’ Copy `token` from response 3. **Call protected route:** ```http GET /api/me Authorization: Bearer eyJ0eXAiOiJKV... ``` --- ## ๐Ÿ–ผ๏ธ [Diagram] Sanctum Flow ``` +-------------+ POST /login +----------------------+ | Frontend +--------------------->+ AuthController | +-------------+ +----------------------+ | | -> Validates credentials | -> Generates token | <- Returns token v +-------------+ GET /experts +----------------------+ | Postman +------------------->+ Protected Controller | | (with token) | Authorization +----------------------+ +-------------+ Bearer token ``` --- ## ๐ŸŽฏ Summary - Authentication = verifying identity - Sanctum = simple token-based auth for APIs - `HasApiTokens` enables `createToken()` method - Routes protected via `auth:sanctum` - Tokens sent via HTTP `Authorization` header --- ## ๐Ÿ“ Assignment > ๐Ÿ”’ Secure your `/api/experts` and `/api/bookings` endpoints: 1. Implement `/api/register`, `/api/login`, `/api/logout` 2. Add `/api/me` to return logged-in user 3. Protect expert and booking routes with `auth:sanctum` 4. Test all endpoints using Postman