Skip to content

Add support for OIDC authentication#5865

Open
matt-oakes wants to merge 1 commit intokimai:mainfrom
matt-oakes:oidc
Open

Add support for OIDC authentication#5865
matt-oakes wants to merge 1 commit intokimai:mainfrom
matt-oakes:oidc

Conversation

@matt-oakes
Copy link
Copy Markdown

@matt-oakes matt-oakes commented Mar 9, 2026

Description

This PR adds support for OpenID Connect (OIDC) authentication. It resolves #2469.

The code is heavily based on the existing SAML authentication implementation using:

  • OidcAuthenticator to hook into Symfony authenticating using Passport.
  • OidcProvider to create and hydrate users.
  • OidcController to supply the login routes to redirect to the configured OIDC provider.
    The implementation of OIDC in this PR is handled by jumbojett/openid-connect-php which does all of the heavy lifting.

Configuration is very similar to SAML too, but much simplier because ODIC is more standardized and has sensible defaults. Basic configuration would be:

kimai:
    oidc:
        activate: true
        title: "Login with Custom OIDC"
        provider_url: "https://auth.example.com/"
        client_id: "EXAMPLE"
        client_secret: "EXAMPLE"

These are the only configuration values which need to be provided because OIDC is able to automatically detect the others using the "well known" URL. In the example above, it is able to access https://auth.example.com/.well-known/openid-configuration. The response to this will include all of the URLs and other configuration needed to setup OIDC with that specific server.

I have also gone a little further and implemented the same "role mapping" system which SAML has. You can configure this in a very similar way by adding this to the above config:

          roles:
            resetOnLogin: true
            mapping:
                # Insert your role-mapping here (ROLE_USER is added automatically)
                - { oidc: Admin, kimai: ROLE_SUPER_ADMIN }
                - { oidc: Manager, kimai: ROLE_ADMIN }
                - { oidc: Teamlead, kimai: ROLE_TEAMLEAD }

This works example the same as with SAML, however, the attribute configuration value isn't needed as it is standarized in OIDC.

Demo video

kimai_oidc.mp4

How to test this

To test this, you will need to have an OIDC authentication provider. There are many available such as Pocket ID, Ory Hydra, Authentik, VoidAuth, Keycloak, and Forgejo.

However, if you don't have any setup, then by far the easiest is to start a "demo instance" of Pocket ID (they last for 30 minutes before being deleted).

https://demo.pocket-id.org

When you have an instance you can follow these steps to create the required enviornment for testing:

  1. Follow the setup instructions to create a new user.
  2. Create a passkey when requested, or skip in this case and it will keep you logged in until the demo instance is deleted.
  3. Go to "Administration" -> "OIDC Clients" and then click "Add OIDC client"
  4. Fill in the name as "Kamai" (or whatever you like) and leave the rest of the settings blank. Press "Save"
  5. Scroll down to the "Allowed User Groups", expand it and press "Unrestrict". This will allow all users in the auth provider (just you) to access the client.
  6. At the top of the screen there will be the settings. Expand it and then use "client ID", "client secret", and "issuer URL" to fill in this Kamai config:
kimai:
    oidc:
        activate: true
        title: "Login with Pocket ID"
        provider_url: "https://EXAMPLE.demo.podkcet-id.org"
        client_id: "EXAMPLE"
        client_secret: "EXAMPLE"
  1. Open the login page of your Kimai instance and there should be a "Login with Pocket ID" button. Pressing that should take you to the Pocket ID login page.
  2. Press sign in and then accept the information which will be shared.
  3. You will be redirected back to Kimai and logged in. If this was a new user your name, email, and profile picture will be set from Pocket ID.

To test role mapping:

  1. In your Pocket ID demo instance, go to "Administration" -> "User groups" and then click "Add Group".
  2. Give it a friendly name and optionally change the name which will be sent to Kimai. This example will use admins.
  3. On the next page, scroll down to the user list, tick your user and then press "Save". This assigns your user to that group.
  4. Modify your Kimai config to include:
          roles:
            resetOnLogin: true
            mapping:
                - { oidc: admins, kimai: ROLE_ADMIN }
  1. Sign out of Kimai and then sign in again with the "Login with Pocket ID" button. You will be asked for permissions again and this time it will be requesting "groups" access.
  2. When you accept and sign in your user will be assigned to the admin role.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 9, 2026

CLA assistant check
All committers have signed the CLA.

@kevinpapst
Copy link
Copy Markdown
Member

Thanks for your effort on this PR. I am not going to details yet, becuase I'd like to discuss one topic first:

Did you try to use/integrate the Symfony OidcHandler https://symfony.com/doc/current/security/access_token.html#using-openid-connect-oidc ?

I am not really open to integrate new dependencies, especially for security related topics. Even more so, as that library didn't receive any commit in 10 months and has open topics for PHP 8.5. The last release was in September 2024. That is not really a reliable dependency.

@simonschaufi
Copy link
Copy Markdown
Contributor

Personally I would expect Kimai to only provide the interfaces and possibilities to add new providers but the providers should come from plugins.

@matt-oakes
Copy link
Copy Markdown
Author

Completely agree on the dependency point. I wasn’t aware that Symfony had OIDC support built-in.

A plugin could make sense, but it has it be tied pretty deeply into the Symfony auth system to work.

@simonschaufi
Copy link
Copy Markdown
Contributor

What I mean is that in my opinion this login authentication provider should not be part of Kimai Core but be provided as a plugin (if possible).

@kevinpapst
Copy link
Copy Markdown
Member

The problem with everything auth related is that it needs changes in core config files. So shipping it as plugin would be ideal, but I am not sure how easy that actually is to achieve.

Yes, I'd like to include the option for OIDC, but as said, with Symfony dependencies only.
I used a library for SAML in the past and had massive issues with that, so moved away from it.

@matt-oakes are you willing to have a look at the Symfony own provider?

@simonschaufi
Copy link
Copy Markdown
Contributor

simonschaufi commented Mar 11, 2026

I am not sure how easy that actually is to achieve.

I can only tell you what TYPO3 uses. TYPO3 has a Auth service chain (https://docs.typo3.org/permalink/t3coreapi:authentication-service-chain). It basically looks like this: https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/Services/UsingServices/ServiceChain.html#services-using-services-service-chain

So you have a registry where you can register your own auth service provider and TYPO3 will iterate over them and check if the auth service provider can handle the request and if the auth was successful or not.

For Kimai this could be an event listener where you can register your own service provider and Kimai then calls them. Each auth service provider needs to implement an interface (https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/Services/Developer/ServiceApi.html)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support OpenID Connect

4 participants