For Developers

How to Implement User Authentication in a REST API Using Laravel Passport?

Implementing user authentication using Laravel Passport

Laravel Passport is an Open Authorization 2.0 server implementation used for authenticating APIs using Laravel. As the tokens are only used in API authentication, Laravel Passport offers an easy way to implement the token authentication on the OAuth server. In Laravel, you can take the holistic approach to build custom APIs. You do not need to put in tons of effort and can easily give preference to security. Laravel Passport streamlines the security and allows you to create Auth Tokens to provide authentication to the users.

Many digital systems today require user authentications to access resources. In this article, we will shed light on the Laravel Passport package to authenticate application APIs. Apart from discussing this in detail, we will also talk about how to create and validate the tokens.

First, let’s discuss API.

What is an API?

API stands for Application Programming Interface. An API is a set of protocols, tools, and routines that are used to create software applications. It acts like a bridge that connects the gaps between different software components.

In software development, an API is a resource locator that handles and manages the data for the web application through HTTP Requests GET, DELETE, UPDATE and POST functions. It also manages the CRUD processes and operations.

What is REST API?

Representational State Transfer or REST is a software development approach that defines a set of limitations. It is used to create web services and solutions. Web solutions that comply with the REST architecture are called RESTful Web services. These services allow the systems to streamline interoperability between different systems on the Internet.

RESTful solutions allow the systems to manipulate the textual representation of Web resources by using a predefined set of stateless operations.

Before we begin implementing user authentication using Laravel Passport, there are some prerequisites we need to follow. Let’s check out the requirements.

Starting a new Laravel project

Let’s begin the task by invoking the following command in the terminal. This will install a brand new Laravel application.


composer create-project laravel/laravel laravel-passport-auth --prefer-dist

Code source

Steps to begin a Laravel project..webp

Setting up the database

To set up the database, you must install XAMPP on your local development system and turn on the local server.

Setting up the database deals with streamlining the consensus between the database and Laravel. Now, you need to import the following code in the ‘.env’ file. Doing this will establish the connection between the server and the client.


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

Code source

Installing the Passport package

This is the second step of starting a new Laravel project. It leads to the installation of the Passport package through the Composer package manager. Run the command in your terminal.


composer require laravel/passport

Code source

Configuring the Passport module

Next, we need to focus on the process to configure the Passport package in the Laravel application. Open the ‘open app/Models/User.php’ file and include the ‘HasApiTokens’ trait inside the user model. This is mentioned in the code below.


<?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 Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
    use HasFactory, Notifiable, HasApiTokens;
    /**
     * 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',
    ];
}

Code source

Next, open the ‘app/Providers/AuthServiceProvider.php’ file and register the registerPolicies() methodology inside the boot() function. This will fetch the required routes for your code.


<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Models\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();
        Passport::routes();
    }
}

Code source

Then you need to register the PassportServiceProvider class in the provider array in the ‘config/app.php’ file. The code will be as follows:


'providers' => [
        ...
        ... 
        ...
        Laravel\Passport\PassportServiceProvider::class,
    ],

Code source

Now, you need to configure the driver for the Passport and get inside the ‘config/auth.php’ file. You also need to make a few changes as shown in the code below.


<?php
    return [
    ....
    ....
    
        'guards' => [
            'web' => [
                'driver' => 'session',
                'provider' => 'users',
            ],
    
            'api' => [
                'driver' => 'passport',
                'provider' => 'users',
            ],
        ],
    
    ....
    ....
]

Code source

Creating run migration and Posts model

To establish an agreement between the client and the server, you need to create the Post model. You can do that by executing the code fragment mentioned below.


php artisan make:model Post -m

After this, you will be able to see the original pattern of the posts migration file in the table:


‘database/migrations/timestamp_create_posts_table’

Here, you can add some values to create the internal connection using the model. Below is the code fragment.


<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedBigInteger('user_id');
            $table->text('title');
            $table->longText('description');
            $table->timestamps();
            $table->foreign('user_id')->references('id')->on('users');  
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}


Next, you need to create the ‘app/Models/Post.php’ file. You also need to register the following values inside the ‘$fillable’ array.


<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
    use HasFactory;
    protected $fillable = [
        'title', 'description'
    ];    
}

Code source

After running the above code fragment, you need to run the migration using the code fragment mentioned below.


php artisan migrate

Creating a new controller

Let’s take another example to execute another command. The code fragment below will create a new controller in the Laravel application to create a registration and login REST API.

A controller is a very important file in Laravel application development. Now, you need to insert the code fragment in the ‘PasspostAuthController.php’ file.


<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
class PassportAuthController extends Controller
{
    /**
     * Registration
     */
    public function register(Request $request)
    {
        $this->validate($request, [
            'name' => 'required|min:4',
            'email' => 'required|email',
            'password' => 'required|min:8',
        ]);
 
        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($request->password)
        ]);
       
        $token = $user->createToken('LaravelAuthApp')->accessToken;
 
        return response()->json(['token' => $token], 200);
    }
 
    /**
     * Login
     */
    public function login(Request $request)
    {
        $data = [
            'email' => $request->email,
            'password' => $request->password
        ];
 
        if (auth()->attempt($data)) {
            $token = auth()->user()->createToken('LaravelAuthApp')->accessToken;
            return response()->json(['token' => $token], 200);
        } else {
            return response()->json(['error' => 'Unauthorised'], 401);
        }
    }   
}

