Laravel

API Authentication using Laravel Sanctum — Laravel 8

Pinterest LinkedIn Tumblr

Laravel 8 Sanctum provides a simple authentication system for SPAs web Application, mobile applications, and simple, token based APIs. Sanctum also allows each user of your application to generate multiple API tokens for their account.

We have the Laravel Passport package to do the authentication and OAuth processes. But, if you don’t want to use the OAuth feature that Passport offers, then the Laravel Sanctum may be a choice for you.

Step 1: Install Laravel 8

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

Step 2: Laravel Sanctum package.

After installation succeeds, install the Laravel Sanctum package.

composer require laravel/sanctum

Then publish the Sanctum configuration and migration files. The Sanctum configuration file will be placed inside your config directory.

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


we require to get default migration for create new sanctum tables in our database. so let’s run bellow command.

php artisan migrate

Next, we need 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: Sanctum Configuration

One very last thing, your User model needs to use the Laravel\Sanctum\HasApiTokens trait.

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 HasFactory, Notifiable, HasApiTokens;

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'password',
];

/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];

/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}

Step 4: Add Product Table and Model

php artisan make:migration create_products_table

After this command you will find one file in following path database/migrations and you have to put bellow code in your migration file for create products table.

<?php


use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;


class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('detail');
            $table->timestamps();
        });
    }


    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}

Run 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 5: Create API Routes

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::post('register', [RegisterController::class, 'register']);
Route::post('login', [RegisterController::class, 'login']);

Route::post('logout', [RegisterController::class, 'logout']);

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

Step 6: Create Controller Files

in next step, now we have create new controller as BaseController, ProductController and RegisterController, i created new folder “API” in Controllers folder because we will make alone APIs controller, So let’s create both controller:

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;

class RegisterController extends BaseController
{
/**
* Register api
*
* @return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$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)
{
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']);
}
}
// Logout
public function logout()
{
Auth::user()->tokens->each(function($token, $key) {
$token->delete();
});

return response()->json('Successfully logged out');
}
}

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\Product as ProductResource;

class ProductController extends BaseController
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$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)
{
$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)
{
$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)
{
$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)
{
$product->delete();

return $this->sendResponse([], 'Product deleted successfully.');
}
}

Step 7: Create Eloquent API Resources

php artisan make:resource Product

Now there created new file with new folder on following path:

app/Http/Resources/Product.php

<?php
  
namespace App\Http\Resources;
   
use Illuminate\Http\Resources\Json\JsonResource;
   
class Product extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        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'),
        ];
    }
}
php artisan serve

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

'headers' => [

    'Accept' => 'application/json',

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

]

Let’s start working

First, let’s try the registration step.

1) Register API: Method:POST, URL: http://127.0.0.1:8000/api/register

2) Login API: Method:POST, URL: http://127.0.0.1:8000/api/login

3) Logout API: Method:POST, URL: http://127.0.0.1:8000/api/logout with middleware

4) Product Create API: Method:POST, URL:http://127.0.0.1:8000/api/products

5) Product List API: Method:GET, URL:http://127.0.0.1:8000/api/products

6) Product Show API: Method:GET, URL:http://127.0.0.1:8000/api/products/{id}

7) Product Delete API: Method:DELETE, URL:http://127.0.0.1:8000/api/products/{id}

Product Update API: Method:PUT, URL:http://localhost:8000/api/products/{id}

Write A Comment