Integrate Passport to your Laravel API’s

Hello everyone, welcome back to justlaravel.com. I am back with another tutorial, here I will show you how to integrate Passport(a Laravel’s API authentication package) into your Laravel applications.
Here I will create 2 Laravel projects, one is an API and other is the API consumer app. It basically means I will create an API with Passport package integrated. A normal Laravel app where I call the API and show its data.
Let’s get started!
-
Laravel API
-
Consumer APP
Working Demo Project on Github
You can also watch the video on YouTube here.
First, let us create an API. In the terminal/command prompt run the following command to create a new Laravel project.
laravel new sampleAPI
Passport Install
Now, install the Passport package using composer,
composer require laravel/passport
Now, register the Passport service provider in the providers array of your config/app.php
file.
'providers' => [ ... ... ... Laravel\Passport\PassportServiceProvider::class, ],
Now, run the following commands to setup passport, but before that setup database details in .env
file ordatabase.php
(app\config\database.php
) file.
php artisan migrate
The migrate command creates some default Laravel tables and some new tables for authentication which comes from passport.

Now run,
php artisan passport:install
it creates some client id’s and secrets, which can be later used by consumer app to access the API.
Working Demo Project on Github
Passport Configure
Here we need to make some configuration changes to our Laravel app so Passport can be used in the API authentication.
Now, in the User model(app\User.php
) we need to add HasApiTokens
trait from Passport package,
<?php namespace App; .... .... .... use Laravel\Passport\HasApiTokens; class User extends Authenticatable { use HasApiTokens, Notifiable; .... .... ... }
Next, we need to add some routes which passport uses, so in the AuthServiceProvider<code>(</code>app/Providers/AuthServiceProvider.php
) add the below extra lines,
<?php namespace App\Providers; ... use Laravel\Passport\Passport; class AuthServiceProvider extends ServiceProvider { .... .... .... public function boot() { $this->registerPolicies(); Passport::routes(); } }
And finally, in auth.php
file(config/auth.php
), I will set the API driver to passport.
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', 'hash' => false, ], ],
Generate data – Faker | DB Seeding
As this is not a real API and just for tutorial purpose, I can stuff with some dummy data.
Now I will generate some random fake data so we can fill up the API with some data. We can use an inbuilt Laravel package Faker
to get us some data.
I will now create a copy of users table and fill that table with dummy users. Create a new details
table by running the following SQL query.
-- Dumping structure for table lar_pas.details CREATE TABLE IF NOT EXISTS `details` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL, `email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL, `email_verified_at` timestamp NULL DEFAULT NULL, `password` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL, `remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `details_email_unique` (`email`) )
Let’s create a seeder for details
table, run the following command,
php artisan make:seed DetailsTableSeeder
In the Seeder file(database\seeds\DetailsTableSeeder.php
), loop and create 250 random users, paste the following in the run()
function of the seeder.
public function run() { $faker = Faker\Factory::create(); for($i = 0; $i < 250; $i++) { App\Detail::create([ 'name' => $faker->name, 'email' => $faker->email, 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 'remember_token' => Str::random(10), ]); } }
Now, in the Database seeder file(database\seeds\DatabaseSeeder.php
), call this DetailsTableSeeder
public function run() { $this->call(DetailsTableSeeder::class); }
Now, we can run the migrate command which fills us the database.
php artisan migrate --seed

Routing | Getting info from DB
Now, lets create a route to the controller which gets all the user data, so in the api routes(\routes\api.php
) place the following route.
Route::get('/users', 'DetailController@index');
Its time to create a new controller named DetailController
as used in the above route.
php artisan make:controller DetailController
In the controller(app\Http\Controllers\DetailController.php
), lets create a function and fetch all the data from user table.
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Detail; class DetailController extends Controller { public function index(){ $user = Detail::all(); return $user; } }
Now if we run the application(php artisan serve
) and go to route(http://127.0.0.1:8000/api/users
), it will display us all the users, but the thing here is everyone can see the details of the API, it just a normal app. An API needs authentication, so now let us use the passport package we have installed earlier.
Working Demo Project on Github
Protect the routes with Passport
Let’s protect the route which we created earlier for displaying the users. Open api.php file(routes\api.php
) and add middleware authentication to the route.
Route::get('users', 'UserController@index')->middleware('auth:api');
Now if we check the link(http://127.0.0.1:8000/api/users
), we are now unable to access the data as it is protected with the passport and it needs some authentication.
Registration and Generating OAuth client_id and client_secret
So to access we need some client_id and client_secret, we have got some of these when I ran php artisan passport:install
earlier and these are stored in a table called oauth_clients
.
Now, if any user wants to access our API, we need them to register to the API and then generate those client_id and client_secret for them so they can access the API.
For registration view, I used the basic files generated that comes from Laravel’s auth scaffolding. So I ran, php artisan make:auth
and removed all unnecessary files and kept only view files also removed its controllers and routes.
So make a new route in (routes\web.php
) calling the registration view.
Route::get('/register', function(){ return view('auth.register'); });

