In this tutorial, you will learn how you can use Laravel Passport to create your own full-fledged OAuth2 server.
If you have ever had to create an OAuth server you would agree with me that it can be difficult and time-consuming. Luckily, there is a Laravel package that makes this job easier: Laravel Passport. In this article, we will consider how you can use this amazing package to create your own OAuth server.
For this article, we will be leveraging on an existing Laravel application. A todo application built using Laravel. We will assume, for the sake of this article, that you have created the application and it already works, but you want to add an OAuth server so other applications can connect to the service securely.
The source code to the todo application is available on GitHub.
⚠️ This is not an OAuth or Laravel tutorial, so this article will focus solely on how you can use Laravel Passport to create an OAuth server on an existing application. If you want to learn more about Laravel or OAuth, you can look here.
Before we start setting up, make sure you have the following requirements ready as they will be necessary to follow through this article:
Now that the requirements are defined, let’s move on. The first thing you need to do is download or clone the entire repository to the application we want to create.
Anatomy of the downloaded repository
Let us quickly look at what we have downloaded. There are three directories; all of them are Laravel applications. In the directory we have:
Copy the todo application without OAuth installed as that is what we will be working with.
Setting up our starting point to-do application
To set up the todo application, copy the directory todoapp - no oauth server
to a different directory and rename it to whatever you wish to rename it to.
For the sake of brevity, we will be using SQLite to create a quick connection to a database. Create a new and empty file: ./database/database.sqlite
.
Next, copy the .env.example
file from the root of your project to .env
and in the new file, change the DB_CONNECTION
key to sqlite
. Now delete every other DB_*
key in the .env file leaving only the DB_CONNECTION
key. If you cannot find the .env.example
file, it is because it may be hidden in your file system. Open the project in Sublime Text or your preferred code editor and you’ll see the file.
To get started, cd
to your project folder in your terminal and run the commands below to install the composer packages, run the migration on the database, and generate an application key respectively:
1# @see https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx on how to install Composer globally 2 $ composer install 3 4 # Run migrations on the database 5 $ php artisan migrate 6 7 # Generate a secure application key 8 $ php artisan key:generate
After the commands have finished running, run the command below to start a PHP server using artisan.
1$ php artisan serve
? The artisan serve command quickly brings up a PHP server and helps you quickly run your Laravel application without having to worry about setting up Virtual Hosts.
Now, when you visit http://127.0.0.1:8000 you should see the Laravel homepage. Click on the register and create a new account, we will need this later.
Once you’re in the application, click the “Add” button to add a bunch of to-dos to your application. You can also tick a few as completed while you are at it. When you are done you should have something similar to this:
Now that the application is running correctly, you should return to your command-line and terminate the server by using cmd+c
(ctrl+c on windows).
Installing and configuring Laravel Passport
The first thing we would do is install Laravel Passport. We can do so by running the following command on our terminal:
1$ composer require laravel/passport
This will install the Laravel Passport composer package to our Laravel application, now if you are using Laravel 5.5 or higher, (our current application is) then that is all you need to do to configure Laravel Passport. However, if you are using Laravel 5.4 or lower, you will need to register the Passport service provider in the providers
array of your config/app.php
configuration file:
1Laravel\Passport\PassportServiceProvider::class,
Now, you need to run the migration that will create all the required database tables that Laravel Passport will need. To do this run:
1$ php artisan migrate
Next, you will need to run the command that will generate an encryption key. This encryption key will let passport securely generate access tokens. The command will also create a personal access client and a password client for us.
1$ php artisan passport:install
Next, add the Laravel\Passport\HasApiTokens
trait to your App\User
model. This trait will provide some helper methods which allow you to inspect the authenticated user’s token and scopes:
1use Laravel\Passport\HasApiTokens; 2 3 class User extends Authenticatable { 4 use HasApiTokens, Notifiable; 5 }
Open the AuthServiceProvider
and inside the register
method of the class make a call to Passport::routes
as shown below (Note that you need to add the use
line to import the Laravel Passport package):
1use Laravel\Passport\Passport; 2 // ... 3 4 class AuthServiceProvider extends ServiceProvider 5 { 6 // ... 7 8 public function boot() 9 { 10 $this->registerPolicies(); 11 12 Passport::routes(); 13 } 14 }
Now, to the last part of configuring Laravel Passport. Open the ./config/auth.php
file. Set the driver
option of the api
authentication guard to “passport”. This will make sure your application uses Passport’s TokenGuard
while authenticating incoming API requests:
1'guards' => [ 2 //... 3 4 'api' => [ 5 'driver' => 'passport', 6 'provider' => 'users', 7 ], 8 ],
With that we have finished configuring Laravel Passport and we are ready to start using it in our application.
Adding a User Interface for managing OAuth clients and tokens
Since we have finished installing Laravel Passport, we want to leverage on some of the things Laravel Passport offers us out of the box. One of them is a User Interface where users can manage client applications, revoke access tokens etc.
Run the command below:
1$ php artisan vendor:publish --tag=passport-components
This will publish some Vue components for plug-and-play usage. If you look at the ./resources/assets/js/components
directory, you should see a passport directory with three Vue components inside. Let’s load them up into the application so we can use them.
Open the ./resources/assets/js/app.js
file and in there paste in the following right under the todos
component (Note that it MUST be added before the const app = new Vue
instance is created):
1Vue.component( 2 'passport-authorized-clients', 3 require('./components/passport/AuthorizedClients.vue') 4 ); 5 6 Vue.component( 7 'passport-clients', 8 require('./components/passport/Clients.vue') 9 ); 10 11 Vue.component( 12 'passport-personal-access-tokens', 13 require('./components/passport/PersonalAccessTokens.vue') 14 );
In the above, we are registering the Vue components that were published using the artisan vendor publish command above. This will make the components available throughout our application if we wanted to use them. Great!
Now run the command below to install the Node packages and rebuild our assets using webpack:
1$ npm install 2 $ npm run dev
After the build is completed, we will need to create a settings page where the passport views will reside.
Create a new controller using the command below
1$ php artisan make:controller SettingsController
Open the newly created controller and replace with the code below:
1<?php 2 3 namespace App\Http\Controllers; 4 5 use Illuminate\Http\Request; 6 7 class SettingsController extends Controller 8 { 9 public function __construct() 10 { 11 $this->middleware('auth'); 12 } 13 14 public function index() 15 { 16 return view('settings'); 17 } 18 }
In the controller above we setup a middleware that only allows logged-in users to access the index
method. Next, we render a view settings
.
Create a new view settings.blade.php
in the ./resources/views
directory and in there add the code below:
1@extends('layouts.app') 2 3 @section('content') 4 <div class="container"> 5 <div class="row"> 6 <div class="col-md-8 col-md-offset-2"> 7 <passport-authorized-clients></passport-authorized-clients> 8 <passport-clients></passport-clients> 9 <passport-personal-access-tokens></passport-personal-access-tokens> 10 </div> 11 </div> 12 </div> 13 @endsection
In the code above we have added the Vue components we imported earlier into our view. This will generate an entire OAuth management tool for the user no further work needed on that front.
Next, we will create a route to expose the controller and view we just created. To do this, open the ./routes/web.php
file and add the route below:
1Route::get('/settings', 'SettingsController@index')->name('settings');
Finally, we want to add a Settings link to the page so it is easily accessible. Open the ./resources/views/layouts/app.blade.php
and on line 55 (or anywhere in the Bootstrap navigation menu you want) add the code below:
1<li><a href="{{ route('settings') }}">Settings</a></li>
This will just create a link to the settings page. Now run php artisan serve
again like you did before and visit the link http://127.0.0.1:8000, then log in and click Your Name > Settings; you should see a page like this below:
Creating an OAuth application
Now you should go ahead and create an OAuth client, we will be needing it in the next section. Click the “Create new client” link and create a new OAuth application. For the tutorial, set the Redirect URL to http://127.0.0.1:8001/callback.
⚠️ When creating your own OAuth application consumer, the redirect URL will be the address to the actual callback on the consumer.
Once you have created it you should see your client with an ID and Secret. We will use this information to test our consumer application.
Exposing an endpoint to test the Laravel Passport OAuth Server implementation
The last thing we will do with our OAuth server enabled application is, create an endpoint that will respond to request using Laravel Passport.
Open the ./routes/api.php
file and add the following route:
1Route::middleware('auth:api')->get('/todos', function (Request $request) { 2 return $request->user()->todos; 3 });
The route above sets a middleware auth:api
which instructs the route to only allow applications authenticated with Laravel Passport to access this route. Then once it’s validated, it returns all the user’s todos.
? ****
**$request->user()**
is tied to the access token of the validated user, and**->todos**
is a relationship that returns the todos of that user.
That’s all! You have successfully added an OAuth server to the application! Your users can now create applications that can access the application without using their username and password.
? You can also create Personal Access Tokens using the settings screen of the OAuth application. Personal Access Tokens just give you instant access tokens you can use to make requests to the application.
We will continue the article to see how we can implement a consumer application. This will enable us test our OAuth2 enabled Laravel application.
To test our OAuth server, we will need to create a separate application that is not connected in any way to the Oauth2 server. Something brand new.
Create a new Laravel project outside our current todo application:
1$ laravel new consumerapp
Once the application has been created successfully, we will install Guzzle. We need the package to make HTTP requests. To install Guzzle, run:
1$ composer install guzzlehttp/guzzle
When the package installation is complete, run the command below to start another PHP server using artisan:
1$ php artisan serve --port=8001
This should start a server in the URL http://127.0.0.1:8001.
Now, to add the needed routes for testing, open the routes file ./routes/web.php
and in there replace the entire file with the following code:
1<?php 2 3 use Illuminate\Http\Request; 4 5 Route::get('/', function () { 6 $query = http_build_query([ 7 'client_id' => 3, // Replace with Client ID 8 'redirect_uri' => 'http://127.0.0.1:8001/callback', 9 'response_type' => 'code', 10 'scope' => '' 11 ]); 12 13 return redirect('http://127.0.0.1:8000/oauth/authorize?'.$query); 14 }); 15 16 Route::get('/callback', function (Request $request) { 17 $response = (new GuzzleHttp\Client)->post('http://127.0.0.1:8000/oauth/token', [ 18 'form_params' => [ 19 'grant_type' => 'authorization_code', 20 'client_id' => 3, // Replace with Client ID 21 'client_secret' => 'CLIENT_SECRET', // Replace with client secret 22 'redirect_uri' => 'http://127.0.0.1:8001/callback', 23 'code' => $request->code, 24 ] 25 ]); 26 27 session()->put('token', json_decode((string) $response->getBody(), true)); 28 29 return redirect('/todos'); 30 }); 31 32 Route::get('/todos', function () { 33 $response = (new GuzzleHttp\Client)->get('http://127.0.0.1:8000/api/todos', [ 34 'headers' => [ 35 'Authorization' => 'Bearer '.session()->get('token.access_token') 36 ] 37 ]); 38 39 return json_decode((string) $response->getBody(), true); 40 });
⚠️ Replace the client ID and secret with the values that were given to you when the application was being created. You can get this in the Settings section of your OAuth 2 enabled application.
In the code above, we have defined 3 routes. In the first route, we use http_build_query
to generate URL parameters which we send to the Laravel Passport enabled OAuth server. The parameters are client_id
, redirect_uri
(which must be the same as the one you used when creating the application) etc. Then we redirect to the URL.
The next route is the callback handler. It receives a code from the OAuth2 server and then you use the code and the other parameters, including the client_secret
, to make a request which will then exchange the code with an access token. When it gets the access token, it saves it to the session and redirects to the last route.
The last route in the code above takes the access token from the session and uses it to make a request to the /api/todos
endpoint on the OAuth2 applications server. If the access token is still active, you will now be able to see a list of the user’s to-dos displayed on the screen!
To test this flow, you can visit the consumer URL: http://127.0.0.1:8001 and then you should see the flow in action, and finally ending with the list of todos on the screen.
In this article, we have been able to create a full-fledged OAuth2 server for our Laravel Application using Laravel Passport! Laravel Passport makes it super easy and it takes only a few steps as we have seen in the article to make your application OAuth 2 enabled.
If you have any questions, please leave them below and if you have feedback, also leave them below. You can star the GitHub repo for reference if you wish.