chantouch/laravel-jwt-redis

This package allows JWT-authenticated users to be stored and management in Redis with their roles, permissions, statuses and anything you want.

v3.2.1 2024-04-04 11:17 UTC

This package is auto-updated.

Last update: 2024-05-04 11:28:09 UTC


README

This package allows JWT-authenticated users to be stored and management in Redis with their roles, permissions, statuses and anything you want.

This package is originally forked from sametsahindogan/laravel-jwtredis

68747470733a2f2f63646e2e61757468302e636f6d2f626c6f672f6a7774616c676f732f6c6f676f2e706e67 68747470733a2f2f63646e342e69636f6e66696e6465722e636f6d2f646174612f69636f6e732f72656469732d322f313435312f556e7469746c65642d322d3531322e706e67

Also, this package has an observer for listening and updating to your user model on Redis. This observer is triggered when you assign roles & permissions to user, or update and delete to your user model.

Requirements

This package works with together php-open-source-saver/jwt-auth and spatie/laravel-permission package under the hood.

# Make sure to install and configure these dependencies. You must publish, migrate etc. all packages. #

Installation

composer require chantouch/laravel-jwt-redis

Once this has finished, you will need to add&change these values in .env file:

CACHE_DRIVER=redis
REDIS_CLIENT=predis

Next, you will need to change the guards and providers arrays in your config/auth.php config as follows:

<?php
return [
'guards' => [
        'api' => [
            'driver' => 'jwt_redis',
            'provider' => 'users'
        ],
    ],

'providers' => [
        'users' => [
            'driver' => 'jwt_redis_user',
            'model' =>  App\Models\User::class, /* Your User Model */
        ],
    ],
];

This package uses auto-discovery to register the service provider, but if you'd rather do it manually, the service provider is: add to providers array in your config/app.php config as follows:

Chantouch\JWTRedis\JWTRedisServiceProvider::class,

You will want to publish the config using the following command:

php artisan vendor:publish --provider='Chantouch\JWTRedis\JWTRedisServiceProvider'

Configurations

When everything is done, remember to add this Trait to your user model if you are going to use with spatie/laravel-permission.

use JWTRedisHasRoles;

When everything is done, remember to add this Trait to your user model, if you are not use with laravel-permission.

use JWTRedis;

You need to add $routeMiddleware array in app/Http/Kernel.php

<?php
return [
    'auth'               => \Chantouch\JWTRedis\Http\Middleware\Authenticate::class,
    'refreshable'        => \Chantouch\JWTRedis\Http\Middleware\Refreshable::class,
    'role'               => \Chantouch\JWTRedis\Http\Middleware\RoleMiddleware::class, // Optional
    'permission'         => \Chantouch\JWTRedis\Http\Middleware\PermissionMiddleware::class, // Optional
    'role_or_permission' => \Chantouch\JWTRedis\Http\Middleware\RoleOrPermissionMiddleware::class, // Optional
];

Usage

You do not have any instructions for use. This package only affects the background, functions in an almost identical way to Laravel session authentication, with a few exceptions. All you have to do is change your middleware.(I mention this below) You can use Laravel's Auth facade, Php saver's JWTAuth facade and all spatie/laravel-permission package methods as usual.

  • For user authentication by token;
    (Use this middleware if the user's identity is not important. This middleware only checks if Token is valid. Doesn't send any query to any database.)
Route::get("/example", "ExampleController@example")->middleware('auth');
  • To check user authorization, you need to this one of these middlewares;
    ( Use this middleware if the user's identity is important. This middlewares fetch user from Redis and mark as authorized to Laravel's Request object. And you will reach all default Auth facade's methods you want. Just call Laravel's Auth facades.)
Route::get("/example", "ExampleController@example")->middleware('role:admin|user');
Route::get("/example", "ExampleController@example")->middleware('permissions:get-user|set-user');
Route::get("/example", "ExampleController@example")->middleware('role_or_permission:admin|get-user');
  • To refresh the token, you can add the refreshable middleware to the required route. You don't need to take any action on the controller of this route;
    (Also this middleware can refresh user from Redis if necessary.)
Route::get("/example", "ExampleController@example")->middleware('refreshable');

If you want to do different things, you can override those mentioned middlewares.

After using it as above, every authorization you made in your application, such as Auth::user() or $user->can('permission'), is always checked from Redis, not from the database.

Options

You can customize some options in that package. Check config/jwt-redis.php file.

  • User Model
