Laravel 11 REST API Authentication using Sanctum Tutorial

  Mar 2024
  ITSolutionsGuides
  Category: Laravel
Laravel 11 REST API Authentication using Sanctum Tutorial

Welcome To ITSolutionsGuides,


In this tutorial lets see Laravel 11 REST API Authentication using Sanctum. Laravel Sanctum provides a simple authentication using the JWT token which is widely used for the smaller applications.
Laravel Sanctum stands out as an API authentication solution tailored for Laravel apps. It presents a user-friendly, lightweight approach to authentication, ideal for SPAs, mobile apps, and API-centric projects. Employing JSON Web Tokens (JWT) or API tokens, it ensures secure authentication without the usual session-based overhead. Sanctum streamlines the setup of token authentication, empowering developers to concentrate on their application's core functionalities, rather than grappling with authentication intricacies.
An API, or application programming interface, serves as a conduit for communication among multiple computer programs. Essential in both web and mobile app development, constructing a REST API is crucial for developers in these domains.
Lets see how to implement Laravel 11 REST API Authentication effortlessly with Sanctum using token-based authentication for secure API endpoints.

Let's Start Coding

laravel new rest_api
In Laravel 11 we need to intsall API in order to use it , Lets install using the following artisan command,
php artisan install:api

The above artisan command will create the api.php file in the routes directory and also it will install the laravel/sanctum package which was a API authentication package for Laravel. In order to use the Santum for the authentication we need to add the traid in the User model,
use Laravel\Sanctum\HasApiTokens;
and also we should add use HasApiTokens;
app/Models/User.php

<?php
  
namespace App\Models;
  
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 HasFactory, Notifiable, HasApiTokens;
  
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];
  
    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];
  
    /**
     * Get the attributes that should be cast.
     *
     * @return array
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }
}

Let's Create Model and Migration

Lets create both the migration and the model using the following artisan command,
php artisan make:model Product -m

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

Let's Edit Model

Lets run the migrations using the following artisan 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'
    ];
}

Let's Create Routes

Since it all were the API routes we need to register all the routes in the api.php file.


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;
   
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);
});

Let's Create Controller

Lets create the BaseController using the following artisan command
php artisan make:controller API/BaseController
BaseController were created to make a unique format for all the API response throughout the application. In order to use this controller we need to extend the controller to the BaseController in order to use that.


app/Http/Controllers/API/BaseController.phpp

<?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);
    }
}

Let's Create Controller

php artisan make:controller API/RegisterController

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']);
        } 
    }
}

Let's Create Controller

php artisan make:controller API/ProductController
In this controller we will send the response via ProductResource to structure the API response.

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.');
    }
}

Let's Create Eloquent API Resources

Lets create the Resources using the following artisan command,
php artisan make:resource ProductResource
the resources are used to structure the API response as per the user requests like filtering columns or modify any of the table column data.


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'),
        ];
    }
}

Let's Run the Application

Lets run the application using the following artisan command,
php artisan serve

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

http://localhost:8000/api/register
http://localhost:8000/api/login
http://localhost:8000/api/products
http://localhost:8000/api/products/{id}

We hope it helps everyone. Thanks for supporting ITSolutionsGuides and keep supporting us also follow us in social media platforms.

Subscribe for NewsLetter

Be the first to know about releases and tutorial news and solutions.

We care about your data in our privacy policy.

ITSolutionsGuides

ITSolutionsGuides was started mainly to provide good and quality web solutions for all the developers. We provide tutorials to support all the developers and also we try to provide solutions to the errors we face while coding.

Contact US

ITSolutionsGuides, provide users with an easy-to-use form to reach out for support or inquiries.

whatsapp  gmail  instagram-new--v1  facebook-circled  twitter-circled  linkedin  github  pinterest 

Copyright © 2023 - 2024 All rights reserved | ITSolutionsGuides