JWT authentication tutorial

JSON Web Token (JWT) is an open standard (open standard means anyone can use it without any restriction) RFC 7519 method which has been designed for representing claims securely between two parties. JWT is mainly used for verifying the requests between two parties or we can say for information exchange. JWT basically works on the public/private key pair. The information is digitally signed hence serves more security to the parties.

JWT is an encoded string which contains three parts: Header, Payload and Verify Signature. They are separated with a period. Following is a format of the JWT:

 s1ksDk8sd2.sdpcSd79a1.sda81eq

This article contains steps of API authentication using JWT:

STEP BY STEP INSTRUCTIONS FOR TUTORIAL OF API AUTHENTICATION USING JSON WEB TOKEN (JWT)

  • Step 1: Create fresh Laravel application

To create the latest version of Laravel application. Open the Terminal and run the following command:

composer create-project laravel/laravel jwt –prefer-dist

Now change Terminal working directory to project:

cd jwt

  • Step 2: Install and configure JWT library

You can install the JWT library by using the following command:

composer require tymon/jwt-auth

Now register the library service provider to config/app.php file. Open the file and add the following into the providers array.

‘providers’ => [

    ….

    Tymon\JWTAuth\Providers\LaravelServiceProvider::class,

],

Publish JWT config file using the following command into terminal:

vendor:command

php artisan vendor:publish –provider=”Tymon\JWTAuth\Providers\LaravelServiceProvider”

This will copy configuration file from vendor to config/jwt.php.

After this, we will be needing to generate a token secret. Therefore, run the following artisan command: 

php artisan jwt:secret

A JWT token secret to .env file. will be created.

  • Step 3: Configuration of database in .env file

To configure database connection. Open the .env file from the root directory and start changing below given database credentials with your MySQL.

DB_CONNECTION=mysql

DB_HOST=127.0.0.1

DB_PORT=3306

DB_DATABASE=jwt

DB_USERNAME=root

DB_PASSWORD=secret

Laravel have users table by default to authenticate API. So migrate users table into database using the command bellow: 

php artisan migrate

  • Step 4: Update User model

Open App/Models/User.php file and implement Tymon\JWTAuth\Contracts\JWTSubject interface. Now add two model methods: 

getJWTCustomClaims() and getJWTIdentifier().

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject

{

    use HasFactory, Notifiable;

    /**

     * Get the identifier that will be stored in the subject claim of the JWT.

     *

     * @return mixed

     */

    public function getJWTIdentifier()

    {

        return $this->getKey();

    }

    /**

     * Return a key value array, containing any custom claims to be added to the JWT.

     *

     * @return array

     */

    public function getJWTCustomClaims()

    {

        return [];

    }

}

  • Step 5: Configure default authentication guard

Open config/auth.php file and change default guard to api.

<?php

return [

    ‘defaults’ => [

        ‘guard’ => ‘api’,

        ‘passwords’ => ‘users’,

    ],

    ‘guards’ => [

        ‘web’ => [

            ‘driver’ => ‘session’,

            ‘provider’ => ‘users’,

        ],

        ‘api’ => [

            ‘driver’ => ‘jwt’,

            ‘provider’ => ‘users’,

        ],

    ],

];

  • Step 6: Add Authentication routes

Now open the file and add following routes into it:

<?php

use Illuminate\Http\Request;

use Illuminate\Support\Facades\Route;

use App\Http\Controllers\JWTController;

Route::group([‘middleware’ => ‘api’], function($router) {

    Route::post(‘/register’, [JWTController::class, ‘register’]);

    Route::post(‘/login’, [JWTController::class, ‘login’]);

    Route::post(‘/logout’, [JWTController::class, ‘logout’]);

    Route::post(‘/refresh’, [JWTController::class, ‘refresh’]);

    Route::post(‘/profile’, [JWTController::class, ‘profile’]);

});

  • Step 7: Create JWTController controller class

The following Artisan command will generate controller class at App/Http/Controllers directory:

 

php artisan make:controller JWTController

 

Add the following methods as per routes in the controller class:

<?php

namespace App\Http\Controllers;

use Auth;

use Validator;

use App\Models\User;

use Illuminate\Http\Request;

use Illuminate\Support\Facades\Hash;

class JWTController extends Controller

{

    /**

     * Create a new AuthController instance.

     *

     * @return void

     */

    public function __construct()

    {

        $this->middleware(‘auth:api’, [‘except’ => [‘login’, ‘register’]]);

    }

    /**

     * Register user.

     *

     * @return \Illuminate\Http\JsonResponse

     */

    public function register(Request $request)

    {

        $validator = Validator::make($request->all(), [

            ‘name’ => ‘required|string|min:2|max:100’,

            ’email’ => ‘required|string|email|max:100|unique:users’,

            ‘password’ => ‘required|string|confirmed|min:6’,

        ]);

        if($validator->fails()) {

            return response()->json($validator->errors(), 400);

        }

        $user = User::create([

                ‘name’ => $request->name,

                ’email’ => $request->email,

                ‘password’ => Hash::make($request->password)

            ]);

        return response()->json([

            ‘message’ => ‘User successfully registered’,

            ‘user’ => $user

        ], 201);

    }

    /**

     * login user

     *

     * @return \Illuminate\Http\JsonResponse

     */

    public function login(Request $request)

    {

        $validator = Validator::make($request->all(), [

            ’email’ => ‘required|email’,

            ‘password’ => ‘required|string|min:6’,

        ]);

        if ($validator->fails()) {

            return response()->json($validator->errors(), 422);

        }

        if (!$token = auth()->attempt($validator->validated())) {

            return response()->json([‘error’ => ‘Unauthorized’], 401);

        }

        return $this->respondWithToken($token);

    }

    /**

     * Logout user

     *

     * @return \Illuminate\Http\JsonResponse

     */

    public function logout()

    {

        auth()->logout();

        return response()->json([‘message’ => ‘User successfully logged out.’]);

    }

    /**

     * Refresh token.

     *

     * @return \Illuminate\Http\JsonResponse

     */

    public function refresh()

    {

        return $this->respondWithToken(auth()->refresh());

    }

    /**

     * Get user profile.

     *

     * @return \Illuminate\Http\JsonResponse

     */

    public function profile()

    {

        return response()->json(auth()->user());

    }

 

    /**

     * Get the token array structure.

     *

     * @param  string $token

     *

     * @return \Illuminate\Http\JsonResponse

     */

    protected function respondWithToken($token)

    {

        return response()->json([

            ‘access_token’ => $token,

            ‘token_type’ => ‘bearer’,

            ‘expires_in’ => auth()->factory()->getTTL() * 60

        ]);

    }

}

  • Step 8: Test application in Postman

We have completed the application coding. Start the Laravel server using the below Artisan command:

php artisan serve

For testing APIs in postman, consider the following steps. 

  • Refresh Token API

You can refresh the current token with a new token using auth()->refresh() method.

  • Register API

All API routes are prefixed with api namespace. In the postman use http://localhost:8000/api/register API endpoint. Pass name, email, password and password_confirmation parameters into request.

  • Profile API

You need to pass access_token in Header as bearer token as all auth:api middleware routes have been protected with api guard

  • Login API

Use http://localhost:8000/api/login API endpoint with email password parameter with request. You will be receiving token json object into response, if the password, email matches with registered user.

  • Logout API

You need to invalidate the current token to logout current token. Simply call auth()->logout() method to invalidate the current access token. Once a user logged out, it can’t access protected routes.

What's your reaction?

Excited
0
Happy
0
In Love
0
Not Sure
0
Silly
0

You may also like

Leave a reply

Your email address will not be published. Required fields are marked *