<?php
return [
    /*
    |--------------------------------------------------------------------------
    | Your User Model
    |--------------------------------------------------------------------------
    |
    | You can set specific user model.
    |
    */
    'user_model' => \App\Models\User::class,
];
  • Observer
<?php
return [
     /*
     |--------------------------------------------------------------------------
     | JWTRedis User Model Observer
     |--------------------------------------------------------------------------
     |
     | This observer class, listening to all events on your user model. Is triggered
     | when you assign roles & permissions to user, or update and delete to
     | your user model.
     |
     */
    'observer' => Chantouch\JWTRedis\Observers\UserRedisObserver::class,
];
  • Events Queue
<?php
return [
    /*
    |--------------------------------------------------------------------------
    | Observer Events Are Queued
    |--------------------------------------------------------------------------
    |
    | If this option is true, model's events are processed as a job on queue.
    |
    | * ~ Remember to run Queue Worker if this option is true. ~ *
    |
    */
    'observer_events_queue' => true,
];
  • Cache Time
<?php
return [
    /*
    |--------------------------------------------------------------------------
    | Cache on Redis up to jwt_ttl value.
    |--------------------------------------------------------------------------
    |
    | If it's option is true, user stored in Redis up to jwt_ttl value time.
    |
    */
    'redis_ttl_jwt' => true,

    /*
    |--------------------------------------------------------------------------
    | Cache on Redis up to specific time
    |--------------------------------------------------------------------------
    |
    | If you don't want to store user in Redis until JWT expire time, 
    | you can set this value as minute.
    |
    */
    'redis_ttl' => 60,
];
  • Cache Prefix
<?php
return [
    /*
    |--------------------------------------------------------------------------
    | Cache Prefix
    |--------------------------------------------------------------------------
    |
    | If it's user id is 1, this user stored in Redis as auth_1.
    |
    */
    'redis_auth_prefix' => 'auth_',
];
  • Banned User Check
<?php
return [
    /*
    |--------------------------------------------------------------------------
    | Banned User Checking
    |--------------------------------------------------------------------------
    |
    | If the check_banned_user option is true, that users cannot access
    | the application.
    |
    */
    'check_banned_user' => false,

    /*
    |--------------------------------------------------------------------------
    | Status Column For Banned User Checking
    |--------------------------------------------------------------------------
    |
    | You can set your specific column name of your user model.
    |
    */
    'status_column_title' => 'status',


    /*
    |--------------------------------------------------------------------------
    | Restricted statuses For Banned User Checking
    |--------------------------------------------------------------------------
    |
    | If the user has one of these statuses and trying to reach your application,
    | JWTRedis throws AccountBlockedException.
    | You can set the message (check it an error array) that will return in this
    | exception.
    |
    */
    'banned_statuses' => [
        'banned',
        'deactivate'
    ],
];
  • Relation Caching
<?php
return [
    /*
    |--------------------------------------------------------------------------
    | Cache This Relations When a User Has Authenticated
    |--------------------------------------------------------------------------
    |
    | You can add this array to your own relations, anything you want to store
    | in Redis. We recommend caching only roles and permissions here as much as
    | possible.
    |
    */
    'cache_relations' => [
        'roles.permissions',
        'permissions'
    ],
];
  • Customize Exceptions
<?php
return [
    /*
    |--------------------------------------------------------------------------
    | Customize All Exception Messages and Codes
    |--------------------------------------------------------------------------
    |
    | You can customize error code,message, title for your application.
    |
    */
    'errors' => [
       'TokenNotProvidedException' => [
           'title' => 'Your custom title',
           'message' => 'Your custom error message.',
           'code' => 99999
       ]
    ],
];

Example Project

Here is an example using laravel-jwt-redis. You can examine in detail.

Performance Improvements Tips

This package requirement the predis package by default.

You may install the PhpRedis PHP extension via PECL. The extension is more complex to install but may yield better performance for applications that make heavy use of Redis. Predis is the alternative for PhpRedis on pure PHP and does not require any additional C extension by default.

"PhpRedis is faster about x6 times. Using binary serializer reduces stored data size about 3x times. If Redis installed on separate machines, reducing network traffic is a very significant speedup."

In my opinion, using PhpRedis and serializer as igbinary (Lodash package it provides this for Laravel.) in production environment gives a great performance.

You can review this article for performance comparison PhpRedis vs. Predis.

License

MIT © Sek Chantouch