Skip to content
Posted on:August 10, 2023 | 3 min read

Setting Up OAuth Client to Connect with Multiple OAuth Servers in Laravel

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

  1. Add the Laravel\Passport\HasApiTokens trait to your App\Models\User model.
  2. Modify the auth.php configuration file and define an API authentication guard, setting the driver option to passport. 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.