API Authentication — Laravel + Core JWT
In a previous article, I explained the benefits of JWT authentication over traditional methods, and we implemented a simple authentication system with Laravel and JWT.
For the example, we used tymondesigns/jwt-auth, an excellent JWT library written for Laravel. In this article, however, we are going back to basics. We will be implementing authentication with Laravel with the core JWT package for PHP, firebase/php-jwt. One reason for this is to get a lower-level understanding of how JWT works and thus understand any implementations we may come across in the future. Another reason is flexibility. With the core package, we get the freedom to customize JWT to achieve what we want at a given instance.
Let’s get started.
Install Laravel and other dependencies
Any version from 8 upwards will be sufficient to run this project (I used version 8 for this project). To install Laravel, you can run this command in your server root folder:
composer create-project laravel/laravel:^8.0 laravel-core-jwtcd laravel-core-jwt
As mentioned earlier, we will be using firebase/php-jwt package. To install, you can use the command below:
composer require firebase/php-jwt
Note: the source code for this project can be found at https://github.com/joshuaetim/laravel-core-jwt
Write token generator
Next, we write the token generator, which is the heart of our authentication procedure. This will be one of our Handlers, which is how we organize methods that are reusable by Controllers and Middlewares. The code is displayed below:
Important to note here are lines 25, where the data to be stored in our token is defined, and lines 37, where we encoded the data to return a JWT to the caller. In this case, this will be our authorization token for user authentication. The GenerateToken method accepts a User model, which will be the newly registered or logged-in user. We will pass this value shortly.
The Public Helper
We will use a helper to grab the token from the request header and decode it using the JWT package. This will be the Public Helper as it can be used by any part of the application. The code is displayed below.
We split the methods into three to encourage reuse by other classes; GetRawJWT extracts token from the header, and DecodeRawJWT decodes it using the package. These methods come together in GetAndDecodeJWT to achieve what we want from our authentication process.
At this point, you must have noticed the env(‘JWT_KEY’), which is the secret key to be used by our JWT package. This is usually a random string that is to be kept secret. For those in UNIX based environment, one good way to generate cryptographically secure keys can be running the following command:
openssl rand -hex 32
and then, in your .env file, store the variable, as such:
Let’s get to the main action centers. We will create the AuthController to handle the endpoints for creation and login of users. Before we do that, however, we will create a base controller responsible for formatting our responses to the client. We’ll call this APIController:
The contents of AuthController is detailed below:
This controller makes use of our handlers created previously. The register method adds a new user to the database and generates a token using the GenerateToken method we created earlier. This is sent to the user to grant them access for as long as the token is valid. The login method checks the login details against the database and generates a token upon a successful match.
We need middleware to check if the user making the request is authenticated. The Helper we have written so far will be of help here. To create the middleware, we will make use of Laravel’s artisan command:
php artisan make:middleware JWTVerify
Here’s the content of JWTVerify:
This middleware makes use of the PublicHelper class to get and decode the JWT from the request header. If there are any inconsistencies such as expired tokens, wrong tokens, no headers — anything, the JWT package raises an exception which is reported as an error response.
To make use of this middleware, we will register it in our Kernel.php file:
At line 65, we registered the middleware with the name ‘jwt.auth’. This will be useful in defining our routes.
The API endpoints
We need a way to present these features to our clients ,so we turn to the routes/api.php file in our folder:
There are two new classes here: AdminHelper and HomeController. The AdminHelper class simply decodes the token and returns the logged in user. The HomeController gives us a public page to show our users.
In the end, we have a simple authentication system that uses JWT directly, allowing us more flexibility on how it is used. You can test on Postman to see how your code worked out, and let me know if you had any issues, or have any suggestions in the comment box.
For the next tutorial, I will share my method for logging out a user, and also tightening the security more. The source code for this project can be found on my Github at https://github.com/joshuaetim/laravel-core-jwt
Be sure to clap and share to help others see and share suggestions. Thanks!