Building a RESTful API with Laravel 13 and Sanctum for Authentication
In this tutorial, we will walk through the process of building a RESTful API using Laravel 13, a popular PHP framework. We will also implement authentication using Laravel Sanctum, a lightweight package for API token authentication. This combination is ideal for developers looking to create secure and scalable APIs for web and mobile applications.
Prerequisites
Before starting, ensure you have the following installed on your machine:
- PHP >= 8.0
- Composer
- MySQL
- Node.js & NPM
To install these prerequisites, you can use the following commands:
PHP and Composer
For Ubuntu:
sudo apt update
sudo apt install php8.0 php8.0-cli php8.0-fpm php8.0-mysql php8.0-xml php8.0-mbstring php8.0-zip php8.0-curl
sudo apt install composer
MySQL
For Ubuntu:
sudo apt update
sudo apt install mysql-server
sudo mysql_secure_installation
Node.js and NPM
For Ubuntu:
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs
Verify the installations:
php -v
composer -v
mysql --version
node -v
npm -v
Project Structure
Once we set up our Laravel project, the directory structure will look like this:
my-laravel-api/
├── app/
├── bootstrap/
├── config/
├── database/
├── public/
├── resources/
├── routes/
│ ├── api.php
│ └── web.php
├── storage/
├── tests/
└── vendor/
Step 1: Setting Up a New Laravel Project
First, create a new Laravel project using Composer:
composer create-project --prefer-dist laravel/laravel my-laravel-api
Navigate into the project directory:
cd my-laravel-api
Start the Laravel development server:
php artisan serve
Visit http://localhost:8000 in your browser to see the default Laravel welcome page.
Explanation
This step initializes a new Laravel project named my-laravel-api. The php artisan serve command starts a local development server, allowing you to view the default Laravel application.
Step 2: Configuring the Database
Edit the .env file in the root of your project to configure your database connection. Update the following lines with your database credentials:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_api
DB_USERNAME=root
DB_PASSWORD=your_password
Create the database using MySQL:
CREATE DATABASE laravel_api;
Run the following command to apply any pending migrations and set up the database schema:
php artisan migrate
Explanation
In this step, we connect our Laravel application to a MySQL database. The .env file stores environment-specific variables, including database credentials. Running php artisan migrate applies any migrations, setting up the necessary tables in the database.
Step 3: Installing and Setting Up Sanctum
Install Laravel Sanctum via Composer:
composer require laravel/sanctum
Publish the Sanctum configuration file:
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
Run the Sanctum migrations to create the necessary tables:
php artisan migrate
Next, add Sanctum's middleware to your api middleware group within your app/Http/Kernel.php file:
protected $middlewareGroups = [
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
Finally, in your config/auth.php, set the sanctum driver for the API authentication guard:
'guards' => [
'api' => [
'driver' => 'sanctum',
'provider' => 'users',
'hash' => false,
],
],
Explanation
In this step, we install and configure Laravel Sanctum for API token authentication. Sanctum provides a simple way to handle API authentication without the complexity of OAuth. We publish its configuration, run migrations, and update middleware and authentication settings to integrate Sanctum into our application.
Step 4: Creating API Endpoints
To create API endpoints, we will first define routes in routes/api.php and then create corresponding controllers.
4.1 Defining Routes
Open routes/api.php and add the following routes for user registration and login:
use App\Http\Controllers\AuthController;
use Illuminate\Support\Facades\Route;
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
4.2 Creating the AuthController
Generate a new controller using Artisan:
php artisan make:controller AuthController
Open app/Http/Controllers/AuthController.php and implement the register and login methods:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;
class AuthController extends Controller
{
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',
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json(['access_token' => $token, 'token_type' => 'Bearer']);
}
public function login(Request $request)
{
$request->validate([
'email' => 'required|string|email',
'password' => 'required|string',
]);
if (!Auth::attempt($request->only('email', 'password'))) {
return response()->json(['message' => 'Unauthorized'], 401);
}
$user = User::where('email', $request->email)->firstOrFail();
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json(['access_token' => $token, 'token_type' => 'Bearer']);
}
}
Explanation
In this step, we define API routes and implement user registration and login functionality in the AuthController. The register method creates a new user and issues a token, while the login method authenticates an existing user and provides a token.
Step 5: Testing the API
To test the API, you can use tools like Postman or cURL.
5.1 Register a New User
Use the following cURL command to register a new user:
curl -X POST http://localhost:8000/api/register \
-H "Content-Type: application/json" \
-d '{"name": "John Doe", "email": "john@example.com", "password": "password"}'
5.2 Log in as a User
Use the following cURL command to log in:
curl -X POST http://localhost:8000/api/login \
-H "Content-Type: application/json" \
-d '{"email": "john@example.com", "password": "password"}'
Explanation
These commands demonstrate how to interact with the API endpoints for user registration and login. Successful requests return an access token.
Complete Working Example
Here are the key files for the complete working example:
routes/api.php
use App\Http\Controllers\AuthController;
use Illuminate\Support\Facades\Route;
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
app/Http/Controllers/AuthController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;
class AuthController extends Controller
{
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',
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json(['access_token' => $token, 'token_type' => 'Bearer']);
}
public function login(Request $request)
{
$request->validate([
'email' => 'required|string|email',
'password' => 'required|string',
]);
if (!Auth::attempt($request->only('email', 'password'))) {
return response()->json(['message' => 'Unauthorized'], 401);
}
$user = User::where('email', $request->email)->firstOrFail();
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json(['access_token' => $token, 'token_type' => 'Bearer']);
}
}
Common Errors and Fixes
-
Error:
Class 'App\Models\User' not found- Fix: Ensure the
Usermodel exists inapp/Models/. If not, runphp artisan make:model Userto generate it.
- Fix: Ensure the
-
Error:
SQLSTATE[HY000] [1045] Access denied for user- Fix: Double-check your database credentials in the
.envfile. Ensure the username and password are correct.
- Fix: Double-check your database credentials in the
-
Error:
Target class [AuthController] does not exist- Fix: Ensure the
AuthControlleris correctly defined and the namespace matches the directory structure.
- Fix: Ensure the
Conclusion
In this tutorial, we built a basic RESTful API using Laravel 13 and implemented authentication with Sanctum. You now have a foundational API setup that can be expanded with more features and endpoints.
Sources
- Laravel Documentation: https://laravel.com/docs
- Laravel Sanctum Documentation: https://laravel.com/docs/sanctum
- PHP Documentation: https://www.php.net/docs.php