This series is going to cover how to build a REST API using laravel API resources, the first part of the series will include setting up the project and handling user authentication using JSON web tokens(JWTs). The second part I'll be building a book review API with the API resources and in the third part, I will test the API with postman.
Before I begin, I'm going to assume the following:
- knowledge of PHP.
- Basic knowledge of laravel.
- Have composer and laravel installed.
- Have postman installed.
The entire source code for this application can be found on my github
let's dive in.
Creating the application
The first thing we're going to do is create a new laravel app
you can do this either by
new bookreview
or
composer create-project laravel/laravel bookreview
if you do not have the installer you can get it by running
composer global require laravel/installer
note: At the time of writing this post, we're going to be using laravel 6.0 but it applies for any laravel version from 5.5
for more information on how to install laravel you can check their official documentation
Now that we have laravel installed and the project set up, let us get started on using jwt.
what are JWTs?
JSON Web Token (JWT) is an Internet standard for creating JSON-based access tokens that assert some number of claims. For example, a server could generate a token that has the claim "logged in as admin" and provide that to a client. The client could then use that token to prove that it is logged in as admin. The tokens are signed by one party's private key (usually the server's), so that both parties can verify that the token is legitimate. The tokens are designed to be compact, URL-safe, and usable especially in a web-browser single-sign-on (SSO) context. JWT claims can be typically used to pass the identity of authenticated users between an identity provider and a service provider.
Getting started
Navigate to the project's directory and install the third party package called jwt-auth by running
require tymon/jwt-auth "1.0.*"
Once the package has installed, we'll need to publish the vendor's files by running ```php
artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
you should be able to see the package in the vendor folders if the command runs successfully.
Next we will generate a jwt secret key by running
```php
artisan jwt:secret
Open the .env file in your project and you will see a randomly generated secret key for your application.
Next, we will need to make our user model implement JWT. By default, laravel comes with a user model, so we will run any commands to create one.
open the app/user.php
file and update it to look like the following:
php
<?php
namespace App;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
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',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function getJWTIdentifier()
{
return $this->getKey();
}
public function getJWTCustomClaims()
{
return [];
}
}
We defined two methods to return the JWTIdentifier
and JWTCustomClaims
. Custom claims are used in generating the JWT token. For this guide, we will not be using custom claims.
Next, let's configure auth guard to make use of the jwt guard by editing the config/auth.php
to look like this
php
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
...
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
'hash' => True,
],
],
Here we are setting the api guard as the default and telling the api guard to use jwt.
That concludes the installation of jwt, let's continue to the rest of the application.
Set up the Database
For this guide, we're going to be using MySQL database, I am using xampp as my database.
open the .env file and edit the database settings to look like this
env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=bookreview
DB_USERNAME=root
DB_PASSWORD=
Also, do remember to create the database "bookreview" on the localhost/phpmyadmin
Turn the local laravel server on by running php artisan serve
and turning xampp or whichever database you have.
we will not modify anything on the default user's table migration. Next, run the migrations by php artisan migrate
command.
Making the User Controller
We will make a controller to handle the registration and login of users. We'll call this controller, AuthController
Run the command php artisan make:controller AuthController
Once the controller is created, navigate to App\Http\Controllers\AuthController.php
file and modify it to look like this...
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class AuthController extends Controller
{
public $loginAfterSignUp = true;
public function register(Request $request)
{
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => bcrypt($request->password),
]);
$token = auth()->login($user);
return $this->respondWithToken($token);
}
public function login(Request $request)
{
$credentials = $request->only(['email', 'password']);
if (!$token = auth()->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
public function getAuthUser(Request $request)
{
return response()->json(auth()->user());
}
public function logout()
{
auth()->logout();
return response()->json(['message'=>'Successfully logged out']);
}
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth()->factory()->getTTL() * 60
]);
}
}
The register function requires the user to provide their name, email and password. While the login function requires one to only provide the email and password. Both methods return a response with a JWT by calling a respondWithToken()
method which gets the token array structure. Users will have to login after registration hence the
public $loginAfterSignUp = true;
The token expires after an hour afterward the user can either log in again or get a refresh token. For more information about token generation, you can check here.
Define API routes
Okay now that we're done with all the heavy lifting, let's define our API endpoints(routes). We do this by navigating to the routes\api.php
file in our application.
Configure the file by adding these
php
Route::post('register', 'AuthController@register');
Route::post('login', 'AuthController@login');
Route::get('logout', 'AuthController@logout');
Route::get('user', 'AuthController@getAuthUser');
All these routes point to the functions defined in the AuthController, we will see how they work by testing them with postman in a while.
You can verify that the routes have been registered by running php artisan route:list
`
That concludes the set up of the user handling. We will now test that the API works.
Testing
For testing purposes, we will use postman to determine whether the app meets our expectations and functionality.
Before we begin testing, ensure that the local laravel server is up by running php artisan serve
Turn on xampp or whichever MySQL server you are using.
note: the API requests need the header, accept:application/json
registration
log in
failed login handling
checking the currently logged in user
Observe that you set the authorization as bearer token, copy the access token provided after logging in and paste it in the token text box
logging out
That completes everything you need to get your user registration and authentication api with laravel. Thanks for reading this post, if you have any problem with the API you can always get in touch on twitter :)
In the next part of this series, we're going to be making a CRUD API with laravel resources that enable our users to upload books and review them as well...
Sponsors
Please note that some of the links below are affiliate links. I only recommend products, tools and learning services I've personally used and believe are genuinely helpful. Most of all, I would never advocate for buying something you can't afford or that you aren't ready to use.
Scraper API is a startup specializing in strategies that'll ease the worry of your IP address from being blocked while web scraping. They utilize IP rotation so you can avoid detection. Boasting over 20 million IP addresses and unlimited bandwidth. Using Scraper API and a tool like 2captcha will give you an edge over other developers. The two can be used together to automate processes. Sign up on Scraper API and use this link to get a 10% discount on your first purchase.
Do you need a place to host your website or app, Digital ocean
is just the solution you need, sign up on digital ocean using this link and experience the best cloud service provider.The journey to becoming a developer can be long and tormentous, luckily Pluralsight makes it easier to learn. They offer a wide range of courses, with top quality trainers, whom I can personally vouch for. Sign up using this link and get a 50% discount on your first course.
Top comments (9)
@ted I'm also on Laravel. On the topic of Auth, have you gotten Laravel Passport and Laravel Socialite working together? Would love to see an article on API-based social auth using Laravel Passport and Socialite. This is the closest thing I could find but getting it working is challenging - it's complicated. itnext.io/laravel-api-authenticati...
Hi.No I haven't tried it out yet, but I can check it out in a few days and give you my feedback...
@ted sounds great...look forward to seeing it.
Hi! Thanks for your information!! It´s very valuable for me, I relatively new in Laravel! I´ve implemented authentication on Laravel using Tymon/jwt, it works fine, but now I need that a user can only be logged in only one device. I read that it is possible with Laravel default authentication, but I don´t find information about how to get this feature with TymonJWT. Do you know if it is possible?
hey, are we not supposed to save the token in the Db?
Thanks Man It Worked Nice Love You Really ❤❤❤
I'm glad it worked out well. You're welcome
Nice job pls i need help how to set jwt expire at to be in UTC
"expires_in": "2020-06-13 12:20:00"
Instead of
expires_in": 3600
@ted - Please note that v1.0 isn't suitable for Production use.