nomadnt/lumen-passport

Lumen porting of Laravel Passport

v10.1.0 2021-01-01 22:27 UTC

This package is auto-updated.

Last update: 2022-07-01 00:12:47 UTC


README

68747470733a2f2f6c61726176656c2e636f6d2f6173736574732f696d672f636f6d706f6e656e74732f6c6f676f2d70617373706f72742e737667

Total Downloads Latest Stable Version License

Lumen Passport

Lumen porting of Laravel Passport. The idea come from https://github.com/dusterio/lumen-passport but try to make it transparent with original laravel passport

Dependencies

  • PHP >= 7.3.0
  • Lumen >= 8.0

Installation

First of all let's install Lumen Framework if you haven't already.

composer create-project --prefer-dist laravel/lumen lumen-app && cd lumen-app

Then install Lumen Passport (it will fetch Laravel Passport along):

composer require nomadnt/lumen-passport

Configuration

Generate your APP_KEY and update .env with single command

sed -i "s|\(APP_KEY=\)\(.*\)|\1$(openssl rand -base64 24)|" .env

Configure your database connection (ie to use SQLite) This is how your .env file should looking after the changes

APP_NAME=Lumen
APP_ENV=local
APP_KEY=<my-super-strong-api-key>
APP_DEBUG=true
APP_URL=http://localhost:8000
APP_TIMEZONE=UTC

LOG_CHANNEL=stack
LOG_SLACK_WEBHOOK_URL=

DB_CONNECTION=sqlite

CACHE_DRIVER=file
QUEUE_CONNECTION=sync

Copy the Lumen configuration folder to your project

cp -a vendor/laravel/lumen-framework/config config

Update guards and provider section of your config/auth.php to match Passport requirements

<?php

return [
    ...

    'guards' => [
        'api' => ['driver' => 'passport', 'provider' => 'users']
    ],

    ...

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

    ...
];

You need to change a little the bootstrap/app.php file doing the following:

<?php

...

// enable facades
$app->withFacades();

// enable eloquent
$app->withEloquent();

...

$app->configure('app');

// initialize auth configuration
$app->configure('auth');

...

// enable auth and throttle middleware
$app->routeMiddleware([
    'auth'     => App\Http\Middleware\Authenticate::class,
    'throttle' => Nomadnt\LumenPassport\Middleware\ThrottleRequests::class
]);

...

// register required service providers

// $app->register(App\Providers\AppServiceProvider::class);
$app->register(App\Providers\AuthServiceProvider::class);
$app->register(Laravel\Passport\PassportServiceProvider::class);
// $app->register(App\Providers\EventServiceProvider::class);

...

Create database.sqlite

touch database/database.sqlite

Lauch the migrations

php artisan migrate

Install Laravel passport

# Install encryption keys and other necessary stuff for Passport
php artisan passport:install

The previous command should give back to you an output similar to this:

Encryption keys generated successfully.
Personal access client created successfully.
Client ID: 1
Client secret: BxSueZnqimNTE0r98a0Egysq0qnonwkWDUl0KmE5
Password grant client created successfully.
Client ID: 2
Client secret: VFWuiJXTJhjb46Y04llOQqSd3kP3goqDLvVIkcIu

Registering Routes

Now is time to register the passport routes necessary to issue access tokens and revoke access tokens, clients, and personal access tokens.
To do this open you app/Providers/AuthServiceProvider.php and change the boot function to reflect the example below.

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Carbon;

// don't forget to include Passport
use Nomadnt\LumenPassport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        // 
    }

    /**
     * Boot the authentication services for the application.
     *
     * @return void
     */
    public function boot()
    {
        // register passport routes
        Passport::routes();

        // change the default token expiration
        Passport::tokensExpireIn(Carbon::now()->addDays(15));

        // change the default refresh token expiration
        Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));
    }
}

User model

Make sure your user model uses Passport's HasApiTokens trait, eg.:

<?php

namespace App;

use Illuminate\Auth\Authenticatable;
use Laravel\Passport\HasApiTokens;
use Laravel\Lumen\Auth\Authorizable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;

class User extends Model implements AuthenticatableContract, AuthorizableContract
{
    use HasApiTokens, Authenticatable, Authorizable;

    // rest of the model
}

Access Token Events

Prune and/or Revoke tokens

If you want to revoke or purge tokens on event based you have to create related Listeners and register on your app/Http/Providers/EventServiceProvider.php istead of using deprecated properties Passport::$revokeOtherTokens = true; and Passport::$pruneRevokedTokens = true;

First you need to make sure that EventServiceProvider is registered on your bootstrap/app.php

<?php

...

// $app->register(App\Providers\AppServiceProvider::class);
$app->register(App\Providers\AuthServiceProvider::class);
$app->register(Laravel\Passport\PassportServiceProvider::class);
$app->register(App\Providers\EventServiceProvider::class);

...

Then you need to listen for AccessTokenCreated event and register your required listeners

<?php

namespace App\Providers;

use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider{

    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'Laravel\Passport\Events\AccessTokenCreated' => [
            'App\Listeners\RevokeOtherTokens',
            'App\Listeners\PruneRevokedTokens',
        ]
    ];
}

Create the app/Listeners/RevokeOtherTokens.php file and put the following content

<?php

namespace App\Listeners;

use Laravel\Passport\Events\AccessTokenCreated;
use Laravel\Passport\Token;

class RevokeOtherTokens
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  \App\Events\OrderShipped  $event
     * @return void
     */
    public function handle(AccessTokenCreated $event)
    {
        Token::where(function($query) use($event){
            $query->where('user_id', $event->userId);
            $query->where('id', '<>', $event->tokenId);
        })->revoke();
    }
}

Create the app/Listeners/PruneRevokedTokens.php file and put the following content

<?php

namespace App\Listeners;

use Laravel\Passport\Events\AccessTokenCreated;
use Laravel\Passport\Token;

class PruneRevokedTokens
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  \App\Events\AccessTokenCreated  $event
     * @return void
     */
    public function handle(AccessTokenCreated $event)
    {
        Token::where(function($query) use($event){
            $query->where('user_id', $event->userId);
            $query->where('id', '<>', $event->tokenId);
            $query->where('revoked', true);
        })->delete();
    }
}