How to implement JWT Authentication.
Effortlessly Implementing it in Fast, Simple Steps.
After you have finished reading my post see my repo: jwt-auth-in-laravel
Table Of Contents
Install
- Install package php-open-source-saver/jwt-auth
composer require php-open-source-saver/jwt-auth
- Run the following command to publish the package config file:
php artisan vendor:publish --provider="PHPOpenSourceSaver\JWTAuth\Providers\LaravelServiceProvider"
- I have included a helper command to generate a key for you:
php artisan jwt:secret
This will update your .env file with something like JWT_SECRET=foobar
It is the key that will be used to sign your tokens. How that happens exactly will depend on the algorithm that you choose to use.
Implementation
The implementation depends if you want to use algorithms of symmetric or asymmetric encryption
⚠️ If you want to implement the JWT authentication with a symmetric algorithm please scroll to code implementation ⚠️
Generate a certificate for asymmetric encryption
For generating certificates the command
php artisan jwt:generate-certs
can be used. The .env file will be updated, to use the newly created certificates.
The command accepts the following parameters.
name | description |
---|---|
force | override existing certificates |
algo | Either rsa or ec |
bits | Key length for rsa |
curve | Curve to be used for ec |
sha | Hashing algorithm |
passphrase | Passphrase for the cert |
dir | Folder to place the certificates |
Examples
Generating a 4096-bit rsa certificate with sha 512
php artisan jwt:generate-certs --force --algo=rsa --bits=4096 --sha=512
Generating an ec certificate with prime256v1-curve and sha 512
php artisan jwt:generate-certs --force --algo=ec --curve=prime256v1 --sha=512
After you have chosen the encryption algorithms with PUBLIC AND PRIVATE KEY.
Your .env file has to look like this:
JWT_PRIVATE_KEY=file://../storage/certs/jwt-ec-4096-private.pem
JWT_PUBLIC_KEY=file://../storage/certs/jwt-ec-4096-public.pem
code implementation
- First You must add in config/auth.php the guard of JWT
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
- Your User model has to look like this:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use HasApiTokens,
HasFactory,
Notifiable;
protected $fillable = [
'name',
'email',
'password',
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
public function getJWTCustomClaims()
{
return [];
}
public function getJWTIdentifier()
{
return $this->getKey();
}
}
- You have to create the routes for the AuthJwtController in your routes/api.php file
use App\Http\Controllers\ApiController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\AuthJwtController;
Route::controller(AuthJwtController::class)->group(function () {
Route::post('login', 'login');
Route::post('refresh', 'refresh');
Route::post('blacklist', 'blacklist');
Route::post('logout', 'logout');
Route::get('get-token/{user_id}', 'getTokenByUser');
});
- You have to add yours private endpoints in the middleware auth:jwt, like this:
Route::controller(ApiController::class)->middleware('auth:api')->group(function () {
Route::get('private-endpoint', 'privateEndopint');
});
- You can configure the time of expiration of the tokens by adding this to the .env file
JWT_TTL=60
You can see more configurations in config/jwt.php file
- Finally, you have to create the AuthJwtController
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
class AuthJwtController extends Controller
{
public function __construct()
{
$this->middleware('auth:api', ['except' => ['login']]);
}
public function login(Request $request): JsonResponse
{
$validate = Validator::make($request->all(), [
'email' => 'required|string|email',
'password' => 'required|string',
]);
if ($validate->fails()) {
return response()->json([
'status' => false,
'error_message' => $validate->errors(),
], 400);
}
$credentials = $request->only('email', 'password');
$token = Auth::guard('api')->attempt($credentials);
if (!$token) {
return response()->json([
'status' => false,
'message' => 'Unauthorized',
], 401);
}
return response()->json([
'status' => true,
'authorisation' => [
'token' => $token,
'type' => 'bearer',
],
]);
}
//if you want use this methods for yourself, add role in your user model and you validate in this methods
public function refresh(): JsonResponse
{
return response()->json([
'status' => true,
'authorisation' => [
'token' => Auth::refresh(true),
'type' => 'bearer',
],
]);
}
public function blackList(): JsonResponse
{
//if you want add to blacklist forever, pass true as parameter
Auth::invalidate();
return response()->json([
'status' => true,
'message' => 'token added to blacklist successfully'
], 200);
}
public function logout(): JsonResponse
{
Auth::logout();
return response()->json([
'status' => true,
'message' => 'logout successfully'
], 200);
}
public function getTokenByUser(Request $request): JsonResponse
{
$validate = Validator::make(['user_id' => $request->user_id], [
'user_id' => 'required',
]);
if ($validate->fails()) {
return response()->json([
'status' => false,
'error_message' => $validate->errors(),
], 400);
}
if (!Auth::tokenById($request->user_id)) {
return response()->json([
'status' => false,
'error_message' => "There aren't Token with this user id",
], 400);
}
return response()->json([
'status' => true,
'token' => Auth::tokenById($request->user_id)
]);
}
}
After you have completed the steps, You can use your JWT authentication in your Laravel app.
let's start to test the JWT authentication.
POSTMAN
When we are testing our private endpoints that have a middleware with JWT we should hit the /login endpoint with the credentials copy the token and then embed it in the baren token of our private endpoint that has the JWT middleware.
Don't worry about that, follow the following steps to automate a pre-request that sets the JWT token in the bearer token to our private endpoint.
- First you must import the collection into your Postman app
- Import the environment in your Postman app
- You have to select the environment imported
- You have to create an endpoint inside of the collection imported and put the authorization Bearer Token like this:
Do you not know how to import environments and collections on Postman?
Don't worry, learn about that in the following links:
Top comments (0)