In this article, I will share how to configure Laravel application to act as an OAuth client, connecting to two other laravel projects which will act as OAuth servers. Our example includes Project A and Project B as OAuth servers, and Project C as OAuth client.
+------------+ +------------+
| Project | | Project |
| A | <------+------> | B |
+------------+ | +------------+
|
|
v
+-------------+
| Project |
| C |
+-------------+
By following these steps, we will be able to configure the OAuth servers and get the access token from both servers seamlessly.
Step 1: Installing Laravel Passport Package
To begin, you need to install the Laravel Passport package in the project that you want to configure as an OAuth server.
Run the following commands within the Project A and Project B servers:
composer require laravel/passport
php artisan migrate
php artisan passport:install --uuids
Step 2: Modifying User Model and Configurations
- Add the
Laravel\Passport\HasApiTokens
trait to yourApp\Models\User
model. - Modify the
auth.php
configuration file and define an API authentication guard, setting the driver option topassport
. Refer to the official documentation for detailed guidance.
Step 3: Generating Passport Keys
For first-time deployment of Passport to your application servers, run the passport:keys
command:
php artisan passport:keys
Step 4: Routes and Controller in Project C (OAuth Client)
Route::group(['prefix' => 'api/{server}'], function () {
Route::get('/oauth/authorize',
[OAuthController::class, 'authorizeClient']
)->name('oauth.authorize');
Route::get('/oauth/callback',
[OAuthController::class, 'redirectCallback']
)->name('oauth.callback');
})->middleware(['auth']);
And let’s see the OAuth Controller,
class OAuthController extends Controller
{
use OAuthHelpers;
public function authorizeClient(Request $request, $server)
{
.....
return redirect($this->serverAppUrl($server).'/oauth/authorize?'.$query);
}
public function redirectCallback(Request $request, $server)
{
.....
return to_route('where-you-want-to-redirect');
}
}
Step 4: Creating OAuth Clients, in Project A and B
Execute the following command to create OAuth clients for the Project A and Project B apps:
php artisan passport:client
When asked about the redirect url, make sure to set the correct redirect URL, as this will be the URL we will be redirected once authorized on in Project A, and Project B.
Step 5: Let’s complete the OAuthController in Project C
class OAuthController extends Controller
{
use OAuthHelpers;
public function authorizeClient(Request $request, $server)
{
$request->session()->put('state', $state = Str::random(40));
$query = http_build_query([
'client_id' => $this->clientId($server),
'redirect_uri' => $this->clientRedirectUri($server),
'response_type' => 'code',
'scope' => '',
'state' => $state,
'prompt' => 'no',
]);
return redirect($this->serverAppUrl($server).'/oauth/authorize?'.$query);
}
public function redirectCallback(Request $request, $server)
{
$state = $request->session()->pull('state');
throw_unless(
strlen($state) > 0 && $state === $request->state,
InvalidArgumentException::class
);
$response = Http::post($this->serverAppUrl($server).'/oauth/token', [
'grant_type' => 'authorization_code',
'client_id' => $this->clientId($server),
'client_secret' => $this->clientSecret($server),
'redirect_uri' => $this->clientRedirectUri($server),
'code' => $request->code,
]);
$data = $response->json();
if (isset($data['access_token'])) {
$request->user()->createOauthToken([
'expires_in' => $data['expires_in'] ?? null,
'access_token' => $data['access_token'] ?? null,
'refresh_token' => $data['refresh_token'] ?? null,
]);
}
return to_route('where-you-want-to-redirect');
}
}
Final Note
Once we have the “access_token” from each OAuth server, and we have stored it in the Project C’s database, we can use it in subsequent requests to pull data from Project A and Project B.
Remember, these steps outline the process for connecting Laravel application to two OAuth servers (which are themselves Laravel projects). Adjust URLs, client IDs, and secrets based on the specific use case and requirement.