Laravel 9 JWT API Authentication Tutorial User Login Signup Example

Using Laravel 9 JWT Authentication Tutorial, we will learn how to Build REST API in Laravel application using JWT Token (JSON Web Token) from scratch. To protect & secure user authentication REST API in Laravel, we will use tymondesigns/jwt-auth a third-party jwt-auth library.

In this tutorial, we will create a login, register, user details, logout (signout) and full crud operation with jwt authentication in laravel app. You can use laravel jwt authentication api example in laravel 5, laravel 6, laravel 7, laravel 8 or laravel 9 apps.

What is JSON Web Token?

JSON Web Token (JWT) is an open standard (RFC 7519), and it represents a compact and self-contained method for securely transmitting information between parties as a JSON object. Digital signature makes the data transmission via JWT trusted and verified. JWTs built upon the secret HMAC algorithm or a public/private key pair using RSA or ECDSA.

Why is JWT Required?

JWT is used for Authorization and information exchange between server and client. It authenticates the incoming request and provides an additional security layer to REST API, which is best for security purposes.

The Structure of JWT

JWT is composed of 5 separate parts encoded in Base64.

  • Deserialized
  • Header
  • Payload
  • Serialized
  • Signature

Laravel JWT API Authentication Example Tutorial

Follow the following steps to implement JWT API authentication in laravel application;

  • Step 1: Download Laravel App
  • Step 2: Connect Database to App
  • Step 3: Run Migration Command
  • Step 4: Install & Configure JWT Package
  • Step 5: Configure User Model
  • Step 6: Configure Auth guard
  • Step 7: Create Authentication Controller
  • Step 8: Add Authentication Routes
  • Step 9: Test Laravel JWT Authentication API using Postman

Download Laravel App

First run following command to install a fresh Laravel app.

composer create-project laravel/laravel laravel-jwt-auth --prefer-dist

Connect Database to App

Now add the database name, user name, and password inside the .env file.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=

Run Migration Command

In this step, we will learn how to register a user table in MySQL database. Laravel fresh installation offers a default user table that we can register into the database using migration.

php artisan migrate

The above command has created a users table inside the database.

Install & Configure JWT Package

Install third party jwt-auth package. You can execute the following command to do so: 

composer require tymon/jwt-auth

Open config/app.php file and update the providers and aliases array.

'providers' => [
    ....
    ....
    Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
],
'aliases' => [
    ....
    'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
    'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,
    ....
],

Now we need to publish the package‚Äôs configuration, following command copy JWT Auth files from vendor folder to config/jwt.php file.

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

For handling the token encryption, generate a secret key by executing the following command.

php artisan jwt:secret

We have successfully generated the JWT Secret key, and you can check this key inside the .env file.

JWT_SECRET=oXVnyMJcrCdQlBSfBtfpSY7ddfF9A7xe2G2tMDrCjyYqke6jDtoyPIIC3PrNb

Configure User Model

Laravel comes with a pre-defined User model, now we implement the jwt-auth package in a user model.

Define Tymon\JWTAuth\Contracts\JWTSubject contract before the User model. This method wants you to define the two methods:

  • getJWTIdentifier(): Get the identifier that will be stored in the subject claim of the JWT.
  • getJWTCustomClaims(): Return a key value array, containing any custom claims to be added to the JWT.

Open the app/Models/User.php file and replace the following code with the existing code.

<?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 Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject
{
    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',
    ];

    /**
     * Get the identifier that will be stored in the subject claim of the JWT.
     *
     * @return mixed
     */
    public function getJWTIdentifier() {
        return $this->getKey();
    }
    /**
     * Return a key value array, containing any custom claims to be added to the JWT.
     *
     * @return array
     */
    public function getJWTCustomClaims() {
        return [];
    }
}

Configure Auth guard

Laravel guard uses the session driver to protect the guards. However, we set the defaults guard to api, and the api guards is ordered to use jwt driver

Place the following code in config/auth.php file.

<?php
return [
    'defaults' => [
        'guard' => 'api',
        'passwords' => 'users',
    ],

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'jwt',
            'provider' => 'users',
            'hash' => false,
        ],
    ],

Create Authentication Controller

In this step, you will create a JWT AuthController controller. Use the below command and create a controller :

php artisan make:controller Api/AuthController

Place the following code inside the app/Http/Controllers/Api/AuthController.php file.

<?php

namespace App\Http\Controllers\Api;

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

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

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

        $requestData['password'] = Hash::make($requestData['password']);

        $user = User::create($requestData);

        return response([ 'status' => true, 'message' => 'User successfully register.', 'user' => $user ], 200);
    }

    /**
     * Get a JWT via given credentials.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(Request $request)
    {
    	$validator = Validator::make($request->all(), [
            'email' => 'required|email',
            'password' => 'required|string|min:6',
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 422);
        }

        if (! $token = auth()->attempt($validator->validated())) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        return $this->createNewToken($token);
    }
    /**
     * Log the user out (Invalidate the token).
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout()
    {
        auth()->logout();
        return response()->json(['message' => 'User successfully signed out']);
    }
    /**
     * Refresh a token.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh()
    {
        return $this->createNewToken(auth()->refresh());
    }
    /**
     * Get the authenticated User.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function userProfile()
    {
        return response()->json(auth()->user());
    }
    /**
     * Get the token array structure.
     *
     * @param  string $token
     *
     * @return \Illuminate\Http\JsonResponse
     */
    protected function createNewToken($token)
    {
        return response()->json([
            'access_token' => $token,
            'token_type' => 'Bearer',
            'expires_in' => auth('api')->factory()->getTTL() * 60,
            'user' => auth()->user()
        ]);
    }
}

Add Authentication Routes

We need to add authentication routes in routes/api.php.

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
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 within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

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

Route::middleware('auth:api')->group(function () {
    Route::get('user-profile', [AuthController::class, 'userProfile']);
    Route::post('refresh', [AuthController::class, 'refresh']);
    Route::post('logout', [AuthController::class, 'logout']);
});

Test Laravel JWT Authentication API using Postman

Start the laravel application with following command:

php artisan serve

User Registration API in Laravel:

User Login API in Laravel:

Laravel User profile API:

JWT Refresh Token Api:

JWT Logout Api:

ss

Leave a Comment