Laravel 9 Rest API With Passport Authentication Tutorial

Laravel 9 Rest API With Passport Authentication Tutorial

Last Updated: 30 Nov, 2022

Dear friends, greetings. In this tutorial, we will learn How to Create REST APIs using Passport Authentication in Laravel 9. To acheive this, we will be using laravel/passport package. Laravel Passport provides a full OAuth2 server implementation for your laravel application in a matter of minutes.

How to Create Rest API with Passport Authentication in Laravel 9?

Follow the below mentioned step-by-step guidance to learn how to create REST APIs with Passport in laravel 9 application from scratch:

Step 1: Install Fresh Laravel 9 Application
Step 2: Set Up Database Configuration
Step 3: Install and Configure Passport Authentication Package
Step 4: Set Up User Model
Step 5: Set Up Product Model and Migration
Step 6: Create and Set Up Auth Controller
Step 7: Create and Set Up Product Controller
Step 8: Create Auth and Product API Routes
Step 9: Run Laravel Application
Step 10: Test the REST APIs using Postman

Now, we will go through the above given steps one-by-one to and get it done.

Step 1: Install Fresh Laravel 9 Application

First of all, let's install a fresh laravel 9 application. Open your terminal and run the following command:

composer create-project laravel/laravel laravel9app

Step 2: Setup Database Configuration

Next, lets update database configuration in .env file as follows:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel9db
DB_USERNAME=dbusername
DB_PASSWORD=dbpassword

Step 3: Install and Configure Passport Authentication Package

Next, install laravel/passport package through composer to authenticate the apis. To install it, run below command in terminal:

composer require laravel/passport

Once you have successfully install the package, run below command to migrate the passport table in to the database:

php artisan migrate

Next, we need to generate a paasport token keys using below command to provide security to your application:

php artisan passport:install

Next, open app/Providers/AuthServiceProvider.php file and register the registerPolicies() method inside the boot() function, It will evoke the required routes. Copy and paste below code in it:

<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The model to policy mappings for the application.
     *
     * @var array<class-string, class-string>
     */
    protected $policies = [
        'App\Models\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Passport::routes();
    }
}

Next, register the PassportServiceProvider class in providers array inside the config/app.php file:

'providers' => [
    ...
    ...
    ...
    /*
     * Package Service Providers...
     */
    Laravel\Passport\PassportServiceProvider::class,
],

Next, we need to configure driver for the passport. Open config/auth.php file and the changes as follows:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

Step 4: Set Up User Model

Next, we need to set up User model. In fresh installation, laravel comes with a pre-defined User model that is used for authentication purpose. Open App\Models\User.php and copy below code in it:

<?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\Passport\HasApiTokens;

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

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

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

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

Step 5: Set Up Product Model and migration

Next, we have to create Product model and migration using below command:

php artisan make:model Product -m

Above command will create a model file named Product.php and a migration file named database/migrations/*_create_products_table.php. Open the migration file and copy below code in it:

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

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

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

Next, open App\Models\Product.php file and copy below code in it:

<?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<int, string>
     */
    protected $fillable = [
        'name',
        'mrp',
        'price',
        'quantity'
    ];
}

once you are done with model and migration files, let's run the below command to create the tables in MySQL DB:

php artisan migrate

Step 6: Create and Set Up Auth Controller

In this step, we have to create AuthController and need to define neccessary methods and logics. Let's run below command in terminal that will create app/Http/Controllers/AuthController.php file.

php artisan make:controller AuthController

Next, open the app/Http/Controllers/AuthController.php and copy below code in it:

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Validator;
use App\Models\User;

class AuthController extends Controller
{
    /**
     * Register a User.
     * @return \Illuminate\Http\Response
     */
    public function register(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|min:3|max:50',
            'email' => 'required|string|email|max:100|unique:users',
            'password' => 'required|string|confirmed|min:8',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => false,
                'message' => 'Invalid Inputs',
                'error' => $validator->errors()
            ], 401);
        }

        $user = new User();
        $user->name = $request->name;
        $user->email = $request->email;
        $user->password = bcrypt($request->password);
        $user->save();

        $token = $user->createToken('Laravel9PassportAppToken')->accessToken;

        return response()->json([
            'status' => true,
            'message' => 'User successfully registered',
            'user' => $user,
            'token' => $token
        ], 201);
    }

    public function login(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|email',
            'password' => 'required|string|min:8'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => false,
                'message' => 'Invalid Inputs',
                'error' => $validator->errors()
            ], 422);
        }

        if (Auth::attempt(['email'=>$request->email, 'password'=>$request->password])) {
            $user = Auth::user();
            $token = $user->createToken('Laravel9PassportAppToken')->accessToken;
            $minutes = 1440;
            $timestamp = now()->addMinute($minutes);
            $expires_at = date('M d, Y H:i A', strtotime($timestamp));
            return response()->json([
                'status' => true,
                'message' => 'Login successful',
                'access_token' => $token,
                'token_type' => 'bearer',
                'expires_at' => $expires_at
            ], 200);
        } else {
            return response()->json([
                'status' => false,
                'message' => 'Invalid Credentials',
            ], 400);
        }
    }
}

