Laravel 8 API CRUD with Authentication using Sanctum

tutspack laravel
Spread the love
  • 8
  •  
  •  
  •  
  •  
  •  
  •  
    8
    Shares

Hello Artisans,

How are you doing? In this tutorial I will show you Laravel 8 API CRUD with Authentication using Sanctum. So here we go . . . . . .

What is 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. These tokens may be granted abilities / scopes which specify which actions the tokens are allowed to perform.

How Sanctum Works?

Laravel Sanctum exists solving two separate problems such as API tokens and SPA Authentication. Let’s discuss each before digging deeper into this sanctum library.

API Tokens

First, Sanctum is a simple package that may use to issue API tokens to our users without the complication of OAuth. This laravel sanctum feature is inspired by GitHub and other applications which issue “personal access tokens”. 

Laravel Sanctum offers this above feature by storing user API tokens in a single database table and authenticating incoming HTTP requests via the Authorization header which must contain a valid API token.

SPA Authentication

Second, Sanctum exists to offer a simple way to authenticate single page applications (SPAs) that need to communicate with a Laravel powered API. Those SPAs might exist in the same repository as your Laravel application or might be an entirely separate repository, such as a SPA created using Vue CLI or a Next.js application.

In this tutorial,I will show you step by step how to you create an CRUD API for your project.

Step 1: Install Laravel 8

run this command in your terminal
composer create-project --prefer-dist laravel/laravel sanctum_api_crud

Step 2: Install Sanctum

You can install Laravel Sanctum via the Composer package manager:

composer require laravel/sanctum

After successfully install this package, you have to publish the Sanctum configuration and migration files using the vendor:publish Artisan command. The sanctum configuration file will be placed in your application’s config directory:

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

Finally, set up the database name for this project and now you should run your database migrations. Laravel sanctum will create one database table in which to store API tokens:

php artisan migrate

Next, if you plan to utilize Sanctum to authenticate a SPA, you should add Sanctum’s middleware to your api middleware group within your application’s app/Http/Kernel.php file. So we have to add middleware for sanctum API, So let’s add as like bellow:

app/Http/Kernel.php

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

Step 3: Configure Sanctum

In User model you have to add HasApiTokens trait of Sanctum and In auth.php, we added api auth configuration.

use Laravel\Sanctum\HasApiTokens;

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

Step 4: Create Product Table and Model

Run this command in your terminal ……

php artisan make:model Product -m

Add those field in your migrations file.

   public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id');
            $table->string('name',15);
            $table->float('price');
            $table->text('description');
            $table->string('image');
            $table->timestamps();
        });
    }

app/Models/Product.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', 'user_id' ,'price','description','image'
    ];
}

Step 4: Now Create API Routes

In this step, you have to create api routes. Laravel provides api.php file for writing web services route. So, let’s create those below new routes on that file.

routes/api.php

Route::apiResource('products',ProductController::class)->middleware('auth:sanctum');
Route::post('register',[AuthController::class,'register']);
Route::post('login', [AuthController::class, 'login']);
Route::post('logout', [AuthController::class, 'logout'])->middleware('auth:sanctum');
Route::get('search/{key}', [ProductController::class, 'search'])->middleware('auth:sanctum');

Step 5: Now Times to Create Controller

Now you have to create two Controller.One is AuthController for Authentication and another is Product Controller which will be resources Controller. Run these command in your terminal.

php arisan make:controller AuthController
php arisan make:controller ProductController --resource

After run these command two controller has created in your app/Http/Controllers folder. Paste this code in two controllers.

AuthController:

