Laravel 10 REST API Authentication using Sanctum

Vidvatek
6 min readMar 7, 2024

--

As a Laravel enthusiast and web developer, I understand the paramount importance of securing REST APIs in today’s interconnected digital landscape.

Laravel, known for its elegant syntax and powerful features, is an excellent choice for building robust APIs.

And when it comes to authentication, Laravel Sanctum is the go-to package for simplifying the process while maintaining top-notch security.

In this step-by-step guide, I will walk you through the process of setting up REST API authentication using Laravel 10 and Sanctum.

Laravel Sanctum provides a featherweight authentication system for SPAs (single page applications), mobile applications, and simple, token based APIs.

Sanctum allows each user of your application to generate multiple API tokens for their account.

API authentication is a crucial aspect of modern web development, ensuring that only authorized users can access protected resources.

With Sanctum, Laravel provides a seamless solution to handle token-based authentication, making your API authentication journey both straightforward and secure.

So, let’s dive into the world of Laravel 10 and Sanctum and learn how to protect your APIs with ease.

Whether you’re building a single-page application, a mobile app, or any other service that communicates over HTTP, this guide will equip you with the knowledge and skills needed to secure your Laravel API effectively.

So, let’s see Laravel 10 REST API Authentication using Sanctum, how to create REST API Authentication using Sanctum in Laravel 9/10, Laravel 9/10 Sanctum, and Laravel Sanctum API Authentication.

Laravel 10 REST API Authentication using Sanctum — A Step-by-Step Guide

Step 1: Create a New Laravel Project

Open your terminal and run the following command to create a new Laravel project.

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

Step 2: Install Sanctum using Composer

Install Sanctum using the Composer command.

composer require laravel/sanctum

Next, publish the Sanctum configuration file.

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

Step 3: Set Up Database

Configure your .env file with database credentials and run migrations.

php artisan migrate

Step 4: Configure Sanctum

Now, we configure the sanctum to add middleware into the kernel.php file.

app/Http/Kernel.php

....
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
....

In app/Models/User.php, update the use HasApiTokens trait to enable API token generation for users.

app/Models/User.php

<?php

namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}

Read Also: Laravel 10 Import and Export CSV and Excel Files

Step 5: Add Migration and Model

Create migration and model for the product using the command.

php artisan make:migration create_products_table

Migration:

<?php  
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('detail');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
Schema::dropIfExists('products');
}
};

Now, run the migration table using the migration command.

php artisan migrate

app/Models/Product.php

<?php

namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'detail'
];
}

Step 6: Create API Routes

Then, we will create API routes for login, register, and product rest API.

routes/api.php

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\API\RegisterController;
use App\Http\Controllers\API\ProductController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::controller(RegisterController::class)->group(function(){
Route::post('register', 'register');
Route::post('login', 'login');
});

Route::middleware('auth:sanctum')->group( function () {
Route::resource('products', ProductController::class);
});

Step 7: Create Controller File

Now, create a controller in the API folder.

app/Http/Controllers/API/BaseController.php

<?php

namespace App\Http\Controllers\API;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller as Controller;
class BaseController extends Controller
{
/**
* success response method.
*
* @return \Illuminate\Http\Response
*/
public function sendResponse($result, $message)
{
$response = [
'success' => true,
'data' => $result,
'message' => $message,
];
return response()->json($response, 200);
}
/**
* return error response.
*
* @return \Illuminate\Http\Response
*/
public function sendError($error, $errorMessages = [], $code = 404)
{
$response = [
'success' => false,
'message' => $error,
];
if(!empty($errorMessages)){
$response['data'] = $errorMessages;
}
return response()->json($response, $code);
}
}

app/Http/Controllers/API/RegisterController.php

<?php

