Laravel 9 REST API Development Using JWT Authentication

Reading Time: 13 minutes
6,078 Views

Inside this article we will learn one more important concept of laravel i.e Laravel 9 REST API Development Using JWT Authentication. This will be step by step guide to create restful services from scratch.

REpresentational State Transfer (REST) is an architectural style that defines a set of constraints to be used for creating web services. REST API is a way of accessing web services in a simple and flexible way without having any processing.

In this article we will create a secure set of rest apis using laravel using JWT auth. We will use a JWT package to implement the concept of JWT authentication.

What we will do in this article –

  • User Register API
  • Login API
  • Refresh Token API
  • Logout API
  • Create Todo API
  • List Todo API
  • Single Todo details API
  • Update Todo API
  • Delete Todo API

Above are the apis, we will create using jwt authentication.

Learn More –

Let’s get started.

Laravel Installation

Open terminal and run this command to create a laravel project.

composer create-project laravel/laravel myblog

It will create a project folder with name myblog inside your local system.

To start the development server of laravel –

php artisan serve

URL: http://127.0.0.1:8000

Assuming laravel already installed inside your system.

Create Database & Connect

To create a database, either we can create via Manual tool of PhpMyadmin or by means of a mysql command.

CREATE DATABASE laravel_app;

To connect database with application, Open .env file from application root. Search for DB_ and update your details.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_app
DB_USERNAME=root
DB_PASSWORD=root

Install And Configure Laravel JWT Auth

JSON Web Token (JWT) is an open standard (RFC 7519), and it represents a compact and self-contained method for securely transmitting information between parties as a JSON object.

Open project into terminal and run this command.

$ composer require php-open-source-saver/jwt-auth

Publish Provider

Back to project terminal and run this command.

$ php artisan vendor:publish --provider="PHPOpenSourceSaver\JWTAuth\Providers\LaravelServiceProvider"

Generate JWT Secret Keys

$ php artisan jwt:secret

It will generate few JWT secret keys and save into .env file. You should see these keys into .env file. These keys handle the token encryption.

JWT_SECRET=ncXDYGJAU30WPY09AgijRXRnFppA3MhZGCG3sDnYhxOCRuFbaXbkYUzvfxg1BmPF

JWT_ALGO=HS256

Configure AuthGuard

We need to make a few changes to configure Laravel to use the JWT AuthGuard to power the application authentication.

To configure guard, Open auth.php file from /config folder.

//...

'defaults' => [
    'guard' => 'api',
    'passwords' => 'users',
],

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

//...

Update User Model

When we install laravel setup, by default we get a model User.php inside /app/Models folder.

use PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject; // Add this

class User extends Authenticatable implements JWTSubject {}

Open User.php and update with this code.

