jeffersongoncalves / laravel-oidc
OpenID Connect for Laravel via a custom Socialite driver. Multi-tenant ready.
Package info
github.com/jeffersongoncalves/laravel-oidc
pkg:composer/jeffersongoncalves/laravel-oidc
Fund package maintenance!
Requires
- php: ^8.2
- firebase/php-jwt: ^6.10|^7.0
- guzzlehttp/guzzle: ^7.8
- illuminate/contracts: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
- laravel/socialite: ^5.10
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.18
- orchestra/testbench: ^9.0|^10.0|^11.0
- pestphp/pest: ^3.7|^4.0
- pestphp/pest-plugin-laravel: ^3.0|^4.0
- phpstan/phpstan: ^2.0
This package is auto-updated.
Last update: 2026-04-26 00:10:02 UTC
README
Laravel OIDC
Laravel OIDC adds first-class OpenID Connect support to Laravel by registering a custom
Laravel Socialite driver named oidc. Unlike vanilla
Socialite — which covers OAuth 2.0 but stops at the userinfo step — this package implements
the OIDC pieces Socialite leaves out: discovery (/.well-known/openid-configuration),
JWKS-based id_token validation, nonce-based replay protection, and PKCE.
It is designed for multi-tenant SaaS: configuration is supplied at runtime, so each tenant can connect its own Azure AD, Okta, Auth0, Google Workspace, Keycloak, or any other spec-compliant OpenID Provider.
Compatibility
| Package | Laravel | PHP |
|---|---|---|
| 1.x | 11.x, 12.x, 13.x | 8.2, 8.3, 8.4 |
Why?
Laravel Socialite ships drivers for fixed providers (GitHub, Google, etc.) and a small set of OAuth 2.0 helpers. It does not:
- Read the IdP's
.well-known/openid-configurationdiscovery document. - Validate the
id_tokenJWT against the IdP's JWKS. - Send and verify a
nonceto mitigate replay attacks. - Make per-request configuration easy in multi-tenant scenarios.
This package adds those pieces while staying inside the Socialite mental model: you still
call Socialite::driver('oidc')->redirect() and ->user().
Installation
composer require jeffersongoncalves/laravel-oidc
Optionally publish the config file:
php artisan vendor:publish --tag="oidc-config"
Configuration
The package works out of the box. For single-tenant apps, set the default IdP in .env:
OIDC_ISSUER_URL=https://login.microsoftonline.com/{tenant-id}/v2.0 OIDC_CLIENT_ID=your-app-client-id OIDC_CLIENT_SECRET=your-app-secret OIDC_REDIRECT_URI=https://your-app.test/sso/callback
For multi-tenant apps, leave the default block empty and supply an OidcConfig at runtime
(see below).
Usage
Single-tenant (config from .env)
use Laravel\Socialite\Facades\Socialite; Route::get('/sso/redirect', fn () => Socialite::driver('oidc')->redirect()); Route::get('/sso/callback', function () { $user = Socialite::driver('oidc')->user(); // $user->id // sub claim // $user->email // $user->name // $user->token // access_token // $user->idToken // raw id_token JWT // $user->idTokenClaims // decoded + validated claims });
Multi-tenant (runtime config)
use Laravel\Socialite\Facades\Socialite; use JeffersonGoncalves\LaravelOidc\Data\OidcConfig; $config = new OidcConfig( issuerUrl: $tenant->issuer_url, clientId: $tenant->client_id, clientSecret: $tenant->client_secret, redirectUri: route('sso.callback'), scopes: ['openid', 'email', 'profile'], ); return Socialite::driver('oidc') ->setConfig($config) ->redirect();
On callback:
$oidcUser = Socialite::driver('oidc') ->setConfig($config) ->user();
HasOidcConfig trait for tenant models
If you store IdP configuration on a model (a typical multi-tenant pattern), drop in the
trait. It expects columns issuer_url, client_id, client_secret (cast to encrypted),
redirect_uri, and an optional scopes JSON column.
use JeffersonGoncalves\LaravelOidc\Concerns\HasOidcConfig; class SsoConnection extends Model { use HasOidcConfig; } Socialite::driver('oidc') ->setConfig($ssoConnection->toOidcConfig()) ->redirect();
Discovery without Socialite
use JeffersonGoncalves\LaravelOidc\Facades\Oidc; $discovery = Oidc::discover('https://login.microsoftonline.com/{tenant-id}/v2.0'); $discovery->authorizationEndpoint; $discovery->tokenEndpoint; $discovery->userinfoEndpoint; $discovery->jwksUri; $discovery->issuer;
Supported Identity Providers
Any IdP that publishes a .well-known/openid-configuration discovery document and signs
id_tokens with one of the allowed algorithms (RS256, RS384, RS512, ES256, ES384)
will work. Examples:
| IdP | Issuer URL example |
|---|---|
| Azure AD / Entra ID | https://login.microsoftonline.com/{tenant-id}/v2.0 |
| Google Workspace | https://accounts.google.com |
| Okta | https://{your-org}.okta.com |
| Auth0 | https://{your-tenant}.auth0.com/ |
| Keycloak | https://{host}/realms/{realm} |
| Ping Identity | https://{environment}.pingone.com/{environment-id}/as |
Security
id_tokenvalidation. Everyid_tokenis decoded against the IdP's JWKS usingfirebase/php-jwt. Theiss,aud,exp, andiatclaims are checked, with a configurable clock-skew window.- Algorithm allow-list. Only the algorithms in
oidc.jwt.allowed_algorithmsare accepted. Symmetric algorithms (HS256& friends) are intentionally absent — accepting them with a JWKS would enable trivial key-confusion attacks. - Replay protection. A random
nonceis generated, stored in the session, and verified against thenonceclaim in the returnedid_token. - PKCE. Enabled by default with
S256. Disable per request withnew OidcConfig(..., usePkce: false). - Caching. The discovery document is cached for 1 hour and the JWKS for 6 hours by
default; both TTLs are configurable. Use
Oidc::clearCache($issuer)to invalidate after a key rotation.
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Pull requests are welcome. Please make sure tests, PHPStan and Pint all pass before opening a PR:
composer test
composer analyse
composer format
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.
