Laravel Passport: A comprehensive guide in Laravel 10

Laravel Passport

Introduction:

Laravel Passport is a powerful authentication and API token management package that seamlessly integrates with Laravel applications, allowing developers to build secure APIs quickly and efficiently. In this tutorial, we’ll guide you through the process of creating a Laravel project, setting up dependencies, creating controllers, migrations, routes, and more. By the end of this tutorial, you’ll have a solid foundation for building secure APIs using Laravel Passport.

Step 1: Create a New Laravel Project

Let’s start by creating a new Laravel project using Composer. Open your terminal and run the following command:

composer create-project --prefer-dist laravel/laravel Laravel-Passport

Step 2: Install and Configure Laravel Passport

Navigate to your project directory and install Laravel Passport using Composer:

composer require laravel/passport

or if you getting any error try this command also:

composer require laravel/passport -w

Next, publish the Passport configuration files and run the migrations:

php artisan vendor:publish --tag=passport-config
php artisan migrate

Generate the encryption keys needed for Passport:

php artisan passport:install

Step 3: Create API Controllers

Create the necessary controllers for authentication and managing items:

php artisan make:controller API/AuthController
php artisan make:controller ItemController

Step 4: Define API Routes

Open the routes/api.php file and define the API routes for authentication and items:

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ItemController;
use App\Http\Controllers\API\AuthController;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "api" middleware group. Make something great!
|
*/

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});


// Registration Route
Route::post('register', [AuthController::class, 'register']);

// Login Route
Route::post('login', [AuthController::class, 'login']);

// Logout Route
Route::middleware('auth:api')->post('logout', [AuthController::class, 'logout']);

Route::controller(AuthController::class)->group(function(){
    Route::get('user','user');
    Route::post('refresh','refresh');
})->middleware('auth:api');

Route::group(['middleware' => ['web','auth:api']], function()
{
    Route::apiResource('items', ItemController::class);
});

Step 5: Create Item Migration and Model

Generate a migration and model for managing items:

php artisan make:model Item -m
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Item extends Model
{
    use HasFactory;
    protected $fillable = [
        'name',
        'description',
        'price',
    ];

}

User Model:

<?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;
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',
        'password' => 'hashed',
    ];
}

Run the following command to create a migration for the items table:

php artisan make:migration create_items_table

Open the generated migration file in a code editor. In the up method, define the columns you want in the items table. For example:

public function up()
{
    Schema::create('items', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->text('description')->nullable();
        $table->integer('price');
        $table->timestamps();
    });
}

Edit the migration file to define the items table structure and run the migration:

php artisan migrate

Step 6: Implement Controllers

In the AuthController, implement authentication methods like registration, login, and logout. In the ItemController, implement CRUD operations for managing items.

<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use Carbon\Carbon;
use App\Models\User;

