Laravel 7 REST API using JWT Authentication with Different Model
The beauty of developing applications in Laravel is that there is so much Rapid Application Development (RAD) and you can easily connect the templated to the backend of the application thus making the majority of projects built with Laravel be traditional web applications where HTML is rendered from the server-side using blade components.
However, did you know that you could also build a robust REST API with Laravel alongside the traditional web application? It’s relatively simple to build one and in this tutorial, we’ll build a Laravel REST API using JWT authentication (JSON Web Tokens) while also loging in with a different module rather than the inbuild User module.
Setting Up a Fresh Laravel 7 Project
Install a new Laravel project using Composer’s create-project
command:
composer create-project --prefer-dist laravel/laravel laravel7-rest-api-with-jwt
The command above creates a new Laravel project and pulls in all the required dependencies along with it.
Next, set up the database. I used a MySQL database named laravel7-jwt-custome-model
and added the database details to the .env
file.
.envDB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel7-rest-api-with-jwt
DB_USERNAME=root
DB_PASSWORD=
Finally, we complete the setup process by running our migrations, which creates the default user-related tables in our database.
php artisan migrate
To verify if the setup works properly, start the webserver using the following command and visit http://127.0.0.1:8000.
php artisan serve
You should see a web page come up similar to this:
Set up JWT Authentication Package
We will be using a famous package called jwt-auth
to implement token-based authentication in our Laravel 7 project. This package has over 9000 stars on GitHub and the package makes it very easy to create and issue tokens to our users.
Let’s install the package via Composer:
composer require tymon/jwt-auth
After that, add the service provider to the Providers
array in your app.php
in the config directory:
config/app.php'providers' => [
...
/*
* Package Service Providers...
*/
'Tymon\JWTAuth\Providers\LaravelServiceProvider'
/*
* Application Service Providers...
*/
...
],
Next, also in the app.config
file, add the JWTAuth
and JWTFactory
facades to the aliases
array.
'aliases' => [
...
'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory'
],
After that, we publish the package’s config using the following command:
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
Finally, let’s generate a secret key that this package will use to encrypt our tokens:
php artisan jwt:secret
The above command generates an encryption key and sets it in our .env
with something like JWT_SECRET=keystring
.
Prepare Custome Model for Authentication
For this case we will be using the existing Client model for authentication, therefore, we need to integrate our client model with the jwt-auth
package. To do that, we’ll import the Tymon\JWTAuth\Contracts\JWTSubject
contract on the client model and define the two required methods, getJWTIdentifier()
and getJWTCustomClaims()
.
Configure the Auth Guard and Providers
Now we need to have Laravel always use jwt-auth
for authentication instead of the traditional session
driver.
Set the default guard to api
and the API guard’s driver to jwt
in app/auth.config
like so:
Under the guars point api
to 'drive'=>'jwt'
and 'provider’=>’clients
which you will define user provider
As you can see the clients provider’s model
points to App\Client::class
. This will enable our auth to pick from client guard rather than user guard.
Define API routes
Now that we’ve installed the package, let’s get to defining the REST API routes for our application.
In Laravel, you should define your API routes in routes/api.php
and not on web.php
. We will define authentication-related routes here.
routes/api.php<?phpuse Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;/*
|--------------------------------------------------------------------------
| 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([
'middleware' => 'api',
'prefix' => 'auth'], function () { Route::post('register', 'JWTAuthController@register');
Route::post('login', 'JWTAuthController@login');
Route::post('logout', 'JWTAuthController@logout');
Route::post('refresh', 'JWTAuthController@refresh');
Route::get('profile', 'JWTAuthController@profile');});
Note: all the routes defined in
routes/api.php
will be prefixed withapi/
by Laravel and auth routes are prefixed withauth
. So our/login
route is actually/api/auth/login
and the same holds for all the other routes.
Define Authentication Logic
Now that we’ve defined the routes, it’s time to define the respective controller methods for all those routes. Let’s create a controller to house all our authentication logic:
php artisan make:controller JWTAuthController
The register logic
The login, profile and logout Logic
And finally the refresh and createToken logic
Before I explain the routes, I would like you to bring your attention to the auth()->guard('api)->
as this will help seperate the logic of traditional Laravel web app with one that has both api and traditional one and using the a different model for authentication
Explanation
- Register: This method is used to register a user and is invoked on
/api/auth/register
route. This method also takes name, email, and password as an input and creates a new user from it. - Login: This method is invoked when the user hits the
/api/auth/login
endpoint. We check if the provided email and password are correct and return a JSON token in the response. You should use this token for any subsequent requests. - Profile: This method returns the logged-in user’s details. You need to pass your token in the header field to authenticate this request. I’ll be showing you how to do it in the next section.
- Refresh Token: It is a good practice to have short-lived tokens. The tokens are only valid for a short period of time and the user needs to get a new token by sending the old one before it expires. Otherwise, the user would have to login again, which will invalidate the old token.
- Logout: This API will invalidate the passed token.
Testing using PostMan
We’re done building our API! Let’s test to see if it works. Note that we pass the token as a header field "Authorization:Bearer token"
for Profile, Refresh Token, and Logout APIs.
I have tested the API using Postman and here are the results.
Register (/api/auth/register)
Login (/api/auth/login)
Profile (/api/auth/profile)
Refresh Token (/api/auth/refresh)
Logout (/api/auth/logout)
Now that you’ve implemented a jwt authentication using different model
Thanks so much for reading!😋👏👏👏👏