Laravel 11 REST API with Passport Authentication Tutorial

By Hardik Savani April 16, 2024 Category : Laravel

In this post, I will show you how to create REST API with Passport Authentication in laravel 11 application. We will learn from scratch about APIs, REST APIs, and Laravel Passport, and create an example API as well.

What is API?

An API (application programming interface) is simply a way of communication between two or more computer programs.

APIs are also used for web and mobile application development; therefore, building a REST API is very essential for any web and mobile application developer.

What is Laravel Passport?

Laravel Passport is a tool for adding secure authentication to web applications. It helps developers set up authentication using APIs quickly and easily. Passport generates API tokens that users can use to access protected resources. It simplifies tasks like user registration, login, and managing access permissions. With Passport, developers can focus more on building their applications and less on handling authentication details.

We will use Laravel Passport, an authentication system package for developing simple APIs for SPAs (single-page applications) which are commonly built via React JS, Angular, or Vue JS.

In this example, we will install the Laravel 11 application. Then, we will install the Passport composer package for API authentication. After that, we will create register and login APIs for user authentication. Then, we will create a products REST API, and you must authenticate using a user token. So, let's follow the steps below to complete this example step by step:

laravel 11 rest api using passport

Step for Laravel 11 Passport REST API Authentication Example

  • Step 1: Install Laravel 11
  • Step 2: Install Passport
  • Step 3: Passport Configuration
  • Step 4: Add Product Table and Model
  • Step 5: Create API Routes
  • Step 6: Create Controller Files
  • Step 7: Create Eloquent API Resources
  • Run Laravel App

Follow the below few steps to create a restful API example in the laravel 11 app.

Step 1: Install Laravel 11

This step is not required; however, if you have not created the Laravel app, then you may go ahead and execute the below command:

composer create-project laravel/laravel example-app

Step 2: Install Passport

In Laravel 11, by default, we don't have an api.php route file. So, you just need to run the following command to install passport with api.php file.

php artisan install:api --passport

Step 3: Passport Configuration

In this step, we have to configure three places: the model, the service provider, and the auth config file. So, you just need to follow the changes in those files.

In the model, we added the HasApiTokens class of Passport.

In the auth.php file, we added API auth configuration.

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

config/auth.php

<?php

return [
    .....
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
        ],
    ],
    .....
]

Step 4: Add Product Table and Model

Next, we need to create a migration for the posts table using the Laravel 11 php artisan command, so first, fire the command below:

php artisan make:migration create_products_table

After this command, you will find one file in the following path database/migrations, and you have to put the below code in your migration file to create the products 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(): 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');
    }
};

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

php artisan migrate

After creating the "products" table, you should create a Product model for products. So, first create a file in this path app/Models/Product.php and put the following content in it:

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

In this step, we will create API routes. Laravel provides the api.php file for writing web service routes. So, let's add a new route to 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\ProductController;
 
  
Route::post('register', [RegisterController::class, 'register']);
Route::post('login', [RegisterController::class, 'login']);
     
Route::middleware('auth:api')->group( function () {
    Route::resource('products', ProductController::class);
});

Step 6: Create Controller Files

In the next step, we've created a new controller called BaseController, ProductController, and RegisterController. I created a new folder named "API" in the Controllers folder because we'll have separate controllers for APIs. So, let's create both controllers:

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

Step 7: Create Eloquent API Resources

This is a very important step in creating a REST API in Laravel 11. You can use Eloquent API resources with the API. It will help you to maintain the same response layout of your model object. We used it in the ProductController file. Now, we have to create it using the following command:

php artisan make:resource ProductResource

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

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

Run Laravel App:

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

php artisan serve

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

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

You can download code from git: Download Code from Github

I hope it can help you...

Shares