class AuthController extends Controller
{
    public function register(Request $request)
    {
        // Validate the incoming request data
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:6|confirmed',
        ]);

        if ($validator->fails()) {
            return response(['errors' => $validator->errors()], 422);
        }

        // Create a new user record
        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($request->password),
        ]);

        // Generate the access token for the newly registered user
        $tokenResult = $user->createToken('Personal Access Token');
        $token = $tokenResult->token;

        // Optionally, set token expiration time (default is 1 year)
        $token->expires_at = Carbon::now()->addYear();
        $token->save();

        // Return the user and access token
        return response([
            'user' => $user,
            'access_token' => $tokenResult->accessToken,
            'token_type' => 'Bearer',
            'expires_at' => Carbon::parse($token->expires_at)->toDateTimeString(),
        ], 200);
    }

    public function login(Request $request)
    {
        // Validate the incoming request data
        $validator = Validator::make($request->all(), [
            'email' => 'required|string|email',
            'password' => 'required|string',
        ]);

        if ($validator->fails()) {
            return response(['errors' => $validator->errors()], 422);
        }

        // Check if the provided credentials are valid
        if (!Auth::attempt(['email' => $request->email, 'password' => $request->password])) {
            return response(['error' => 'Unauthorized'], 401);
        }

        // Get the authenticated user
        $user = $request->user();

        // Generate the access token for the authenticated user
        $tokenResult = $user->createToken('Personal Access Token');
        $token = $tokenResult->token;

        // Optionally, set token expiration time (default is 1 year)
        $token->expires_at = Carbon::now()->addYear();
        $token->save();

        // Return the user and access token
        return response([
            'user' => $user,
            'access_token' => $tokenResult->accessToken,
            'token_type' => 'Bearer',
            'expires_at' => Carbon::parse($token->expires_at)->toDateTimeString(),
        ], 200);
    }

    public function logout(Request $request)
    {
        // Revoke the user's access token
        if (Auth::guard('api')->check()) {
            $request->user()->token()->revoke();
            // Return a success message
            return response(['message' => 'Logged out successfully'], 200);
        }
        return Response(['data' => 'Unauthorized'],401);
    }

    public function refresh(Request $request)
    {
        // Get the user's current access token
        $currentToken = $request->user()->token();

        // Revoke the current access token
        $currentToken->revoke();

        // Generate a new access token
        $newTokenResult = $request->user()->createToken('Personal Access Token');
        $newToken = $newTokenResult->token;

        // Optionally, set token expiration time (default is 1 year)
        $newToken->expires_at = Carbon::now()->addYear();
        $newToken->save();

        // Return the new access token
        return response([
            'access_token' => $newTokenResult->accessToken,
            'token_type' => 'Bearer',
            'expires_at' => Carbon::parse($newToken->expires_at)->toDateTimeString(),
        ], 200);
    }

    public function user(Request $request)
    {
        if (Auth::guard('api')->check()) {
            $user = Auth::guard('api')->user();
            return Response(['data' => $user], 200);
        }
        return Response(['data' => 'Unauthorized'], 401);
    }
}

ItemController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Item;

class ItemController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index()
    {
        $items = Item::all();
        return response(['data' => $items,], 200);
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'description' => 'nullable|string',
            'price' => 'required|integer',
        ]);

        $item = Item::create($request->all());
        return response()->json($item, 201);
    }

    /**
     * Display the specified resource.
     */
    public function show(Item $item)
    {
        return response()->json($item);
    }

    /**
     * Update the specified resource in storage.
     */
 
     public function update(Request $request, Item $item)
     {
         $request->validate([
             'name' => 'sometimes|required|string|max:255',
             'description' => 'nullable|string',
             'price' => 'sometimes|required|integer',
         ]);
 
         $item->update($request->all());
         return response()->json($item);
     }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(Item $item)
    {
        $item->delete();
        return response()->json(null, 204);
    }  
}

Step 7: Configure Middleware and Guards

In config/auth.php, set up the api guard to use Passport’s token driver:

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

Step 8: Testing the API

With the API controllers, routes, and middleware configured, you can start testing the API endpoints using tools like Postman. Use /api/register to register a new user, /api/login to obtain a token, and /api/items for managing items.

Register API:

Laravel Passport

Login API:

Laravel Passport

Get User API:

Laravel Passport

Logout API:

Laravel Passport

Conclusion:

Laravel Passport simplifies the process of securing APIs by providing a robust authentication and token management system. In this tutorial, we covered the steps to create a Laravel project, install and configure Passport, create API controllers and routes, set up migrations and models, and implement authentication and CRUD operations. With this foundation, you’re well-equipped to build secure and feature-rich APIs using Laravel Passport.


Our Recommendation

Avatar of Akhand Pratap Singh

Akhand Pratap Singh

Greetings and a warm welcome to my website! I am Akhand Pratap Singh, a dedicated professional web developer and passionate blogger.

Related Post

Leave a Comment





Newsletter

Subscribe for latest updates

We don't spam.

Loading

Categories