<?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 PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject
{
    use HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    /**
     * 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 [];
    }
}

Create Model & Migration For Todo

Open project into terminal and run this artisan command.

$ php artisan make:model Todo -m

-m to create migration file as well.

Above command will generate two files. One is Model and second is migration file.

Model – Todo.php inside /app/Models folder

Migration – 2022_03_20_040948_create_todos_table.php inside /database/migrations

Open Todo.php and write this code into it.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Todo extends Model
{
    use HasFactory;

    protected $fillable = [
        'title',
        'description'
    ];
}

Open Migration file 2022_03_20_040948_create_todos_table.php and write this code.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('todos', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('description');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('todos');
    }
};

Run Migration

Back to terminal and run this command to migrate.

$ php artisan migrate

Create Controllers

Back to terminal and run these artisan commands to create.

Auth Api Controller

$ php artisan make:controller AuthController

This command will create a file AuthController.php inside /app/Http/Controllers folder.

Todo Api Controller

$ php artisan make:controller TodoController

This command will create a file TodoController.php inside /app/Http/Controllers folder.

Now, we will start writing code inside all these controllers.

Open AuthController.php file and write this code into it.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use App\Models\User;

class AuthController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:api', ['except' => ['login', 'register']]);
    }

    public function login(Request $request)
    {
        $request->validate([
            'email' => 'required|string|email',
            'password' => 'required|string',
        ]);
        $credentials = $request->only('email', 'password');

        $token = Auth::attempt($credentials);
        if (!$token) {
            return response()->json([
                'status' => 'error',
                'message' => 'Unauthorized',
            ], 401);
        }

        $user = Auth::user();
        return response()->json([
            'status' => 'success',
            'user' => $user,
            'authorisation' => [
                'token' => $token,
                'type' => 'bearer',
            ]
        ]);
    }

    public function register(Request $request)
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:6',
        ]);

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        $token = Auth::login($user);
        return response()->json([
            'status' => 'success',
            'message' => 'User created successfully',
            'user' => $user,
            'authorisation' => [
                'token' => $token,
                'type' => 'bearer',
            ]
        ]);
    }

    public function logout()
    {
        Auth::logout();
        return response()->json([
            'status' => 'success',
            'message' => 'Successfully logged out',
        ]);
    }

    public function refresh()
    {
        return response()->json([
            'status' => 'success',
            'user' => Auth::user(),
            'authorisation' => [
                'token' => Auth::refresh(),
                'type' => 'bearer',
            ]
        ]);
    }
}

Open TodoController.php file and write this code into it.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Todo;

class TodoController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:api');
    }

    public function index()
    {
        $todos = Todo::all();
        return response()->json([
            'status' => 'success',
            'todos' => $todos,
        ]);
    }

    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'required|string|max:255',
        ]);

        $todo = Todo::create([
            'title' => $request->title,
            'description' => $request->description,
        ]);

        return response()->json([
            'status' => 'success',
            'message' => 'Todo created successfully',
            'todo' => $todo,
        ]);
    }

    public function show($id)
    {
        $todo = Todo::find($id);
        return response()->json([
            'status' => 'success',
            'todo' => $todo,
        ]);
    }

    public function update(Request $request, $id)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'required|string|max:255',
        ]);

        $todo = Todo::find($id);
        $todo->title = $request->title;
        $todo->description = $request->description;
        $todo->save();

        return response()->json([
            'status' => 'success',
            'message' => 'Todo updated successfully',
            'todo' => $todo,
        ]);
    }

    public function destroy($id)
    {
        $todo = Todo::find($id);
        $todo->delete();

        return response()->json([
            'status' => 'success',
            'message' => 'Todo deleted successfully',
            'todo' => $todo,
        ]);
    }
}

Add API Routes

Open api.php from /routes folder. Add these routes into it.

//...
use App\Http\Controllers\AuthController;
use App\Http\Controllers\TodoController;

//...
Route::controller(AuthController::class)->group(function () {
    Route::post('login', 'login');
    Route::post('register', 'register');
    Route::post('logout', 'logout');
    Route::post('refresh', 'refresh');
});

Route::controller(TodoController::class)->group(function () {
    Route::get('todos', 'index');
    Route::post('todo', 'store');
    Route::get('todo/{id}', 'show');
    Route::put('todo/{id}', 'update');
    Route::delete('todo/{id}', 'destroy');
});

Open terminal and run this artisan command to see all available routes.

Application Testing

Run this command into project terminal to start development server,

php artisan serve

Register API

URL – http://127.0.0.1:8000/api/register

Method – POST

Header

Content-Type:application/json
Accept:application/json

Body

{
   "name": "Sanjay Kumar",
   "email": "sanjay@gmail.com",
   "password": "123456"
}

Login API

URL – http://127.0.0.1:8000/api/login

Method – POST

Header –

Content-Type:application/json
Accept:application/json

Body –

{
   "email": "sanjay@gmail.com",
   "password": "123456"
}

Refresh Token API

URL – http://127.0.0.1:8000/api/refresh

Method – POST

Header –

Authorization:Bearer <token>
Accept:application/json

Logout API

URL – http://127.0.0.1:8000/api/logout

Method – POST

Header –

Authorization:Bearer <token>
Accept:application/json

Create Todo API

URL – http://127.0.0.1:8000/api/todo

Method – POST

Header –

Content-Type:application/json
Authorization:Bearer <token>
Accept:application/json

Body –

{
	"title": "Post 1",
	"description": "Sample Post 1"
}

List Todo API

URL – http://127.0.0.1:8000/api/todos

Method – GET

Header –

Authorization:Bearer <token>
Accept:application/json

Single Todo Detail API

URL – http://127.0.0.1:8000/api/todo/1

Method – GET

Header –

Authorization:Bearer <token>
Accept:application/json

Update Todo API

URL – http://127.0.0.1:8000/api/todo/1

Method – PUT

Header –

Content-Type:application/json
Authorization:Bearer <token>
Accept:application/json

Body –

{
	"title": "Post 2 update",
	"description": "Sample Post 2 content updated"
}

Delete Todo API

URL – http://127.0.0.1:8000/api/todo/1

Method – DELETE

Header –

Authorization:Bearer <token>
Accept:application/json

We hope this article helped you to learn about Laravel 9 REST API Development Using JWT Authentication in a very detailed way.

Online Web Tutor invites you to try Skillshike! Learn CakePHP, Laravel, CodeIgniter, Node Js, MySQL, Authentication, RESTful Web Services, etc into a depth level. Master the Coding Skills to Become an Expert in PHP Web Development. So, Search your favourite course and enroll now.

If you liked this article, then please subscribe to our YouTube Channel for PHP & it’s framework, WordPress, Node Js video tutorials. You can also find us on Twitter and Facebook.