For the complete documentation index, see llms.txt. This page is also available as Markdown.

OIDC Authentication

TeamCal Neo supports SSO login via OpenID Connect (OIDC) for all users except 'admin'.

With release 5.3.0, TeamCal Neo supports Single Sign-On (SSO) login using OpenID Connect (OIDC). This allows users to authenticate through an external Identity Provider (IdP) such as Keycloak, Microsoft Entra (Azure AD), Okta, or any other OIDC-certified service — without entering a TeamCal Neo password.


How it works

TeamCal Neo uses the Authorization Code Flow. When a user clicks "Login with SSO":

  1. TeamCal Neo redirects the browser to the IdP's login page.

  2. The user authenticates at the IdP (the password is never sent to TeamCal Neo).

  3. The IdP redirects back to TeamCal Neo with a short-lived code.

  4. TeamCal Neo exchanges the code for an ID Token (server-to-server).

  5. The ID Token contains claims — in particular sub (a permanent unique ID) and preferred_username (the human-readable login name).

  6. TeamCal Neo looks up the local user account by sub, then by preferred_username as a fallback.

  7. On first match via preferred_username, the sub is stored for future lookups so IdP username renames do not break the link.

  8. If no matching local account is found, login is rejected.

  9. On success, a standard session cookie is set — the rest of the application is unchanged.


Prerequisites

  • A running OIDC-compatible Identity Provider (Keycloak, Entra, Okta, Google, etc.)

  • A Client registered on the IdP for TeamCal Neo (see below)

  • PHP Composer package jumbojett/openid-connect-php (included in the 5.3.0 distribution)


Configuration

OIDC is configured via the .env file. Add the following entries (see .env.example for reference):

Variable
Description

OIDC_YES

1 to enable OIDC, 0 to disable

OIDC_PROVIDER_URL

Base URL of the IdP realm. The library fetches /.well-known/openid-configuration from it automatically.

OIDC_CLIENT_ID

The client ID registered at the IdP

OIDC_CLIENT_SECRET

The client secret from the IdP

OIDC_REDIRECT_URI

The callback URL back to TeamCal Neo — must match the redirect URI configured at the IdP

When OIDC_YES=1:

  • LDAP authentication is automatically disabled, even if LDAP_YES=1 is also set.

  • The login page shows a "Login with SSO" button and hides the standard username/password form for regular users.

  • The admin account always authenticates locally, regardless of the OIDC setting.

  • The application's built-in two-factor authentication (TOTP) is bypassed for OIDC-authenticated users. MFA is the responsibility of the IdP.


User management

OIDC authentication does not auto-provision new user accounts. A local TeamCal Neo account must exist before a user can log in via OIDC. This is by design — local accounts are where group memberships, roles, and absence permissions are managed.

The user add and user edit screens display a reminder when OIDC is active.

After the first successful OIDC login, TeamCal Neo stores the IdP's permanent sub identifier against the local account. Subsequent logins look up the account by sub first, so IdP username renames do not orphan the account.


Behaviour overview

Scenario
Result

OIDC active, known user clicks "Login with SSO"

Login succeeds; session cookie set

OIDC active, unknown user (no local account)

Rejected: "No local account found"

OIDC active, user tries to log in via the local form

Rejected: "Local login is disabled while SSO is active"

OIDC active, admin logs in via the local form

Allowed — admin is always local-only

OIDC active, locked or unverified account authenticates at IdP

Rejected with the corresponding account status message

OIDC active, user logs out

Local session cookie cleared; IdP session remains active (no Single Logout)

OIDC active, LDAP_YES=1 also set in .env

LDAP is ignored; OIDC takes precedence


Keycloak setup for testing

Keycloak is a free, open-source IdP that runs in Docker. It is the recommended option for testing OIDC before connecting to a production IdP such as Entra or Okta.

Step 1 — Start Keycloak in Docker

After about a minute, the Keycloak admin console is available at http://<host>:8180.

Step 2 — Create a Realm

  1. Log in to the Keycloak admin console.

  2. Open the realm dropdown (top-left) → Create Realm.

  3. Name it teamcalneoCreate.

All following steps are done inside the teamcalneo realm.

Step 3 — Create the TeamCal Neo client

  1. Go to ClientsCreate client.

  2. Client ID: teamcal-neo, Client type: OpenID ConnectNext.

  3. Enable Client authenticationNext.

  4. Valid redirect URIs: http://<teamcal-server>/index.php?action=oidccallbackSave.

  5. Open the Credentials tab and copy the Client secret.

Step 4 — Create a test user

  1. Go to UsersCreate new user.

  2. Set Username to a value that exactly matches a username in the TeamCal Neo database.

  3. Open the Credentials tab → Set password (disable "Temporary").

Step 5 — Verify the discovery document

Open the following URL in a browser to confirm Keycloak is reachable and OIDC-ready:

If a JSON document is returned, Keycloak is working correctly.

Step 6 — Configure TeamCal Neo


Connecting to production Identity Providers

Once the feature works against Keycloak, switching to a production IdP only requires updating the .env file. No code changes are needed.

Identity Provider

OIDC_PROVIDER_URL value

Microsoft Entra (Azure AD)

https://login.microsoftonline.com/<tenant-id>/v2.0

Okta

https://<your-domain>.okta.com

Google

https://accounts.google.com

Keycloak

https://<host>/realms/<realm-name>

The OIDC library fetches the discovery document from <OIDC_PROVIDER_URL>/.well-known/openid-configuration at runtime and adapts to the IdP automatically.


Troubleshooting

Symptom
Likely cause

"No local account found" after IdP login

The preferred_username in the IdP does not match any TeamCal Neo username

"OIDC: Provider connection error" on the login page

OIDC_PROVIDER_URL is unreachable or incorrect

Redirect loop or state mismatch error

The session cookie SameSite attribute must be Lax (not Strict) — already set correctly in 5.3.0

LDAP login still works when OIDC is enabled

Check that OIDC_YES=1 is set and not overridden by a cached .env

User is rejected despite a matching username

Check whether the account is locked or unverified in TeamCal Neo user management

For detailed login event logs, check the TeamCal Neo System Log (Administration → System Log). Keycloak also records all authentication events under Realm settings → Events.

Last updated