Back to Course |
How to Build Laravel 11 API From Scratch

Authentication with Laravel Passport and Password Grant Type

This lesson will cover API authentication using the Laravel Passport package. If you look at the Passport documentation, it is huge, and for someone new to API authentication, it would be hard to understand and use.

We have covered Sanctum, which I recommend using, so we will check the basics of Passport in this lesson.


You must understand that Passport is a server based on the OAuth2 standard. This standard isn't from Laravel or PHP. It's a general web standard for authentication applications.

The Laravel Passport is based on the PHP OAuth 2.0 Server. But that server follows the OAuth specification. You would need to learn these things if you wanted to look deeper into how OAuth works and how to use it elsewhere.


You can install Laravel passport using an artisan command install:api and passing --passport as an option.

php artisan install:api --passport
php artisan migrate

Next, you need to configure your application to use Passport. In the User Model, add the Laravel\Passport\HasApiTokens trait.

app/Models/User.php:

use Laravel\Passport\HasApiTokens;
 
class User extends Authenticatable
{
use HasFactory, Notifiable;
use HasApiTokens;
 
// ...
}

Finally, add the passport guard driver in the config/auth.php configuration.

return [
// ...
 
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
 
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
 
// ...
];

Now all protected routes can have the auth:api Middleware.

routes/api.php:

Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:api');
 
Route::apiResource('categories', \App\Http\Controllers\Api\CategoryController::class)
->middleware('auth:api');
 
Route::get('products', [\App\Http\Controllers\Api\ProductController::class, 'index']);

If we try to get a list of categories, we will get a 401 Unauthenticated message.

To log in and get the data, we have to do two API calls. The first call is to get a token. Passport provides a specific route /oauth/token. To this request, we need to send data grant_type, client_id, client_secret, username (email in our case), password, and optional scope.

First, we must generate a password grant client using an artisan command.

php artisan passport:client --password

After sending the request, as a result, we get two tokens: one is the access_token, which needs to be sent with every API request, and the second is a refresh_token in case the first one expires.

Now, if we provide access_token as a Bearer authentication, we can see a list of the categories.


Now, let's talk about expired data. This feature Sanctum doesn't have, which may be a reason for you to use Passport instead.

By default, the token expires after one year. But if you want the token to expire sooner, you can set it in the AppServiceProvider. In this example, the token will expire after fifteen days.

app/Providers/AppServiceProvider.php:

use Laravel\Passport\Passport;
 
class AuthServiceProvider extends ServiceProvider
{
// ...
public function boot(): void
{
$this->registerPolicies();
 
Passport::tokensExpireIn(now()->addDays(15));
}
}

When the token expires to get a new access_token you need to do the same request to /oauth/token but with the refresh_token instead of a username and password, and the grant_type now is refresh_token.

When sending API requests, the new access_token needs to be used.