namespace App\Http\Controllers\API;
use Illuminate\Http\Request;
use App\Http\Controllers\API\BaseController as BaseController;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Validator;
use Illuminate\Http\JsonResponse;
class RegisterController extends BaseController
{
/**
* Register api
*
* @return \Illuminate\Http\Response
*/
public function register(Request $request): JsonResponse
{
$validator = Validator::make($request->all(), [
'name' => 'required',
'email' => 'required|email',
'password' => 'required',
'c_password' => 'required|same:password',
]);
if($validator->fails()){
return $this->sendError('Validation Error.', $validator->errors());
}
$input = $request->all();
$input['password'] = bcrypt($input['password']);
$user = User::create($input);
$success['token'] = $user->createToken('MyApp')->plainTextToken;
$success['name'] = $user->name;
return $this->sendResponse($success, 'User register successfully.');
}
/**
* Login api
*
* @return \Illuminate\Http\Response
*/
public function login(Request $request): JsonResponse
{
if(Auth::attempt(['email' => $request->email, 'password' => $request->password])){
$user = Auth::user();
$success['token'] = $user->createToken('MyApp')->plainTextToken;
$success['name'] = $user->name;
return $this->sendResponse($success, 'User login successfully.');
}else{
return $this->sendError('Unauthorised.', ['error'=>'Unauthorised']);
}
}
}

app/Http/Controllers/API/ProductController.php

<?php

namespace App\Http\Controllers\API;
use Illuminate\Http\Request;
use App\Http\Controllers\API\BaseController as BaseController;
use App\Models\Product;
use Validator;
use App\Http\Resources\ProductResource;
use Illuminate\Http\JsonResponse;
class ProductController extends BaseController
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(): JsonResponse
{
$products = Product::all();
return $this->sendResponse(ProductResource::collection($products), 'Products retrieved successfully.');
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/

public function store(Request $request): JsonResponse
{
$input = $request->all();
$validator = Validator::make($input, [
'name' => 'required',
'detail' => 'required'
]);

if($validator->fails()){
return $this->sendError('Validation Error.', $validator->errors());
}
$product = Product::create($input);

return $this->sendResponse(new ProductResource($product), 'Product created successfully.');
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/

public function show($id): JsonResponse
{
$product = Product::find($id);
if (is_null($product)) {
return $this->sendError('Product not found.');
}
return $this->sendResponse(new ProductResource($product), 'Product retrieved successfully.');
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Product $product): JsonResponse
{
$input = $request->all();
$validator = Validator::make($input, [
'name' => 'required',
'detail' => 'required'
]);
if($validator->fails()){
return $this->sendError('Validation Error.', $validator->errors());
}
$product->name = $input['name'];
$product->detail = $input['detail'];
$product->save();

return $this->sendResponse(new ProductResource($product), 'Product updated successfully.');
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Product $product): JsonResponse
{
$product->delete();
return $this->sendResponse([], 'Product deleted successfully.');
}
}

Read Also: Laravel 10 Send Mail Using Queue

Step 8: Create Eloquent API Resources

Now, we will create API resources using the following command.

php artisan make:resource ProductResource

app/Http/Resources/ProductResource.php

<?php

namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ProductResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'detail' => $this->detail,
'created_at' => $this->created_at->format('d/m/Y'),
'updated_at' => $this->updated_at->format('d/m/Y'),
];
}
}

Step 9: Run the Laravel App

Now, run the laravel application using the artisan command.

php artisan serve

Now, Go to your postman and check the following APIs.

Add header details into the POSTMAN.

'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$accessToken,
]

Here is Routes URL with Verb:

  1. Register API: Verb: GET, URL:http://localhost:8000/api/register
  2. Login API: Verb: GET, URL:http://localhost:8000/api/login
  3. Product List API: Verb: GET, URL:http://localhost:8000/api/products
  4. Product Create API: Verb: POST, URL:http://localhost:8000/api/products
  5. Product Show API: Verb: GET, URL:http://localhost:8000/api/products/{id}
  6. Product Update API: Verb: PUT, URL:http://localhost:8000/api/products/{id}
  7. Product Delete API: Verb: DELETE, URL:http://localhost:8000/api/products/{id}

--

--

Vidvatek

Vidvatek is a comprehensive platform dedicated to assisting beginner programmers in launching their careers in web development.