steverhoades/oauth2-openid-connect-server
Laravel-friendly OAuth2 + OpenID Connect server built on League OAuth2. Provides OIDC discovery and JWT ID tokens, common grant types, and flexible storage/adapters so you can run your own authorization server for APIs and SSO.
Installation Add the package via Composer:
composer require steverhoades/oauth2-openid-connect-server
Ensure league/oauth2-server is also installed (dependency).
Basic Configuration
Extend OpenIdConnectServer in your Laravel service provider:
use Stevehoades\OAuth2\OpenIdConnectServer;
use League\OAuth2\Server\ResourceServer;
$server = new OpenIdConnectServer(
new ResourceServer($storage, $privateKey, $encryptionKey),
$config // Your OIDC config (issuer, claims, etc.)
);
First Use Case: Issuing Tokens
Use the getAuthorizationServer() method to issue an OIDC token:
$request = $server->validateAuthorizationRequest($authRequest);
$response = $server->completeAuthorizationRequest($request, $authCode);
Key Files to Review
config/oauth.php (if using Laravel OAuth packages)app/Providers/AuthServiceProvider.php (for middleware binding)routes/web.php (for /token and /auth endpoints)Authenticate User
Use Laravel’s built-in auth (e.g., Auth::user()) to verify credentials.
$user = Auth::guard('web')->user();
Generate OIDC Claims
Customize claims via OpenIdConnectServer:
$server->setClaim('email', $user->email);
$server->setClaim('name', $user->name);
Issue Access/ID Tokens
$accessToken = $server->issueAccessToken();
$idToken = $server->issueIdToken();
Validate Tokens (Client-Side)
Use the ResourceServer to verify tokens in API routes:
$server = new ResourceServer($storage, $privateKey);
$request = Request::capture();
$psr7Request = ServerRequest::fromGlobals();
$token = $server->validateAuthenticatedRequest($psr7Request);
Laravel Middleware
Bind the ResourceServer middleware to protected routes:
Route::middleware(['auth:api', 'oauth'])->group(function () {
// Protected routes
});
Dynamic Claims
Use Laravel’s Authenticatable traits to inject claims dynamically:
class User extends Authenticatable {
public function getOidcClaims() {
return ['preferred_username' => $this->username];
}
}
JWT vs. Reference Tokens
Configure OpenIdConnectServer to use JWT or reference tokens:
$server->enableJwtSupport($privateKey, $publicKey);
Missing state Parameter
OIDC requires a state parameter in auth requests. Laravel’s session driver can handle this, but ensure it’s included in redirects:
return redirect()->to($authUrl)->with('state', $state);
Clock Skew in Token Validation
Ensure server clocks are synchronized (OIDC uses iat, exp claims). Configure league/oauth2-server:
$server->setClock(new \DateTimeImmutable());
Nonce Mismatch
The nonce claim must match the original auth request. Store it in the session or database:
session(['oauth_nonce' => $nonce]);
CORS Issues
OIDC endpoints (/token, /userinfo) may require CORS headers. Configure in Laravel:
Header::set('Access-Control-Allow-Origin', '*');
Enable Verbose Logging Configure Monolog in Laravel to log OIDC events:
'channels' => [
'oidc' => [
'driver' => 'single',
'path' => storage_path('logs/oidc.log'),
'level' => 'debug',
],
],
Validate Tokens Locally
Use jwt.io or https://jwt.ms to decode ID tokens for debugging.
Custom Claims Provider
Implement Stevehoades\OAuth2\ClaimProviderInterface:
class CustomClaimProvider implements ClaimProviderInterface {
public function getClaims(User $user) {
return ['custom_claim' => 'value'];
}
}
UserInfo Endpoint
Extend the /userinfo endpoint to return additional claims:
$server->addUserInfoClaim('address', $user->address);
Dynamic Issuer Configuration Use Laravel’s config caching to switch issuers dynamically:
config(['oauth.issuer' => env('OIDC_ISSUER')]);
Private Key Format Ensure the private key is in PEM format (no passphrase for simplicity):
-----BEGIN PRIVATE KEY-----
(Your key here)
-----END PRIVATE KEY-----
Algorithm Constraints
OIDC defaults to RS256. Change in config if needed:
$server->setAlgorithm('HS256'); // For HMAC (less secure)
How can I help you explore Laravel packages today?