Laravel 12 API Authentication with Sanctum

Laravel 12 API Authentication with Sanctum

 Guide to building a secure Laravel 12 REST API using Laravel Sanctum for token-based authentication. Laravel Sanctum is a simple package for API token authentication and is ideal for SPAs or mobile apps.

Laravel 12 API Authentication with Sanctum

Prerequisites

Before starting, ensure you have:

  • PHP 8.1+

  • Composer

  • Laravel 12

  • MySQL or MariaDB

  • Postman (for testing)

Step 1: Create a Laravel 12 Project

composer create-project laravel/laravel laravel-sanctum-api

Step 2: Install Laravel Sanctum

composer require laravel/sanctum

Step 3: Add HasApiTokens to User Model

In app/Models/User.php, add:

use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { use HasApiTokens, HasFactory, Notifiable; }

Step 4: Configure Database

In your .env file:

DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=your_db_name DB_USERNAME=your_db_user DB_PASSWORD=your_db_password

Then run:

php artisan migrate

Step 5: Create API Routes

If the a install:api A command is available; run it in your terminal:

php artisan install:api

This will automatically generate API controllers, routes, and configurations, and may also install any

Step 6: Define API Routes

Open routes/api.php and add:

Route::group(['namespace' => 'App\Http\Controllers\API'], function () { // --------------- Register and Login ----------------// Route::post('register', 'AuthenticationController@register')->name('register'); Route::post('login', 'AuthenticationController@login')->name('login'); // ------------------ Get Data ----------------------// Route::middleware('auth:sanctum')->group(function () { Route::get('get-user', 'AuthenticationController@userInfo')->name('get-user'); Route::post('logout', 'AuthenticationController@logOut')->name('logout'); }); });

Step 7: Create Authentication Controller

php artisan make:controller API/AuthenticationController

Step 8: AuthenticationController Logic

Edit app/Http/Controllers/API/AuthenticationController.php:

<?php namespace App\Http\Controllers\API; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Log; use Illuminate\Validation\ValidationException; use App\Models\User; class AuthenticationController extends Controller { /** * Register a new account. */ public function register(Request $request) { try { $validated = $request->validate([ 'name' => 'required|string|min:4', 'email' => 'required|string|email|max:255|unique:users', 'password' => 'required|string|min:8', ]); $user = User::create([ 'name' => $validated['name'], 'email' => $validated['email'], 'password' => Hash::make($validated['password']), ]); return response()->json([ 'response_code' => 201, 'status' => 'success', 'message' => 'Successfully registered', ], 201); } catch (ValidationException $e) { return response()->json([ 'response_code' => 422, 'status' => 'error', 'message' => 'Validation failed', 'errors' => $e->errors(), ], 422); } catch (\Exception $e) { Log::error('Registration Error: ' . $e->getMessage()); return response()->json([ 'response_code' => 500, 'status' => 'error', 'message' => 'Registration failed', ], 500); } } /** * Login and return auth token. */ public function login(Request $request) { try { $credentials = $request->validate([ 'email' => 'required|email', 'password' => 'required|string', ]); if (!Auth::attempt($credentials)) { return response()->json([ 'response_code' => 401, 'status' => 'error', 'message' => 'Unauthorized', ], 401); } $user = Auth::user(); $token = $user->createToken('authToken')->plainTextToken; return response()->json([ 'response_code' => 200, 'status' => 'success', 'message' => 'Login successful', 'user_info' => [ 'id' => $user->id, 'name' => $user->name, 'email' => $user->email, ], 'token' => $token, 'token_type' => 'Bearer', ]); } catch (ValidationException $e) { return response()->json([ 'response_code' => 422, 'status' => 'error', 'message' => 'Validation failed', 'errors' => $e->errors(), ], 422); } catch (\Exception $e) { Log::error('Login Error: ' . $e->getMessage()); return response()->json([ 'response_code' => 500, 'status' => 'error', 'message' => 'Login failed', ], 500); } } /** * Get list of users (paginated) — protected route. */ public function userInfo() { try { $users = User::latest()->paginate(10); return response()->json([ 'response_code' => 200, 'status' => 'success', 'message' => 'Fetched user list successfully', 'data_user_list' => $users, ]); } catch (\Exception $e) { Log::error('User List Error: ' . $e->getMessage()); return response()->json([ 'response_code' => 500, 'status' => 'error', 'message' => 'Failed to fetch user list', ], 500); } } /** * Logout user and revoke tokens — protected route. */ public function logOut(Request $request) { try { $user = $request->user(); if ($user) { $user->tokens()->delete(); return response()->json([ 'response_code' => 200, 'status' => 'success', 'message' => 'Successfully logged out', ]); } return response()->json([ 'response_code' => 401, 'status' => 'error', 'message' => 'User not authenticated', ], 401); } catch (\Exception $e) { Log::error('Logout Error: ' . $e->getMessage()); return response()->json([ 'response_code' => 500, 'status' => 'error', 'message' => 'An error occurred during logout', ], 500); } } }

Step 9: Run the Server

php artisan serve 

Step 10: Test Routes in Postman

ActionMethodURLAuth Header
RegisterPOSThttp://localhost:8000/api/register-
LoginPOSThttp://localhost:8000/api/login-
Get UserGEThttp://localhost:8000/api/get-userBearer your_token
LogoutPOSThttp://localhost:8000/api/logoutBearer your_token

Step 1: Test the API with Postman

Register

  • POST http://127.0.0.1:8000/api/register

  • Body (JSON):

{ "name": "StarCode Kh", "email": "starcodekh@example.com", "password": "password@123" }

Login

  • POST http://127.0.0.1:8000/api/login

  • Response will include the token.

Get Authenticated User

  • GET http://127.0.0.1:8000/api/get-user

  • Header:

Authorization: Bearer YOUR_TOKEN_HERE

Logout

  • POST http://127.0.0.1:8000/api/logout

  • Header:

Authorization: Bearer YOUR_TOKEN_HERE

Conclusion

You’ve now built a secure Laravel 12 REST API with:

  • User registration

  • Login with token generation

  • Protected routes using auth:sanctum

  • Token-based logout

Souy Soeng

Souy Soeng

Hi there 👋, I’m Soeng Souy (StarCode Kh)
-------------------------------------------
🌱 I’m currently creating a sample Laravel and React Vue Livewire
👯 I’m looking to collaborate on open-source PHP & JavaScript projects
💬 Ask me about Laravel, MySQL, or Flutter
⚡ Fun fact: I love turning ☕️ into code!

Post a Comment

CAN FEEDBACK
close