So when the registration form is submitted, a new user is created and also an OAuth client id and secret are generated for that user.
The route(routes/web.php
),
Route::post('/register', 'PassportController@register');
In the register function, I first save the user and then get its id
and use it in oauth_clients
table. So as am dealing with one or more insertions for an operation, I use a concept called DB Transactions, what this does is, it either inserts in both of the tables or none of them. As I don’t need any sort of incomplete operations here.
Assume a case where the user is created and got an error in creating a record in oauth_clients table, in this case, there is a problem, so to avoid such situations there is a concept called Transactions and Atomicity property of the transaction is what we use here.
So the basic flow of operation looks like,
public function register(Request $request) { // begin the transaction DB::beginTransaction(); try { ... ... .... try { // Save User } catch(\Exception $e){ // if error in saving user, rollback - dont insert anything DB::rollback(); } try { // Save in oauth Clients } catch(\Exception $e){ // if error in creating oauth_clients, rollback - dont insert anything DB::rollback(); } // if everything is fine, complete both the inserts(user, oauth_clients) DB::commit(); } catch (\Exception $e) { // if error any errors, rollback - dont insert anything DB::rollback(); } }
In the registration form, I check for some basic validations and then proceed to insert the user.
$validator = Validator::make($request->all(),[ 'name' => 'required|string', 'email' => 'required|string|email|unique:users', 'password' => 'required|string|confirmed' ]); if ($validator->fails()) { return Redirect::back() ->withErrors($validator) ->withInput(); } else{ // insert user }
Now, in the else part, I will create a new user, enclosing with try catch block for rollback scenario.
else{ try { $user_save = User::create([ 'name' => $request->name, 'email' => $request->email, 'password' => bcrypt($request->password) ]); } catch(\Exception $e){ DB::rollback(); $message = $e->getMessage(); return response()->json(['error' => 1, 'message' => $message]); } }
After the user is created, I will get the inserted id to use it the oauth_clients table.
$insertedId = $user_save->id;
Now, there is some data to be inserted in oauth_clients table.
Secret – A random 40 character string
$secret = Str::random(40);
Name – Any name
Password Client – As it is password access client the value should be ‘1’
Personal Access Client – It should be 0 as it is a password client and not personal
Redirect – A redirect URL
Revoked – whether the client revoked the access or not, it should be ‘0’ as we need access to the API
So the insert query for oauth_clients will look as follows,
try { $oauth_clients = OAuthClient::create([ "user_id" => $insertedId, "secret" => $secret, "name" => "Password Grant", "revoked" => 0, "password_client" => 1, "personal_access_client" => 0, "redirect" => "http://localhost", ]); } catch(\Exception $e){ DB::rollback(); $message = $e->getMessage(); return response()->json(['error' => 1, 'message' => $message]); }
After successful insertion of both queries, I can use DB commit and give the user the required client id and secret.
// user insert // oauth clients insert DB::commit(); return response()->json([ 'message' => 'Successfully created user!', 'client_secret' => $secret, 'client_id' => $oauth_clients->id ], 201);
The final register function looks as below.
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use DB; use App\User; use App\OAuthClient; use Str; use Validator; use Redirect; class PassportController extends Controller { public function register(Request $request) { DB::beginTransaction(); try { $validator = Validator::make($request->all(),[ 'name' => 'required|string', 'email' => 'required|string|email|unique:users', 'password' => 'required|string|confirmed' ]); if ($validator->fails()) { return Redirect::back() ->withErrors($validator) ->withInput(); } else{ try { $user_save = User::create([ 'name' => $request->name, 'email' => $request->email, 'password' => bcrypt($request->password) ]); } catch(\Exception $e){ DB::rollback(); $message = $e->getMessage(); return response()->json(['error' => 1, 'message' => $message]); } } $insertedId = $user_save->id; $secret = Str::random(40); try { $oauth_clients = OAuthClient::create([ "user_id" => $insertedId, "secret" => $secret, "name" => "Password Grant", "revoked" => 0, "password_client" => 1, "personal_access_client" => 0, "redirect" => "http://localhost", ]); } catch(\Exception $e){ DB::rollback(); $message = $e->getMessage(); return response()->json(['error' => 1, 'message' => $message]); } DB::commit(); return response()->json([ 'message' => 'Successfully created user!', 'client_secret' => $secret, 'client_id' => $oauth_clients->id ], 201); } catch (\Exception $e) { DB::rollback(); // something went wrong $message = $e->getMessage(); return response()->json(['error' => 1, 'message' => $message]); } } }

We are done with the API part.
Working Demo Project on Github
Consumer App
Now, let us create a consumer app, where this API data is fetched and displayed.
Create a new App
Let us create a new Laravel app,
laravel new consumerApp
Install GuzzleHttp
Here I use GuzzleHttp
package to call the API just created. So let us install it. In the consumerApp root, run the following command to install it,
composer require guzzlehttp/guzzle
Authenticate the API and get the data
Now, let us authenticate the API and get data from the API. Here it is only one function so I will manage everything in a single function in the routes file(routes\web.php
)
Assuming the API we created is running at http://localhost:8000
Route::get('/', function () { $client = new GuzzleHttp\Client; try { $response = $client->post('http://localhost:8000/oauth/token', [ 'form_params' => [ 'client_id' => the_client_id_obtained_when_registered_to_API, 'client_secret' => 'the_client_secret_obtained_when_registered_to_API', 'grant_type' => 'password', 'username' => 'username_used_for_registering', 'password' => 'password_used_for_registering', 'scope' => '*', ] ]); $auth = json_decode( (string) $response->getBody() ); $response = $client->get('http://localhost:8000/api/users', [ 'headers' => [ 'Authorization' => 'Bearer '.$auth->access_token, ] ]); $details = json_decode( (string) $response->getBody() ); ?> ... }catch(..){ .... } }
I will call the url http://localhost:8000/oauth/token
with post method, this URL is one of the route created by the passport package.
As you see there are some form_params
to be passed to it, client_id
and client_secret
are the one which obtained when registered to the API and the grant_type
is password, and also we need to provide the username
and password
used for registering to the API, also scope
should be passed as *
With the above call, we get an access_token
and pass this access_token as a Header to the actual API call to get all the details.
$auth = json_decode( (string) $response->getBody() ); $response = $client->get('http://localhost:8000/api/users', [ 'headers' => [ 'Authorization' => 'Bearer '.$auth->access_token, ] ]);
Now, the obtained data is stored in some variable, so we can loop it and display the data accordingly.
$details = json_decode( (string) $response->getBody() );
Working Demo Project on Github
Display the data
Here I will use a basic HTML table to display the data.
<table style="width:100%; border: 1px solid black; border-collapse: collapse;"> <tr style="border: 1px solid black; border-collapse: collapse;"> <td>#</td> <td>Name</td> <td>Email</td> </tr> <?php foreach ($details as $detail) { ?> <tr> <td><?php echo $detail->id; ?></td> <td><?php echo $detail->name; ?></td> <td><?php echo $detail->email; ?></td> </tr> <?php } ?> </table>
Run the app
So now lets run the application and see. As the API is running on default port 8000. Let us change the port and run it.
php artisan serve --port 8594
So now when we open http://localhost:8594/
we can see the data, which looks like the below image.

So that’s it, guys! We have successfully created an API with passport authentication and also consumed that API in another application.
Thank you for the tutorial , but i want ask to you , at this condition i must doing login attempt twice at consumer laravel and laravel passport ?
In Laravel Passport App you will register to the API, and in consumer App, you will login to the API to access the data.
Hi, i am really happy to come over your tutorial.
I have a few questions.
1. if i want to show a dashboard where users can manage their authclients created rather than using the default vue componet, how do i go about that.
2. is there a way to implement the GuzzleHttp package inside the api application where only a link will be will be provided to the consuming app for ease. or is there a way out to do that other done the GuzzleHttp package
Thanks