Handling user registration and authentication on a laravel API using jwt
Tags: laravel, php, jwt, api
Published: 2019-10-20 18:43:47

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:
   
1. knowledge of PHP.
2. Basic knowledge of laravel.
3. Have composer and laravel installed.
4. Have postman installed.

The entire source code for this application can be found on my [github](https://github.com/King-maker/book-review-api)

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
```laravel 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](https://laravel.com/docs/6.x#installation)
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 
```composer 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
<?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 
```php
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](https://jwt-auth.readthedocs.io/en/develop/quick-start/#create-the-authcontroller).
##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](https://www.getpostman.com/) 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
![registration](https://thepracticaldev.s3.amazonaws.com/i/sbu1w62m1z7nw4vsov6s.PNG)
###log in
![login](https://thepracticaldev.s3.amazonaws.com/i/az3fs9chr85849fwcwo2.PNG)
###failed login handling
![failed login](https://thepracticaldev.s3.amazonaws.com/i/ngqy8183fn9vsh7xadez.PNG)
### 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
![logged in user](https://thepracticaldev.s3.amazonaws.com/i/ggvtwnz08dqik0qnfshh.PNG)
###logging out
![log out](https://thepracticaldev.s3.amazonaws.com/i/qdwv4qa9afajirhm4c28.PNG)

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](https://twitter.com/Ngeene_kihiu) :) 

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](https://www.scraperapi.com?via=teddy44) 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](https://2captcha.com?from=12437369) 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] (https://www.scraperapi.com?via=teddy44) to get a 10% discount on your first purchase.

- Do you need a place to host your website or app, [Digital ocean](DigitalOcean – The developer cloudwww.digitalocean.com)
 is just the solution you need, sign up on digital ocean using this [link](https://m.do.co/c/eaa803fe4d99) and experience the best cloud service provider.

- The journey to becoming a developer can be long and tormentous, luckily [Pluralsight](http://referral.pluralsight.com/mQh0Nxp) 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](http://referral.pluralsight.com/mQh0Nxp) and get a 50% discount on your first course.