public function register(RegisterRequest $request)
    {
        $data = $request->validated();
        $data['password'] = bcrypt($data['password']);
        $user = User::create($data);
        $success['token'] =  $user->createToken('SanctumAPI')->plainTextToken;
        $success['name'] =  $user->name;

        return $this->sendResponse($success, 'User register successfully.',201);
    }

    public function login(Request $request)
    {
        if (Auth::attempt(['email' => $request->email, 'password' => $request->password])) {
            $user = Auth::user();
            $success['token'] =  $user->createToken('SanctumAPI')->plainTextToken;
            $success['name'] =  $user->name;

            return $this->sendResponse($success, 'User login successfully.');
        } else {
            return $this->sendError('Unauthorized.', ['error' => 'Unauthorized'],401);
        }
    }
    public function logout(Request $request)
    {
        auth()->user()->tokens()->delete();

        return [
            'message' => 'Logged out'
        ];
    }

ProductController:

<?php

namespace App\Http\Controllers;

use App\Models\Product;
use Illuminate\Http\Request;
use App\Http\Requests\ProductRequest;
use App\Http\Resources\ProductResource;

class ProductController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $products = Product::with('category')->latest()->get();
        return $this->sendResponse($products, 'Products retrieved successfully.');
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(ProductRequest $request)
    {
        $data =  $request->validated();
        $product = Product::create($data);
        return $this->sendResponse($product,'Product Created Successfully!',201);
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $product = Product::with('category')->find($id);

        return $product ? $this->sendResponse($product, 'Product retrieved Successfully!', 200) : $this->sendError('Product not found.');
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        return response([
            'data' => Product::with('category')->find($id)
        ]);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(ProductRequest $request, $id)
    {
        $product = Product::find($id);
        if($product){
            $product->update($request->validated());
        }
        return $product ? $this->sendResponse($product, 'Product Updated Successfully!!', 200) : $this->sendError('Product not found.');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {

        $product = Product::find($id);
        if ($product) {
            $product->delete();
        }

        return $product ? $this->sendResponse([], 'Product Deleted Successfully!!', 200) : $this->sendError('Product not found.');
    }

    public function search($key)
    {
        $products = Product::with('category')->where('name','like',"%$key%")->get();

        return $products ? $this->sendResponse($products, 'Product retrieved Successfully!', 200) : $this->sendError('Product not found.');
    }
}

You may noticed that I have called sendResponse() and sendError() methods in these controller but I am not define this two methods anywhere. OK,don’t worry paste bellows code in your main controller.

<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;

class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    public function sendResponse($result, $message,$code = 200)
    {
        $response = [
            'success' => true,
            'message' => $message,
            'data'    => $result,
        ];


        return response()->json($response, $code);
    }


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

Ok.Our api is almost run. Now time to check our in api in postman.

Make sure in details api we will use following headers as listed bellow:

'headers' => [

    'Accept' => 'application/json',

    'Authorization' => 'Bearer '.$accessToken,

]

Now test those all api in your postman. 

Register API

Request: POST

API: http://localhost:8000/api/register


Login API

Request: POST

API: http://localhost:8000/api/login

Product List API

Request: GET

API: http://localhost:8000/api/products

Header: Bearer Token

Product Create API

Request: Post

API: http://localhost:8000/api/products

Header: Bearer Token

Product Show API

Request: Get

API: http://localhost:8000/api/products/{id}

Header: Bearer Token

Product Update API

Request: Put

API: http://localhost:8000/api/products/{id}

Header: Bearer Token


Product Delete API

Request: Delete

API: http://localhost:8000/api/products/{id}

Header: Bearer Token


Product Search API

Request: GET

API: http://localhost:8000/api/products/search/{key}

Header: Bearer Token

Hope this Laravel sanctum tutorial will help you.


Spread the love
  • 8
  •  
  •  
  •  
  •  
  •  
  •  
    8
    Shares
  • 8
    Shares

About Anisur Rahman Shahin

Hello. My name is Shahin. I'm a tech enthusiast guy. Personally, I’m Optimistic and always in hurry kinda person. I'm a freelance web developer. I am working at Zakir Soft as Laravel Developer. My Portfolio website: https://devshahin.com/

View all posts by Anisur Rahman Shahin →

2 Comments on “Laravel 8 API CRUD with Authentication using Sanctum”

Leave a Reply

Your email address will not be published. Required fields are marked *