Setting up JWT Token-based Authentication in Laravel is easy. The traditional process of interacting with a website is logging in from the login page. Next, you perform your desired actions and then log out. However, in the case of REST API, the process is entirely different. JWT (JSON Web Token) is usually used to send information that can be trusted and verified using a digital signature.
When we can use JSON Web Tokens
Let us say; you have a mobile application that needs to communicate with the server. Now, a server needs to identify with whom they are talking. But unfortunately, HTTP is a stateless protocol. So we need to create a mechanism that resolves our issue: how the server will identify that the user is new or old. Is it already registered with the application or not. Is it authorized a user or not? In that scenario, we can use JWT Authentication.
Laravel JWT Authentication
- A user sends a signup post request to the server, and the server creates a user and JWT token on that database and returns a JWT token as a response.
- JWT is stored either in the browser’s local or other storage mechanisms.
- When a user makes another request, it needs to append that token in the request header.
- The server checked that token, and based on whether the JWT token was valid or not, it returned a response.
- Until a user logs out of the application and destroys that token from the local storage, it always checks for it. If the token is valid, then it can access the particular resources.
- If the token is destroyed or manipulated, the user redirects to the login screen, and he needs to fill in the username and password.
- If the username and password are valid, then in response, it sends a JWT token back to the user. Then, again same procedure, the user stores it in local storage and sends that token for every request to verify with the server that he has a trusted user and can access the particular resources.
As usual, we start this project by installing fresh Laravel.
Step 1: Install and configure Laravel
Install Laravel by the following command.
composer create-project laravel/laravel jwtauth --prefer-dist
Configure the database.
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.
Step 2: Update the config/app.php for the JWT package
Go to the config >> app.php file and add the following.
'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"
Now for token encryption, I need to generate a secret key by running the following line of code :
php artisan jwt:generate
If you find an error like this after hitting the above command.
You need to do the following step.
Go to the JWTGenerateCommand.php file located in vendor/tymon/src/Commands and paste this part of the code. public function handle() { $this->fire(); }
You can find out more about this issue.
Step 3: Register the user into the database.
Migrate the tables into the database by the following command.
php artisan migrate
Now, create two controller files for user registration and authentication.
- APIRegisterController.php
- APILoginController.php
Please type the following command to generate it.
php artisan make:controller APIRegisterController php artisan make:controller APILoginController
Also, register the api routes inside routes >> api.php file.
Route::post('user/register', 'APIRegisterController@register'); Route::post('user/login', 'APILoginController@login');
First, we code the register function inside the APIRegisterController.php file.
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use App\User; use JWTFactory; use JWTAuth; use Validator; use Response; class APIRegisterController extends Controller { public function register(Request $request) { $validator = Validator::make($request->all(), [ 'email' => 'required|string|email|max:255|unique:users', 'name' => 'required', 'password'=> 'required' ]); if ($validator->fails()) { return response()->json($validator->errors()); } User::create([ 'name' => $request->get('name'), 'email' => $request->get('email'), 'password' => bcrypt($request->get('password')), ]); $user = User::first(); $token = JWTAuth::fromUser($user); return Response::json(compact('token')); } }
What I have done is first check the validation, and then if all the form data seems right, it will register the user in the database and return a JWT token. We are generating the token based on the User object. You can create the token from anything you want. You can find more guidance here.
Step 4: Test in Postman.
We are registering the user through postman. So let us do that.
First, we check the validation.
Now, fill in your name, email, and password and see if we can get the token or not.
Yikes!! We have successfully registered the user and get back the JWT token. Now save this token in the local storage, and when we need to access any protected resource, pass this token as Auth Bearer to get a request and obtain that route.
Step 5: Login the user.
We have already defined the login route in the api.php file. Now, go to the APILoginController.php file and code the login function.
// APILoginController.php <?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Validator; use JWTFactory; use JWTAuth; use App\User; use Illuminate\Support\Facades\Auth; class APILoginController extends Controller { public function login(Request $request) { $validator = Validator::make($request->all(), [ 'email' => 'required|string|email|max:255', 'password'=> 'required' ]); if ($validator->fails()) { return response()->json($validator->errors()); } $credentials = $request->only('email', 'password'); try { if (! $token = JWTAuth::attempt($credentials)) { return response()->json(['error' => 'invalid_credentials'], 401); } } catch (JWTException $e) { return response()->json(['error' => 'could_not_create_token'], 500); } return response()->json(compact('token')); } }
If the email and password are correct, we can generate the JWT token. Otherwise, we get an error. Now check this in the POSTMAN and see if we can get the token.
Step 6: Include middleware to protect the resources.
/jwt-auth package provides us, by default, two middlewares.
- jwt.auth
-
jwt.refresh
We need to register these middlewares into the app >> Http >> Kernel.php file.
protected $routeMiddleware = [ ... ... 'jwt.auth' => 'Tymon\JWTAuth\Middleware\GetUserFromToken', 'jwt.refresh' => 'Tymon\JWTAuth\Middleware\RefreshToken', ]
Define one route that needs to be protected via JWT Token Authentication.
// api.php Route::middleware('jwt.auth')->get('users', function(Request $request) { return auth()->user(); });
Now, log in to the application and get the token. We can use this token in the get request like the following.
Authorization: Bearer {yourtokenhere}
And, we are getting the User back. So Our fully functional Laravel JWT Authentication Tutorial Example is working. So, I have put this code on Github. So please check that out as well.
How to use JWT with multiple Models (also multiple tables). I mean like User and Admin models. Please create the tutorial for this case, thank you!
You should implement it yourself using guards. Please look at my tutorial about how to build a multi auth application with Laravel: https://medium.com/@renandiett/laravel-5-4-trabalhando-com-autentica%C3%A7%C3%B5es-independentes-sem-packages-adicionais-6e50c11a0b79
Please note that the text was made with my language (Portuguese).
Furthermore you may try DevMarketer tutorial: https://www.youtube.com/watch?list=PLwAKR305CRO9S6KVHMJYqZpjPzGPWuQ7Q&v=iKRLrJXNN4M
You can make a check to your models and if the checks are okay by your clause or filters, then use the JWTFACTORY to create a token and send.
how do i destroy a token? for logout the user?
Step1: Define logout route in routes/api.php
Route::group([‘middleware’ => ‘jwt.auth’], function(){
Route::post(‘auth/logout’, ‘AuthController@logout’);
});
Step2: In controller
public function logout()
{
JWTAuth::invalidate();
return response([
‘status’ => ‘success’,
‘msg’ => ‘Logged out Successfully.’
], 200);
}
Hi,
I am getting
{
“error”: “token_not_provided”
}
Even, i am sending Authorization header. Please help. its urgent issue. Needs to resolve ASAP
Can you explain to me how to have that Bearer type authorization and what is your header set up?
Hello!
I have cloned you GitHub repository and I have installed your app. When I send POST request to /api/user/register I get error message: SQLSTATE[HY000]: General error: 1364 Field ‘api_token’ doesn’t have a default value.
How can i fix it?
Cool. Definitely gott my internet working now. Thanks a lot guys.
How to secure this token can any one help me out here ?
I want to get the api to pass to the router for the client after logon how to do
How to get current logged in token and invalid it
Class ‘Tymon\JWTAuth\Providers\JWTAuthServiceProvider’ not found
this is implementation of Laravel 5.7. Any idea?
How to use JWT with multiple tables. Authentication details stored in 2 tables. I mean like Staff (Teaching+NonTeaching) and Student Tables.
I am getting
{
“error”: “token_not_provided”
}
Nice tutorials, thanks, it’s very helpful, thanks krunal.
Hi there, always i used to check web site posts here early in the dawn, aas i love to learn more and more.