Step 7: Create and Set Up Product Controller

In this step, we have to create ProductController by running below command in terminal that will create app/Http/Controllers/ProductController.php file.

php artisan make:controller ProductController

Next, open the app/Http/Controllers/ProductController.php and copy below code in it:

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Validator;
use App\Models\Product;

class ProductController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $products = Product::all();
        
        return response()->json([
            "status" => true,
            "message" => "Product List",
            "data" => $products
        ]);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $request_data = $request->all();
        
        $validator = Validator::make($request_data, [
            'name' => 'required',
            'mrp' => 'required',
            'price' => 'required',
            'quantity' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => false,
                'message' => 'Invalid Inputs',
                'error' => $validator->errors()
            ]);
        }

        $product = Product::create($request_data);
        
        return response()->json([
            "status" => true,
            "message" => "Product created successfully.",
            "data" => $product
        ]);
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show(Product $product)
    {
        if (is_null($product)) {
            return response()->json([
                'status' => false,
                'message' => 'Product not found'
            ]);
        }

        return response()->json([
            "success" => true,
            "message" => "Product found.",
            "data" => $product
        ]);
    }

    /**
     * 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)
    {
        $request_data = $request->all();
        
        $validator = Validator::make($request_data, [
            'name' => 'required',
            'mrp' => 'required',
            'price' => 'required',
            'quantity' => 'required'
        ]);

        if($validator->fails()){
            return response()->json([
                'status' => false,
                'message' => 'Invalid Inputs',
                'error' => $validator->errors()
            ]);      
        }

        $product->name = $request_data['name'];
        $product->mrp = $request_data['mrp'];
        $product->price = $request_data['price'];
        $product->quantity = $request_data['quantity'];
        $product->save();
        
        return response()->json([
            "status" => true,
            "message" => "Product updated successfully.",
            "data" => $product
        ]);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Product $product)
    {
        $product->delete();
        return response()->json([
            "status" => true,
            "message" => "Product deleted successfully.",
            "data" => $product
        ]);
    }
}

Step 8: Create Auth and Product APIs Routes

In this step, we have to create route for the apis. API routes are stored and served through routes/api.php file. These routes are prfixed with api/ and authentication routes are denoted by auth/. We will be creating a resource route for CRUD operation on Product table.

So, lets open the routes/api.php and copy below given code in it:

<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\AuthController;
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::prefix('auth')->controller(AuthController::class)->group(function () {
    Route::post('register', 'register');
    Route::post('login', 'login');
});
Route::middleware('auth:api')->group(function () {
    Route::resource('products', ProductController::class);
});

Step 9: Run Laravel Application

Great, we are all set. Lets start the application now by using below command in terminal:

php artisan serve

Once development server is started, you can test your application with postman.

Step 10: Test the REST API using Postman

Now, in this step we will use the postman to test our application. Open postman app and in Headers tab, define "Accept": application/json header value. Next, you are ready to go and test the APIs one-by-one.

Test User Registration API

First of all, register a new user using /api/auth/register API. You have to select POST as request method and in the request body select form-data and fill in all the required parameters like name, email, password, etc. Then call the api by clicking on Send button in postman. Please refer the below attached screenshot:

Laravel 9 REST API With Passport Authentication

 

Test User Login API

Next, test the User Login by calling the /api/auth/login API. Select POST as request method and fill in required parameters (email and password) under form-data in request body. On successful call, this API will return a access token along with other details like token type, token expiration time, etc. Please refer the below screenshot:

Laravel 9 REST API With Passport Authentication


Once you have got the API Access Token, you can easily call product CRUD APIs by providing the access token in request header as a field 'Authorization: Bearer Token'.

CRUD APIs on Product Table

Product Create API

Next, create the prodcut by calling /api/products POST API. Please refer the below screenshot:

Laravel 9 REST API With Passport Authentication


Product List API

Next, get the prodcuts by calling /api/products GET API. Please refer the below screenshot:

Laravel 9 REST API With Passport Authentication


Product Detail API

Next, get the particular prodcut by calling /api/products/{id} GET API. Please refer the below screenshot:

Laravel 9 REST API With Passport Authentication


Product Update API

Next, update the prodcut by calling /api/products PUT API. Please refer the below screenshot:

Laravel 9 REST API With Passport Authentication


Product Delete API

Next, delete the prodcut by calling /api/products DELETE API. Please refer the below screenshot:

Laravel 9 REST API With Passport Authentication

 

Dear friends, if you have followed this tutorial step-by-step, I can proudly say that you have successfully learnt how to implement Restful API in Laravel 9 with Passport authentication.

HAPPY LEARNING:)

 

Thank You, Please Share.