Setting up OAuth in Lumen using Laravel Passport

A Software Developer reviewing a Pull Request on GitHub

Laravel Passport is the flagship OAuth server created by Taylor Otwell for the Laravel framework. It is simple to set up and use as are all packages made for Laravel by Taylor and the incredible Laravel community.

The same should be possible for Lumen, right? No, Laravel Passport’s Lumen support has never been released and there have been some walkarounds to do this. Some developers gave up and tried incorporating other third-party OAuth packages which are more complicated and may not have great support.

In this confusion, one man emerged and saved us all. His name is Denis Mysenko who built a lumen package suitably named Lumen Passport. This package was a lifesaver as it provides the much-needed support for Passport on Lumen. It is the best implementation so far as compared to the rest.

Let me save you the time to figure out how to setup things by providing this short tutorial. Follow the following steps and thank me later.

Install Lumen Passport in your Lumen project

Use composer command or install by adding it to composer.json file. Ensure the version matches the one below:

composer require dusterio/lumen-passport

Or add it to composer.json file:

{   
"require": {
"dusterio/lumen-passport": "^0.2.0"
}
}

2.Modify the bootstrap/app.php file

Uncomment the following lines:

// enable use of facades
$app->withFacades();
// enable Eloquent
$app->withEloquent();
// Load auth config files
$app->configure('auth');

3. Create/modify the config/auth.php file and add the following code

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

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

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

4. Register service providers

$app->register(Laravel\Passport\PassportServiceProvider::class);
$app->register(Dusterio\LumenPassport\PassportServiceProvider::class);

5. Add CheckClientCredentials middleware to $routeMiddleware

$app->routeMiddleware([
'auth' => App\Http\Middleware\Authenticate::class,
'client' => \Laravel\Passport\Http\Middleware\CheckClientCredentials::class,
]);

Attach to your routes:

use Illuminate\Http\Request;
$router->get('/test_endpoint', function (Request $request) {
...
})->middleware('client');

or group your routes and give them all the middleware

$router->group(['prefix' => 'api/v1', 'middleware' => 'client'], function() use (&$router){
...
});

6. Run migrations

php artisan migrate

This creates several tables:

- auth_access_tokens
- oauth_auth_codes
- oauth_clients
- oauth_personal_access_clients
- oauth_refresh_tokens

7. Install passport

The following command is used to generate private and public encryption keys used for token generation and it also sets up the necessary routes. The keys are stored in the storage folder.

php artisan passport:install

8. Setup route prefix

This statement is added to your bootstrap/app.php file after registering the service providers.

Dusterio\LumenPassport\LumenPassport::routes($app->router, ['prefix' => 'api/v1/oauth'] );

Modify the prefix to match your preferences.

9. Add HasAPITokens Trait to your User model

use Laravel\Passport\HasApiTokens;
class User extends Model implements AuthenticatableContract, AuthorizableContract
{
     use Authenticatable, Authorizable, HasApiTokens;
     /* Rest of the model here */
}

Generating Tokens

Fake Arcade tokens

You want some tokens, eh? They have been rumoured to be stored deep in Treasure Island and only Jack Sparrow has ever seen them. Do not fear because I will show you thy way and magically generate for you your heart’s desire.

It is quite simple to generate your clients and access tokens.

Let us take an example, you have a mobile app that you would like to securely access an API on the backend. So which tokens would you generate?

The simple way is to consider your app as a client. The client has to be generated and issued the following:

client_id -> integer value
client_secret -> alphanumeric value generated by Passport

This data is provided after issuing the following command which takes you through a step-by-step guide:

php artisan passport:client

The redirect url is a callback url you have to setup where after the user will be redirected to after authorization. In our case we’ll use a different command:

php artisan passport:client --client

This is because we do not have users involved and it’s only a machine-to-machine communication between our first-party client (mobile app) and our microservice API. This can also be used to generate clients for scheduled jobs on your servers that use your APIs.

This means, there is no need for your users to go through the entire OAuth2 authorization code redirect flow. Yay!

If you receive the following error, do not worry, I got you.

In Container.php line 945:
Target [Illuminate\Contracts\Routing\UrlGenerator] is not instantiable.

This is an issue in Lumen where the UrlGenerator contract has not been bound to any instance, so you'll have to do it manually.

Add this to your bootstrap/app.php file:

$app->bind(\Illuminate\Contracts\Routing\UrlGenerator::class, function ($app) {
return new \Laravel\Lumen\Routing\UrlGenerator($app);
});

Here is the full app.php file for comparison:

After going through the steps, you should have a message like the one below:

Password grant client created successfully.
Client ID: 3
Client Secret: RZZyELdtmVrFmujA7NLCep9srvSHsvz91bVTtnnh

We are almost there, in order to acquire your access tokens, we have to make a POST request to [api_prefix]/oauth/token

Remember to replace [api_prexix] with what you set in your bootstrap/app.php file.

Make your request using Postman, curl, httpie or whatever you use to test endpoints and make the request with the following application/json body:

{
"grant_type": "client_credentials",
"scope": "*
"client_id": "[CLIENT_ID]",
"client_secret": "[CLIENT_SECRET]"
}

Replace the values of CLIENT_ID and CLIENT_SECRET with those you had generated using passport:client —client above.

You should now have your much-desired access tokens.

For more information, check out the official Lumen Passport and Laravel Passport docs.

You can also view all necessary files as GitHub gists.