Laravel 9 Rest API JWT Authentication Tutorial

Hello Artisan,

In this tymonjwt auth laravel 9 tutorial, I will show you a complete Laravel 9 rest api development tutorial with jwt auth. I will create login, register, and product create read update delete api with jwt auth. After completing the api login, user will able to create the product. We are going to create this system with json web token (jwt auth). 

You know that there are many ways to create rest api authentication, but in this example, I will create Laravel 9 rest api authentication using json web token(jwt auth). In this tutorial, you will learn how to build the rest APIs with jwt (JSON web token) authentication in Laravel 9. As well as I will also show you how to install jwt auth and configure jwt auth in laravel 9 app.

Let's see the step by step guide on laravel 9 jwt authentication tutorial: Let's start building our Rest Api using JWT authentication.

 

Step 1: Install Laravel 

I am going to explain step by step from scratch so, we need to get a fresh Laravel 9 application using below command

composer create-project --prefer-dist laravel/laravel api

 

Step 2: Install  tymondesigns/jwt-auth Package

Now, install the third-party jwtauth package by typing the following command.

composer require tymon/jwt-auth

 

It will install the package in the vendor folder and our composer.json file will be updated. Now go to the config/app.php file and add the following.

config/app.php

'providers' => [
    ....
    'Tymon\JWTAuth\Providers\JWTAuthServiceProvider',
],
'aliases' => [
    ....
    'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
    'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
],

 

To publish the configuration file in Laravel, you need to run the following line of code :

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"

 

Step 3 : Generate JWT Key

JWT tokens will be signed with an encryption key. Run the following command to generate jwt key.

php artisan jwt:generate

 

If you find an error like this after hitting the above command.

ReflectionException : Method Tymon\JWTAuth\Commands\JWTGenerateCommand::handle() does not exist

then open the JWTGenerateCommand.php file and paste the following code, Hope it will work.

vendor/tymon/src/Commands/JWTGenerateCommand.php

public function handle() { 
 $this->fire(); 
}

 

Step 4 : Registering Middleware

JWT auth package comes up with middlewares that we can use. Register auth.jwt middleware in 

app/Http/Kernel.php

protected $routeMiddleware = [
    'auth.jwt' => 'auth.jwt' => 'Tymon\JWTAuth\Middleware\GetUserFromToken',
];

 

This middleware verifies that the user is authenticated by checking the token sent with the request. If the user is not authenticated, the middleware will throw an UnauthorizedHttpException exception.

 

Step 5 : Create Api Routes

Now we need to create our route. paste this following code to this path

routes/api.php 

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ApiController;

Route::post('login', [ApiController::class,'login']);
Route::post('register', [ApiController::class,'register']);
 
Route::group(['middleware' => 'auth.jwt'], function () {
    Route::get('logout', [ApiController::class,'logout']);
    Route::get('user', [ApiController::class,'getAuthUser']);
    Route::get('products', [ApiController::class,'index']);
    Route::get('products/{id}', [ApiController::class,'show']);
    Route::post('products', [ApiController::class,'store']);
    Route::put('products/{id}', [ApiController::class,'update']);
    Route::get('logout', [ApiController::class,'destroy']);
    Route::delete('products/{id}', [ApiController::class,'getAuthUser']);
});

 

Step 5 : Update User Model

Now open the user model and paste the following code to make changes. As we are going to make a product crud system also, so we need to make a relationship between user and product.

namespace App\Models;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];

    public function products()
    {
        return $this->hasMany(Product::class);
    }
}

 

Let’s write the logic for restful API in Laravel using JWT authentication. We need to validate our request data. So run the below command to make a registration request.

php artisan make:request RegisterAuthRequest

 

After running this command just open this file going the following directory and paste the below code.

app/Http/Requests/RegisterAuthRequest.php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class RegisterAuthRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'name' => 'required|string',
            'email' => 'required|email|unique:users',
            'password' => 'required|string|min:6|max:10'
        ];
    }
}

 

Step 6 : Create Controller

Now we have to create our controller. So run the below command

php artisan make:controller ApiController
php artisan make:controller ProductController

 

Now open this ApiController and paste this below code

app/Http/Controllers/ApiController.php

namespace App\Http\Controllers;

use JWTAuth;
use App\User;
use Illuminate\Http\Request;
use App\Http\Requests\RegisterAuthRequest;
use Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpFoundation\Response;

class ApiController extends Controller
{
    public $loginAfterSignUp = true;
 
    public function register(RegisterAuthRequest $request)
    {
        $user = new User();
        $user->name = $request->name;
        $user->email = $request->email;
        $user->password = bcrypt($request->password);
        $user->save();
 
        if ($this->loginAfterSignUp) {
            return $this->login($request);
        }
 
        return response()->json([
            'success' => true,
            'data' => $user
        ], Response::HTTP_OK);
    }
 
    public function login(Request $request)
    {
        $input = $request->only('email', 'password');
        $jwt_token = null;
 
        if (!$jwt_token = JWTAuth::attempt($input)) {
            return response()->json([
                'success' => false,
                'message' => 'Invalid Email or Password',
            ], Response::HTTP_UNAUTHORIZED);
        }
 
        return response()->json([
            'success' => true,
            'token' => $jwt_token,
        ]);
    }
 
