feat(oidc): implement OIDC login attributes and provider - #6044
feat(oidc): implement OIDC login attributes and provider#6044habibhaidari1 wants to merge 4 commits into
Conversation
- Add OidcLoginAttributes class to manage user attributes from OIDC. - Create OidcProvider class for user retrieval and hydration from OIDC tokens. - Introduce OidcToken class extending PostAuthenticationToken for OIDC authentication. - Implement OidcAuthenticationFailureHandler and OidcAuthenticationSuccessHandler for custom authentication handling. - Update login template to support OIDC login alongside SAML. - Add tests for OidcConfiguration, OidcProvider, OidcLoginAttributes, and OidcToken to ensure functionality and correctness.
|
Habib Haidari seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6044 +/- ##
============================================
+ Coverage 88.69% 88.81% +0.12%
- Complexity 10011 10185 +174
============================================
Files 887 896 +9
Lines 31929 32429 +500
============================================
+ Hits 28319 28803 +484
- Misses 3610 3626 +16
🚀 New features to boost your workflow:
|
|
Thanks! Did you have a look at #5865 before proposing your PR? |
|
Oh, you're absolutely right! How did I miss that? 🤦♂️ |
There was a problem hiding this comment.
Pull request overview
Adds first-class OpenID Connect (OIDC) SSO support to Kimai alongside the existing SAML integration, including configuration, controllers/routes, a Symfony security authenticator, and user provisioning/hydration based on OIDC claims.
Changes:
- Introduces OIDC configuration (DI config tree + runtime configuration wrapper) and wires new OIDC services/authenticator into Symfony Security + 2FA.
- Implements the OIDC login flow (redirect with state/nonce/PKCE, callback handling, token exchange, discovery caching, userinfo fetch) and user hydration/role mapping.
- Adds comprehensive PHPUnit coverage for the new OIDC components and updates existing controller/config tests for the new config surface.
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Oidc/OidcTokenTest.php | Tests token basics and attribute storage. |
| tests/Oidc/OidcProviderTest.php | Tests user lookup/creation, claim mapping, and role mapping behavior. |
| tests/Oidc/OidcLoginAttributesTest.php | Tests attribute container behavior and error cases. |
| tests/Oidc/OidcClientTest.php | Tests discovery, authorization URL building, PKCE, token/userinfo handling, and ID-token validation paths. |
| tests/Oidc/OidcBadgeTest.php | Tests custom passport badge behavior. |
| tests/Oidc/OidcAuthenticatorTest.php | Tests authenticator supports/authenticate/createToken and success/failure delegation. |
| tests/DependencyInjection/ConfigurationTest.php | Extends DI config validation/defaults coverage for oidc.*. |
| tests/Controller/Security/SecurityControllerTest.php | Updates controller construction to include OIDC config. |
| tests/Controller/Auth/OidcControllerTest.php | Tests OIDC login/callback controller behavior under activation toggles. |
| tests/Configuration/OidcConfigurationTest.php | Tests OIDC configuration wrapper against SystemConfiguration. |
| templates/security/login.html.twig | Adds an OIDC SSO button alongside SAML in the login UI. |
| src/Oidc/Security/OidcAuthenticationSuccessHandler.php | Adds dedicated success handler for OIDC authenticator flow. |
| src/Oidc/Security/OidcAuthenticationFailureHandler.php | Adds dedicated failure handler for OIDC authenticator flow. |
| src/Oidc/OidcToken.php | Adds OIDC post-auth token type for Symfony Security/2FA integration. |
| src/Oidc/OidcProvider.php | Implements OIDC user provisioning/hydration + role mapping on login. |
| src/Oidc/OidcLoginAttributes.php | Adds a claim/attribute container used across the OIDC flow. |
| src/Oidc/OidcClient.php | Implements OIDC discovery, auth URL creation, code exchange, userinfo fetch, and ID-token validation. |
| src/Oidc/OidcBadge.php | Adds passport badge to carry OIDC login attributes through authentication. |
| src/Oidc/OidcAuthenticator.php | Adds Symfony authenticator for the OIDC callback route and token creation. |
| src/Entity/User.php | Adds OIDC auth constant and helper (isOidcUser()). |
| src/DependencyInjection/Configuration.php | Adds oidc config node, defaults, and validation rules. |
| src/Controller/SystemConfigurationController.php | Keeps login-related system configuration enabled when OIDC is active. |
| src/Controller/Security/SecurityController.php | Passes OIDC config into login template rendering. |
| src/Controller/Auth/OidcController.php | Adds routes for /oidc/login (redirect) and /oidc/callback (firewall-handled). |
| src/Configuration/SystemConfiguration.php | Adds getters for oidc.* settings (activation, endpoints, scopes, mappings, roles). |
| src/Configuration/OidcConfigurationInterface.php | Defines the OIDC configuration contract. |
| src/Configuration/OidcConfiguration.php | Implements the OIDC configuration contract via SystemConfiguration. |
| config/services.yaml | Registers/wires OIDC services (OidcProvider, OidcClient). |
| config/packages/security.yaml | Adds OidcAuthenticator to the secured firewall authenticators. |
| config/packages/scheb_2fa.yaml | Allows OidcToken for Scheb 2FA token handling. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| $issuer = $this->configuration->getIssuer(); | ||
| if ($issuer !== null && $issuer !== '' && isset($payload['iss'])) { | ||
| $tokenIssuer = $payload['iss']; | ||
| if (!\is_string($tokenIssuer) || rtrim($tokenIssuer, '/') !== rtrim($issuer, '/')) { | ||
| throw new AuthenticationException('OIDC ID token issuer mismatch.'); | ||
| } | ||
| } | ||
|
|
||
| if (isset($payload['aud'])) { | ||
| $audiences = \is_array($payload['aud']) ? $payload['aud'] : [$payload['aud']]; | ||
| if (!\in_array($this->configuration->getClientId(), $audiences, true)) { | ||
| throw new AuthenticationException('OIDC ID token audience mismatch.'); | ||
| } | ||
| } |
| /** | ||
| * Validates the ID token claims. The token itself is retrieved through the | ||
| * trusted back-channel (direct TLS connection to the token endpoint), which is | ||
| * why we validate the standard claims (iss, aud, exp, nonce) instead of the | ||
| * signature. | ||
| */ |
Description
I'd like to propose adding OpenID Connect support to Kimai, alongside the existing SAML2 integration. While SAML2 works well, OIDC has become the de-facto standard for modern identity providers. Many popular IdPs (Keycloak, Authentik, Authelia, Zitadel, Entra ID, Google, PocketID, ...) offer OIDC as their primary protocol. Supporting it would give admins many more options to connect their existing identity provider and help organizations consolidate their IT landscape by reusing one central SSO solution instead of maintaining separate credentials or an extra SAML bridge.
The code in this PR was generated with the help of Claude Fable 5. I have reviewed it tested the full login flow against "Pocket ID" as identity provider. (https://pocket-id.org/)
Types of changes
Checklist
composer code-check)