REST API Authentication using Sanctum Example Laravel 10

https://ahtesham.me/storage/posts/September2023/BTEscC4HKqWPfEpZoOji.jpg

In this tutorial, we’ll learn how to create a RESTful API using Laravel 10 and Laravel Sanctum. We’ll also explore how to test CRUD operations (create, read, update, delete) on RESTful APIs with Sanctum authentication in Laravel 10. This is a simple example of working with Laravel 10 Sanctum.

Throughout this tutorial, you’ll discover how to build APIs in Laravel with the help of the Laravel Sanctum package. Sanctum authenticates incoming HTTP requests by checking the Authorization header, which contains a valid API token. It efficiently manages user API tokens by storing them in a single database table.

 

Step 1: Download Laravel

Let us begin the tutorial by installing a new laravel application. if you have already created the project, then skip following step.

composer create-project laravel/laravel example-app

 

Step 2: Use Sanctum

In this step we need to install sanctum via the Composer package manager, so one your terminal and fire bellow command:

composer require laravel/sanctum

After successfully install package, we need to publish configuration file with following command:

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:

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

 

Step 3: Sanctum Configuration

In this step, we have to configuration on three place model, service provider and auth config file. So you have to just following change on that file.

In model we added HasApiTokens class of Sanctum,

In auth.php, we added api auth configuration.

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

Read More : Laravel 10 Get Current Logged in User Data Example

 

Step 4: Add Post Table and Model

next, we require to create migration for posts table using Laravel 10 php artisan command, so first fire bellow command:

php artisan make:migration create_posts_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 posts table.

<?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()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('body');
            $table->timestamps();
        });
    }
  
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
};

After create migration we need to run above migration by following command:

php artisan migrate

After create “posts” table you should create Post model for posts, so first create file in this path app/Models/Post.php and put bellow content in item.php file:

app/Models/Post.php

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

 

Step 5: Add API Routes

In this step, we will create api routes for login, register and posts rest api. So, let’s add new route on that 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\PostController;
  
/*
|--------------------------------------------------------------------------
| 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('posts', PostController::class);
});

 

Step 6: Add Controller Files

For the next step, we’ll create three new controllers: BaseController, PostController, and RegisterController. To keep our API controllers organized, we’ll create a new folder named “API” within the Controllers directory. Here’s how to create these controllers:

php artisan make:controller BaseController

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);
    }
}
php artisan make:controller 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;
   
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',
        ]);
   
        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']);
        } 
    }
}
php artisan make:controller PostController

app/Http/Controllers/API/PostController.php

<?php
   
namespace App\Http\Controllers\API;
   
use Illuminate\Http\Request;
use App\Http\Controllers\API\BaseController as BaseController;
use App\Http\Resources\PostResource;
use App\Models\Post;
use Validator;
   
class PostController extends BaseController
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $posts = Post::all();
    
        return $this->sendResponse(PostResource::collection($posts), 'Post 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, [
            'title' => 'required',
            'body' => 'required'
        ]);
   
        if($validator->fails()){
            return $this->sendError('Validation Error.', $validator->errors());       
        }
   
        $post = Post::create($input);
   
        return $this->sendResponse(new PostResource($post), 'Post created successfully.');
    } 
   
    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $post = Post::find($id);
  
        if (is_null($post)) {
            return $this->sendError('Post not found.');
        }
   
        return $this->sendResponse(new PostResource($post), 'Post 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, Post $post)
    {
        $input = $request->all();
   
        $validator = Validator::make($input, [
            'title' => 'required',
            'body' => 'required'
        ]);
   
        if($validator->fails()){
            return $this->sendError('Validation Error.', $validator->errors());       
        }
   
        $post->title = $input['title'];
        $post->body = $input['body'];
        $post->save();
   
        return $this->sendResponse(new PostResource($post), 'Post updated successfully.');
    }
   
    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Post $post)
    {
        $post->delete();
   
        return $this->sendResponse([], 'Post deleted successfully.');
    }
}

 

Step 7: Add Eloquent API Resources

Creating API resources in Laravel is indeed an important step for building a REST API. API resources help you define a consistent and customizable response format for your model objects. To create an API resource in Laravel 10, you can use the following command:

php artisan make:resource PostResource

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

app/Http/Resources/PostResource.php

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

 

Run Laravel App:

All steps have been done, now you have to type the given command and hit enter to run the laravel app:

php artisan serve

Now, you have to open web browser, type the given URL and view the app output:

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

 

Here is Routes URL with Verb:

Now simply you can run above listed URL like as bellow screen shot:

1. Register API: Verb:GET, URL:http://localhost:8000/api/register

2. Login API: Verb:GET, URL:http://localhost:8000/api/login

3. Post List API: Verb:GET, URL:http://localhost:8000/api/posts

4. Post Create API: Verb:GET, URL:http://localhost:8000/api/posts

5. Post Show API: Verb:GET, URL:http://localhost:8000/api/posts/{id}

6. Post Update API: Verb:PUT, URL:http://localhost:8000/api/posts/{id}

7. Post Delete API: Verb:DELETE, URL:http://localhost:8000/api/posts/{id}

 

I hope it can help you…

Laravel News Links