    public function logout(Request $request)
    {
        $this->validate($request, [
            'token' => 'required'
        ]);
 
        try {
            JWTAuth::invalidate($request->token);
 
            return response()->json([
                'success' => true,
                'message' => 'User logged out successfully'
            ]);
        } catch (JWTException $exception) {
            return response()->json([
                'success' => false,
                'message' => 'Sorry, the user cannot be logged out'
            ], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }
 
    public function getAuthUser(Request $request)
    {
        $this->validate($request, [
            'token' => 'required'
        ]);
 
        $user = JWTAuth::authenticate($request->token);
 
        return response()->json(['user' => $user]);
    }
}

 

Step 7 : Create Product Model

Now we have to create our product model and migration to test our crud with JSON web token (JWT). So run the below command to create it

php artisan make:model Product -m

 

It will create a new database migration. Open it and paste this code

create_products_table.php in database/migrations

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('products', function (Blueprint $table) {
            $table->id();
            $table->increments('id');
            $table->unsignedInteger('user_id');
            $table->string('name');
            $table->integer('price');
            $table->integer('quantity');
            $table->timestamps();
        });
    }

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

 

Now run migrate command to create product migration then open the Product model

app\Models\Product.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $fillable = [
        'name', 'price', 'quantity'
    ];
}

 

Now go to the ProductController.php file and paste the following code Here we will do all the crud parts for creating and testing the rest API with jwt in laravel.

app/Http/Controllers/ProductController.php

namespace App\Http\Controllers;

use JWTAuth;
use App\Models\Product;
use Illuminate\Http\Request;

class ProductController extends Controller
{
    protected $user;
 
    public function __construct()
    {
        $this->user = JWTAuth::parseToken()->authenticate();
    }
    public function index()
    {
        return $this->user
            ->products()
            ->get(['name', 'price', 'quantity'])
            ->toArray();
    }
    public function show($id)
    {
        $product = $this->user->products()->find($id);
    
        if (!$product) {
            return response()->json([
                'success' => false,
                'message' => 'Sorry, product with id ' . $id . ' cannot be found'
            ], 400);
        }
    
        return $product;
    }

    public function store(Request $request)
    {
        $this->validate($request, [
            'name' => 'required',
            'price' => 'required|integer',
            'quantity' => 'required|integer'
        ]);
    
        $product = new Product();
        $product->name = $request->name;
        $product->price = $request->price;
        $product->quantity = $request->quantity;
    
        if ($this->user->products()->save($product))
            return response()->json([
                'success' => true,
                'product' => $product
            ]);
        else
            return response()->json([
                'success' => false,
                'message' => 'Sorry, product could not be added'
            ], 500);
    }

    public function update(Request $request, $id)
    {
        $product = $this->user->products()->find($id);
    
        if (!$product) {
            return response()->json([
                'success' => false,
                'message' => 'Sorry, product with id ' . $id . ' cannot be found'
            ], 400);
        }
    
        $updated = $product->fill($request->all())
            ->save();
    
        if ($updated) {
            return response()->json([
                'success' => true
            ]);
        } else {
            return response()->json([
                'success' => false,
                'message' => 'Sorry, product could not be updated'
            ], 500);
        }
    }

    public function destroy($id)
    {
        $product = $this->user->products()->find($id);
    
        if (!$product) {
            return response()->json([
                'success' => false,
                'message' => 'Sorry, product with id ' . $id . ' cannot be found'
            ], 400);
        }
    
        if ($product->delete()) {
            return response()->json([
                'success' => true
            ]);
        } else {
            return response()->json([
                'success' => false,
                'message' => 'Product could not be deleted'
            ], 500);
        }
    }
}

 

Now everything is done. We can check it now. So run the below command to start our server and take a tour to test it with the postman.

php artisan serve

 

For testing restful APIs, I will use Postman. Let’s try to check our rest API with JSON web token(jwt) application.

Preview:  Register route

laravel-9-jwt-athentication

 

Preview:  Login route

laravel-9-jwt-athentication

 

Preview:  Logged in user data

Now, we will test the details API, In this API you have to set three headers as listed below:

'headers' => [
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer
]

 

So, make sure the above header, otherwise, you can not get user details.

laravel-9-rest-api-development

 

Preview: Store product route

laravel-9-rest-api-development

 

Preview: Single product route

laravel-9-rest-api-development

 

Preview: All product details route

laravel-9-rest-api-development

 

Preview: Update product route

laravel-9-rest-api-development

 

Preview: Delete product route

laravel-9-rest-api-development

 

Preview: User logout route

laravel-9-rest-api-development

 

Github link : Laravel REST API development with JWT

 

Read also: Laravel 9 Custom Token Based Api Authentication Tutorial

 

Hope it can help you.

 

author-image
Facebook Github
A web enthusiastic, a self-motivated full-stack software engineer from Dhaka, Bangladesh with experience in developing applications using Laravel , React and Vue js