DEV Community

Dallington Asingwire
Dallington Asingwire

Posted on • Updated on

How to secure Laravel API

Laravel Passport provides a full OAuth2 server implementation for your laravel application. If your application needs to support OAuth2, then you should use Laravel Passport.
To get started, install Passport via the Composer package manager as follows;

composer require laravel/passport
Enter fullscreen mode Exit fullscreen mode

Passport has its service provider that registers its own database migration directory, so you should migrate your database after installing the package. The Passport migrations will create the tables your application needs to store OAuth2 clients and access tokens:

php artisan migrate
Enter fullscreen mode Exit fullscreen mode

Next, execute the following artisan command;

php artisan passport:install
Enter fullscreen mode Exit fullscreen mode

The above command creates the encryption keys needed to generate secure access tokens. This also creates "personal access" and "password grant" clients which will be used to generate access tokens.

After running the passport:install command, add Laravel\Passport\HasApiTokens trait to your model that authenticates your users. In my case, I use customer model as the authentication model.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
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 Customer extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
    protected $table = "customers";
    public $timestamps = true;

    protected $guarded=['id'];
    protected $fillable = [
       'first_name',
       'last_name',
       'phone_number',
       'email',
       'account_balance',
       'password'
    ];

    protected $hidden = [
        'password',
        'remember_token',
    ];

    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function getAuthPassword(){
        return $this->password;
    }

}
Enter fullscreen mode Exit fullscreen mode

As you can see in the above code snippet, my model Customer uses HasApiTokens trait.

The next step is to call the Passport::routes method within the boot method of your App\Providers\AuthServiceProvider. This method registers the routes necessary to issue access tokens and revoke access tokens, clients, and personal access tokens.

<?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();

         // scope customer used when creating access token  
         Passport::tokensCan([
            'customer' => 'Customer access',
         ]);


    }
}
Enter fullscreen mode Exit fullscreen mode

In the next step, in the application's config/auth.php, I set the driver option of my customized api authentication guard called api-customers to passport. This instructs the application to use passport's TokenGuard when authenticating incoming customer API requests.

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

        'api-customers' => [
            'driver' => 'passport',
            'provider' => 'customers',
            'hash' => false,
        ],
    ],

Enter fullscreen mode Exit fullscreen mode

in the above config/auth.php file, I have created an authentication guard called api-customers which uses provider customers. Below is my provider customers set in the providers array in the same file.

  'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],

         'customers' => [
            'driver' => 'eloquent',
            'model' => App\Models\Customer::class,
        ],

    ],
Enter fullscreen mode Exit fullscreen mode

Lastly, you can apply auth middleware to your routes in routes/api.php as seen in the example below;

Route::group(['prefix' => 'customer', 'middleware' => ['auth:api-customers']], function(){
 Route::get('/search/{id}', [CustomerController::class, 'findCustomer']);
});
Enter fullscreen mode Exit fullscreen mode

In the above route for searching customer, an auth middleware on the customer guard(api-customers) is used and any request to this endpoint will be authenticated using Laravel passport since we applied it to the api authentication guard called api-customers.

Now users will be assigned new access tokens every time they login. Access token in the login method in your login controller can be created as follows;

$access_token = $customer->createToken('Customer'.$customer->phone_number, ['customer'])->accessToken;
Enter fullscreen mode Exit fullscreen mode

This token must be sent as part of headers in the http requests from the frontend to the API if the end point is to be accessed.

And that's how you can secure your application or your laravel api end points using Laravel Passport. Thank you for reading through this, see you in my next post.

Top comments (0)