Authenticating Socialite on a Laravel Passport backend
Table of contents
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 start with a new branch/clean state, just in case.
In the User model, you 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
.
Moving to auth:api 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 associaliteproviders/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
andrefresh_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.
Did you find this article valuable?
Support Elliot by becoming a sponsor. Any amount is appreciated!