Installation
composer require drenso/symfony-oidc-bundle
Symfony Flex auto-generates .env variables and config/packages/drenso_oidc.yaml.
Configure OIDC Client
Update config/packages/drenso_oidc.yaml with your provider’s details (e.g., well_known_url, client_id, client_secret).
Example:
drenso_oidc:
clients:
default:
well_known_url: '%env(OIDC_WELL_KNOWN_URL)%'
client_id: '%env(OIDC_CLIENT_ID)%'
client_secret: '%env(OIDC_CLIENT_SECRET)%'
Implement User Provider
Extend your UserProvider to implement OidcUserProviderInterface:
use Drenso\OidcBundle\Security\User\OidcUserProviderInterface;
use Drenso\OidcBundle\Security\User\OidcUserData;
use Drenso\OidcBundle\Security\User\OidcTokens;
class CustomUserProvider implements OidcUserProviderInterface {
public function ensureUserExists(string $userIdentifier, OidcUserData $userData, OidcTokens $tokens): void {
// Create user logic (e.g., via Doctrine or database).
}
public function loadOidcUser(string $userIdentifier): UserInterface {
// Load user logic (e.g., via Doctrine).
}
}
Configure Firewall
Enable the oidc listener in config/packages/security.yaml:
security:
firewalls:
main:
oidc: ~
Trigger Login Add a route to redirect users to the OIDC provider:
#[Route('/login_oidc', name: 'login_oidc')]
public function login(OidcClientInterface $oidcClient): RedirectResponse {
return $oidcClient->generateAuthorizationRedirect();
}
Multi-Client Setup
Configure multiple OIDC clients in drenso_oidc.yaml and inject them via autowiring:
drenso_oidc:
clients:
auth0: { well_known_url: '%env(AUTH0_WELL_KNOWN_URL)%', ... }
keycloak: { well_known_url: '%env(KEYCLOAK_WELL_KNOWN_URL)%', ... }
Inject clients in controllers/services:
public function __construct(
private OidcClientInterface $auth0OidcClient,
private OidcClientInterface $keycloakOidcClient
) {}
Dynamic User Identifier
Use user_identifier_property in firewall config to override the default sub:
security:
firewalls:
main:
oidc:
user_identifier_property: email
Remember Me Enable in firewall and client config:
security:
firewalls:
main:
oidc:
enable_remember_me: true
Add _remember_me=1 to the redirect URL:
$oidcClient->generateAuthorizationRedirect(['_remember_me' => '1']);
Logout Handling
Enable end_session_support in firewall:
security:
firewalls:
main:
oidc:
enable_end_session_listener: true
Custom User Data Parsing
Override the well_known_parser service to modify how the .well-known config is parsed.
Example:
services:
custom_well_known_parser:
class: App\Service\CustomWellKnownParser
tags: ['drenso_oidc.well_known_parser']
drenso_oidc:
clients:
default:
well_known_parser: custom_well_known_parser
Token Validation Leeway
Adjust token_leeway_seconds to account for clock skew:
drenso_oidc:
clients:
default:
token_leeway_seconds: 60
Caching
Enable caching for .well-known and JWKS responses:
drenso_oidc:
clients:
default:
well_known_cache_time: 3600
jwks_cache_time: 3600
Symfony Version Mismatch
v1.x branch for older Symfony versions (e.g., 4.x).composer.json for Symfony version constraints.Missing User Provider Methods
ensureUserExists or loadOidcUser throws RuntimeException.UserProvider implements OidcUserProviderInterface fully.Clock Skew Errors
token_leeway_seconds (default: 0):
drenso_oidc:
clients:
default:
token_leeway_seconds: 30
ADFS/Entra ID Quirks
Caching Issues
.well-known or JWKS responses cause auth failures.well_known_cache_time/jwks_cache_time:
php bin/console cache:clear
Remember Me Not Working
REMEMBERME cookie not set despite enable_remember_me: true.remember_me authenticator is enabled._remember_me=1 is passed in the redirect URL.SameSite attributes).Logout Redirect Loops
use_logout_target_path:
security:
firewalls:
main:
oidc:
use_logout_target_path: false
Enable Verbose Logging
Add to config/packages/dev/monolog.yaml:
handlers:
oidc:
type: stream
path: "%kernel.logs_dir%/oidc.log"
level: debug
channels: ["drenso_oidc"]
Then enable the channel in config/packages/drenso_oidc.yaml:
drenso_oidc:
logging_channel: drenso_oidc
Inspect Tokens
Dump OidcTokens in ensureUserExists:
public function ensureUserExists(string $userIdentifier, OidcUserData $userData, OidcTokens $tokens): void {
\dump($tokens->getIdToken()->getClaims());
}
Validate Well-Known Config
Manually fetch the .well-known endpoint to verify it matches your config:
curl %env(OIDC_WELL_KNOWN_URL)%
Custom Authenticator
Extend the default OidcAuthenticator to add pre/post-auth logic:
use Drenso\OidcBundle\Security\Authenticator\OidcAuthenticator;
class CustomOidcAuthenticator extends OidcAuthenticator {
protected function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response {
// Custom logic (e.g., set flash message).
}
}
Register as a service and replace the default authenticator in security.yaml:
security:
firewalls:
main:
oidc:
authenticator: custom_oidc_authenticator
Event Listeners
Listen to OIDC events (e.g., OidcAuthenticationSuccessEvent):
How can I help you explore Laravel packages today?