DEV Community

Cover image for Handling user registration and authentication on a laravel API using jwt
Ted Ngeene
Ted Ngeene

Posted on • Updated on

Handling user registration and authentication on a laravel API using jwt

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

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
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

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 [];
    }
 }
Enter fullscreen mode Exit fullscreen mode

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

'defaults' => [
        'guard' => 'api',
        'passwords' => 'users',
    ],
 ...
'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'jwt',
            'provider' => 'users',
            'hash' => True,
        ],
    ],
Enter fullscreen mode Exit fullscreen mode

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

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=bookreview
DB_USERNAME=root
DB_PASSWORD=
Enter fullscreen mode Exit fullscreen mode

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
      ]);
    }

}

Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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

Route::post('register', 'AuthController@register');
Route::post('login', 'AuthController@login');
Route::get('logout', 'AuthController@logout');
Route::get('user', 'AuthController@getAuthUser');
Enter fullscreen mode Exit fullscreen mode

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

registration

log in

login

failed login handling

failed login

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

logging out

log 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)

Collapse
 
kp profile image
KP • Edited

@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...

Collapse
 
tngeene profile image
Ted Ngeene

Hi.No I haven't tried it out yet, but I can check it out in a few days and give you my feedback...

Collapse
 
kp profile image
KP

@ted sounds great...look forward to seeing it.

Collapse
 
vblanco20 profile image
Valeria Blanco

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?

Collapse
 
microsoftjulius profile image
microsoftjulius

hey, are we not supposed to save the token in the Db?

Collapse
 
h4775346 profile image
Opeto

Thanks Man It Worked Nice Love You Really ❤❤❤

Collapse
 
tngeene profile image
Ted Ngeene

I'm glad it worked out well. You're welcome

Collapse
 
kennyendowed profile image
kenneth Endowed

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

Collapse
 
chyn_km profile image
KM

@ted - Please note that v1.0 isn't suitable for Production use.