Laravel Socialite OpenID Connect login with PKCE
Sign-in with Dazr Identity: free OpenID Connect, hosted in the EU, with passkeys, email codes and Google or Microsoft accounts behind one button.
You need three values from the developer console: the client ID, the client secret (web server apps only) and the redirect URI you registered. Everything else comes from the discovery document at https://identity.dazr.eu/.well-known/openid-configuration.
Laravel
Laravel Socialite has no generic OpenID Connect driver built in, so add a small custom driver. It sends people to Dazr with PKCE and reads the user from the user info endpoint. Socialite does not read the discovery document, so the endpoints are written out. Register a web server app with the redirect URI https://app.example.eu/auth/dazr/callback.
<?php
// app/Socialite/DazrProvider.php
namespace App\Socialite;
use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\User;
class DazrProvider extends AbstractProvider
{
protected $scopes = ['openid', 'profile', 'email'];
protected $scopeSeparator = ' ';
protected $usesPKCE = true;
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase('https://identity.dazr.eu/oauth/authorize', $state);
}
protected function getTokenUrl()
{
return 'https://identity.dazr.eu/oauth/token';
}
protected function getUserByToken($token)
{
$response = $this->getHttpClient()->get('https://identity.dazr.eu/oauth/userinfo', [
'headers' => ['Authorization' => 'Bearer '.$token],
]);
return json_decode((string) $response->getBody(), true);
}
protected function mapUserToObject(array $user)
{
return (new User)->setRaw($user)->map([
'id' => $user['sub'],
'name' => $user['name'] ?? null,
'email' => $user['email'] ?? null,
]);
}
}
// config/services.php
'dazr' => [
'client_id' => env('DAZR_CLIENT_ID'),
'client_secret' => env('DAZR_CLIENT_SECRET'),
'redirect' => env('DAZR_REDIRECT_URI'),
],
// app/Providers/AppServiceProvider.php, in boot()
use Laravel\Socialite\Facades\Socialite;
use App\Socialite\DazrProvider;
Socialite::extend('dazr', function ($app) {
return Socialite::buildProvider(DazrProvider::class, config('services.dazr'));
});
// routes/web.php
Route::get('/auth/dazr', fn () => Socialite::driver('dazr')->redirect());
Route::get('/auth/dazr/callback', function () {
$dazr = Socialite::driver('dazr')->user();
$user = \App\Models\User::updateOrCreate(
['dazr_sub' => $dazr->getId()],
['name' => $dazr->getName() ?? $dazr->getEmail(), 'email' => $dazr->getEmail()],
);
Auth::login($user);
return redirect('/');
});
sub claim is pairwise: the same for every app of your organisation, different for every other organisation. It never changes for a person, while an email address can. Store sub as the account key and treat email as contact data.
More for developers
Developer docsAll integration guidesAny OpenID Connect libraryPricing