Code source

Before moving to the next step, you need to establish an agreement between the User and Post model. Eventually, you need to incorporate the following method inside ‘app/Models/User.php’ file.


<?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 Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
    use HasFactory, Notifiable, HasApiTokens;
    /**
     * 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 posts()
    {
        return $this->hasMany(Post::class);
    }    
}

Code source

After this, you need to create a Post controller.


php artisan make:controller PostController

You now have to insert the following code in the ‘PostController.php’ file.


<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Post;
class PostController extends Controller
{
    public function index()
    {
        $posts = auth()->user()->posts;
 
        return response()->json([
            'success' => true,
            'data' => $posts
        ]);
    }
 
    public function show($id)
    {
        $post = auth()->user()->posts()->find($id);
 
        if (!$post) {
            return response()->json([
                'success' => false,
                'message' => 'Post not found '
            ], 400);
        }
 
        return response()->json([
            'success' => true,
            'data' => $post->toArray()
        ], 400);
    }
 
    public function store(Request $request)
    {
        $this->validate($request, [
            'title' => 'required',
            'description' => 'required'
        ]);
 
        $post = new Post();
        $post->title = $request->title;
        $post->description = $request->description;
 
        if (auth()->user()->posts()->save($post))
            return response()->json([
                'success' => true,
                'data' => $post->toArray()
            ]);
        else
            return response()->json([
                'success' => false,
                'message' => 'Post not added'
            ], 500);
    }
 
    public function update(Request $request, $id)
    {
        $post = auth()->user()->posts()->find($id);
 
        if (!$post) {
            return response()->json([
                'success' => false,
                'message' => 'Post not found'
            ], 400);
        }
 
        $updated = $post->fill($request->all())->save();
 
        if ($updated)
            return response()->json([
                'success' => true
            ]);
        else
            return response()->json([
                'success' => false,
                'message' => 'Post can not be updated'
            ], 500);
    }
 
    public function destroy($id)
    {
        $post = auth()->user()->posts()->find($id);
 
        if (!$post) {
            return response()->json([
                'success' => false,
                'message' => 'Post not found'
            ], 400);
        }
 
        if ($post->delete()) {
            return response()->json([
                'success' => true
            ]);
        } else {
            return response()->json([
                'success' => false,
                'message' => 'Post can not be deleted'
            ], 500);
        }
    }
}

Code source

Defining the API routes

It’s time to define the API routes. You need to go to ‘routes/api.php’ file to declare the code fragment below.


<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PassportAuthController;
use App\Http\Controllers\PostController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::post('register', [PassportAuthController::class, 'register']);
Route::post('login', [PassportAuthController::class, 'login']);
Route::middleware('auth:api')->group(function () {
    Route::resource('posts', PostController::class);
});

Code source

Testing the Laravel 9 Passport API

With this, we are at the end of building the REST API with Passport Authentication in Laravel. Last but not least, we have to test the API we created.

We can use the Postman application to test our newly created endpoints. Postman is an easy application for professional developers. After registration and login, we will receive the access token which streamlines secure authentication and authorization with the server. Finally, we need to set it as the Bearer token in the Authorization Header to proceed with the testing.


'headers' => [
    'Accept' => 'application/json',
    'Authorization' => 'Bearer '. $accessToken,
]

Code source

To start our new Laravel application, we can run the following command:


php artisan serve

We discussed the Laravel Passport API and walked you through every process to build the REST API in Laravel. To recap, user authentication is the process to identify the user credentials and authenticate the user for secure web sessions.

FAQs

1. What is the use of authentication in Laravel?

User authentication is the process of identifying user credentials for social media accounts, emails, and more. In Web applications, this process is managed by multiple sessions that take different input parameters for user identification. The user is authenticated only if these parameters match. In short, the user must be authenticated before decrypting these parameters.

2. What is OAuth 2.0?

OAuth stands for ‘Open Authorization’ which is a standard that allows a Web application or a website to access the resources or user credentials on behalf of the user. It is the industry-standard protocol for user authentication that focuses mainly on the client while streamlining the flows for all the web applications.

3. What is a Laravel Passport?

Passport is an OAuth 2.0 server implementation for API authentication that works in the Laravel environment. The Laravel Passport package offers a secure way to implement token authentication on the server.

4. Is Laravel good for API?

Yes. Laravel works in tandem with API. There are multiple benefits of testing an API structure and analyzing the results while having complete control on the database.

5. Is encryption a form of authentication?

Digital signatures are special codes that are unique to each party. Encryption authentication prevents online attacks with these digital signatures.

Press

Press

What's up with Turing? Get the latest news about us here.
Blog

Blog

Know more about remote work.
Checkout our blog here.
Contact

Contact

Have any questions?
We'd love to hear from you.

Hire and manage remote developers

Tell us the skills you need and we'll find the best developer for you in days, not weeks.

Hire Developers