Elliot
Elliot's Blog

Elliot's Blog

Authenticating Socialite on a Laravel Passport back-end

Elliot's photo
Elliot
·Aug 8, 2022·

3 min read

Subscribe to my newsletter and never miss my upcoming articles

Play this article

Table of contents

  • Server App
  • Client App

This took TOO long to figure out. Both first-party packages of Laravel, and yet unusually difficult to debug, and really simple fixes (despite a number of rabbit-holes that might have led to all sorts of refactoring).

Here's the context:

  • I'd like a Jetstream app to be an Identity Server
  • I'd like other Laravel apps to be able to authenticate against it

Easy right? Add Passport to the server, add socialite to the clients, job done. Well, in the end, yes - but the journey was harder than that.

Server App

composer require laravel/passport

So yes, require Passport on the server in the usual way. It isn't as disruptive to Jetstream/Sanctum as you'd think. Remember to commit first, just in case.

In the User model will then need to replace Laravel\Sanctum\HasApiTokens with Laravel\Passport\HasApiTokens.

Add Passport::routes() in one of your Service Providers (RouteServiceProvider?) - in the boot section.

In config/jetstream.php, change the Jetstream Guard to passport.

Amend config/auth.php. You need to add to the guards array:

'guards' => [
    //...
    'api' => [
            'driver' => 'passport',
            'provider' => 'users',
            'hash' => false,
    ],
],

In the routes file for API: api.php change the Route middleware from auth:sanctum to auth:api. (This one got me for ages, and was the last thing I did. Without it, you can successfully authenticate against the server, but the returned user fields will all be null when the client then uses the token).

Final thing - it could be worth overriding your default Client model to allow first-party clients to authenticate without a confirmation. You may need to adjust the logic in that override.

You can probably remove Sanctum now. Might want to check for any other uses first.

You will also need to create a way for users to create clients and tokens if you need them to - I took inspiration from this package. I didn't pull it in, but instead reworked the views and Livewire components into my app. Because.

Client App

You can use Socialite with the LaravelPassport provider as usual i.e.

  • Pull in the package (you want laravel/socialite as well as socialiteproviders/laravelpassport)
  • Register the providers (noting you don't register the socialite provider, unless using it for e.g. GitHub)
  • Register the listeners
  • Register the routes
  • Add the migrations to store the id, token and refresh_token in your User model, or in a related model.
  • Remove the login button, or supplement it with a login/register button that takes you to the the Socialite redirect.

And finally - add the necessary config. This one got me. You need to register a URL for the Passport server somewhere, and it is not document (or wasn't, I've raised a Pull Request). You need the following to be covered in services.php:

  'laravelpassport' => [
        // These are the usual Socialite/OAuth settings
        'client_id' => env('LARAVELPASSPORT_CLIENT_ID'),
        'client_secret' => env('LARAVELPASSPORT_CLIENT_SECRET'),
        'redirect' => env('LARAVELPASSPORT_REDIRECT_URI'),

        // And this is how you tell Socialite where your Passport app lives
        'host' => env('LARAVELPASSPORT_HOST'), 
    ],

And that's it. You should now be able to authenticate one Laravel App against another one, and get back basic user details by return.

 
Share this