RESTful API development using Laravel is quite easy. Laravel provides built-in support for API development using Laravel Passport and a rich ecosystem with tons of packages makes development a breeze. Here we are going to use JWT for API authentication. JWT stands for JSON Web Tokens. You can read more about JWT here.
Getting Started
Let’s get started by installing a fresh Laravel application.
composer create-project --prefer-dist laravel/laravel multi-jwt-auth
For using JWT in laravel there is a popular package called jwt-auth created by Sean Tymon. Let’s install that package also.
composer require tymon/jwt-auth 1.0.*
Note: This article is only for Laravel version > 5.4 . You can read the full documentation here
Next, publish the config file using the command
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
This will publish a config file config/jwt.php that allows you to configure the basics of this package.
Now we need to set a secret key for the encryption and decryption of JWT tokens. For that run the below artisan command.
php artisan jwt:secret
This will update your .env file with something like JWT_SECRET=foobar
The Use Cases
We have 3 types of users.
-
Admins
-
Subadmins
-
Users (Normal users)
Let’s create the migrations.
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
});
Schema::create('admins', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
});
Schema::create('subadmins', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
});
Now run the migrations.
php artisan migrate
Create corresponding models.
<?php | |
namespace App; | |
use Tymon\JWTAuth\Contracts\JWTSubject; | |
use Illuminate\Notifications\Notifiable; | |
use Illuminate\Contracts\Auth\MustVerifyEmail; | |
use Illuminate\Foundation\Auth\User as Authenticatable; | |
class User extends Authenticatable implements JWTSubject | |
{ | |
use Notifiable; | |
/** | |
* The attributes that are mass assignable. | |
* | |
* @var array | |
*/ | |
protected $fillable = [ | |
'name', 'email', 'password', | |
]; | |
/** | |
* The attributes that should be hidden for arrays. | |
* | |
* @var array | |
*/ | |
protected $hidden = [ | |
'password', 'remember_token', | |
]; | |
/** | |
* 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 []; | |
} | |
} |
Note: Be sure to implement the JWTSubject contract.
Configuring the Auth Guard
jwt-auth works by extending laravel’s auth system. So we need to configure the auth guards.
Open config/auth.php and add these guards.
'guards' => [
'admins' => [
'driver' => 'jwt',
'provider' => 'admins',
],
'subadmins' => [
'driver' => 'jwt',
'provider' => 'subadmins',
],
'users' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
Now let’s configure the provider details. Add these to the providers section.
'providers' => [
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
'subadmins' => [
'driver' => 'eloquent',
'model' => App\Subadmin::class,
],
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
],
What is this guards Really? 😇
So let’s understand what these configurations imply.
Laravel uses guards for authentication. They define how the system should store and retrieve information about your users. We have defined 3 guards admins, subadmins, and users. Each guard has a driver and a model. The driver config tells the guard to use which method to authenticate users (usually session or api). The provider config indicates to which model the user is authenticated against and the driver used for the database connection. This is configured in the providers section.
You can also add more guards if you have more user hierarchies. If you need to know more about guards check out this blog.
Now let's configure the jwt settings. Open config/jwt.php and set the lock_user property to true.
'lock_subject' => true,
What this does is it instruct jwt to check if the user is authenticated against the correct table. This is done by adding a hash value of the table name to the generated token.
Now let’s create a custom middleware to instruct laravel to use the correct guard per route. Run the below artisan command to create a middleware.
php artisan make:middleware AssignGuard
<?php | |
namespace App\Http\Middleware; | |
use Closure; | |
class AssignGuard | |
{ | |
/** | |
* Handle an incoming request. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @param \Closure $next | |
* @return mixed | |
*/ | |
public function handle($request, Closure $next, $guard = null) | |
{ | |
if($guard != null) | |
auth()->shouldUse($guard); | |
return $next($request); | |
} | |
} |
In order the middleware to work, we need to register it. For that, go to app/Http/Kernel.php and add the following to the $routeMiddleware array.
'assign.guard' => \App\Http\Middleware\AssignGuard::class,
Now add the middleware to the routes.
<?php | |
use Illuminate\Http\Request; | |
/* | |
|-------------------------------------------------------------------------- | |
| 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::group(['prefix' => 'admin','middleware' => ['assign.guard:admins','jwt.auth']],function () | |
{ | |
Route::get('/demo','AdminController@demo'); | |
}); | |
Route::group(['prefix' => 'subadmin','middleware' => ['assign.guard:subadmins','jwt.auth']],function () | |
{ | |
Route::get('/demo','SubadminController@demo'); | |
}); | |
Route::group(['prefix' => 'user','middleware' => ['assign.guard:admins','jwt.auth']],function () | |
{ | |
Route::get('/demo','UserController@demo'); | |
}); |
And that’s it. We have implemented multi-user authentication using jwt. If you have any queries feel free to ask in the comments section. Thank you.