yeke.io · docs · enterprise
OIDC Login (SSO)
Connect an OIDC provider such as Keycloak or Entra ID with Enterprise. Users can sign in through SSO while local accounts remain available. This guide covers provider settings, the redirect URI and group mapping.
Overview
One more button on the login screen; the password path stays where it is.
The SSO button takes the user to the provider’s login page. YEKE never receives the password. After authentication, YEKE creates a session using the Authorization Code + PKCE flow.
The local username-and-password form does not disappear. That is not an oversight but an emergency access path: the install owner is always local, so local administrator login stays available when the provider is unreachable or misconfigured.
The SSO button is only drawn on the login screen when two conditions hold together: an
enabled provider must be defined and the license must carry the Enterprise
sso item. That item is shared with
Active Directory / LDAP login — there is no new license
flag, and both can be enabled at the same time.
Defining the provider
One provider is configured from the admin screen, and saving it really tests the connection.
| Field | What it does |
|---|---|
label | The text on the login screen's button. It is the only name the user ever sees. |
issuer | The provider's identity URL; https is
required. It must match the issuer value in the provider's discovery
document exactly — trailing slash included. |
clientId | The ID of the client you created for YEKE on the provider side. |
clientSecret | The client secret; it is required. It is write-only: no response ever returns it, a response only says whether it is set. |
caCertPem | Optional. If the provider's certificate is signed by an internal CA, paste its PEM here. A certificate is not a secret, so it is stored unencrypted. |
usernameClaim | The claim the username is read from. Default
preferred_username; email is also selectable. |
groupsClaim | The claim groups are read from. Default
groups. |
adminGroup | Optional. When set, members of that group get the
admin role on every login. |
| Extra scopes | Any scopes you need to request from the provider beyond the defaults. |
label : Corporate account issuer : https://id.example.com/realms/corp client id : yeke client secret : (write-only) username claim : preferred_username groups claim : groups admin group : yeke-admins
Before you save, the "Test connection" button really fetches the provider's discovery document, resolves the endpoints and writes them into the record. If the test fails, the reason shows up on screen; the record is still stored, but not enabled.
Only one provider can be enabled at a time.
A wrong client secret now shows up as IDP_CLIENT_REJECTED
If the provider rejects the client secret at the last step of sign-in, YEKE now shows
its own error code for that — it used to report a generic "cannot reach identity
provider" message. On Entra ID the most common cause is copying the Secret ID instead of
the Value column: the column to copy is Value, not Secret ID. If the client ID is wrong,
the error appears on Microsoft's sign-in page before the flow ever returns to YEKE
(AADSTS700016).
The redirect URI
The address derives from YEKE's own public URL, not from the incoming request's headers.
The return address from the provider is built by appending
/api/auth/oidc/callback to YEKE_PUBLIC_URL. That address has to be
registered on the provider side exactly like this.
YEKE_PUBLIC_URL : https://yeke.example.com redirect URI : https://yeke.example.com/api/auth/oidc/callback
Without YEKE_PUBLIC_URL, the configuration is refused
The redirect URI comes from YEKE_PUBLIC_URL, never from a request header. This setting is required; OIDC configuration is rejected when it is empty. Installation settings →
Keycloak treats only a trailing * as a wildcard
Register the exact redirect URI with your provider. Avoid a wildcard in the middle: for example, https://server:*/path will not match in Keycloak and produces invalid_redirect_uri.
Roles and Kubernetes group mapping
The group claim is written into the same mapping list as the directory side; there is no separate list for OIDC.
Roles can be derived from the directory
The provider record lets you optionally name an admin group (adminGroup). When
set, a user's role is derived from the token's group claim on every login, and writing
that user's role from the UI is refused — otherwise a manual edit would be silently overwritten
by the next login. Leave it unset and the role is managed the usual way, from YEKE's user
screen.
Kubernetes identity: the same list as the directory
The cluster rule plus personal binding model described on the Permissions and RBAC page still applies. The token's group claim is written into the same mapping list in the cluster identity rule: there is no separate list for LDAP and another for OIDC. One list carries both LDAP group DNs and OIDC's plain group names.
source group Kubernetes group CN=YEKE-Operators,OU=Groups,DC=example,DC=com → yeke:cluster-admins (LDAP) yeke-operators → yeke:cluster-admins (OIDC) 3f2b9c14-8a71-4d0e-9c53-6b7a1e5d20f4 → payments-oncall (OIDC)
Keycloak: "full path" must be off in the group mapper
Keycloak's group mapper can emit the group's full path
(/parent-group/child-group). If you want to write plain group names in the mapping
list, that option has to be off — the plain name landing in the claim depends on it.
Entra ID emits GUIDs in the group claim
Entra ID puts a group's GUID, not its name, into the group claim; the value you write on the left side of a mapping row is that GUID. An optional label can be written on the row — a list of nothing but GUIDs becomes unreadable.
Registering an application in Entra ID
Before you can connect Microsoft Entra ID as a provider, you need to register an application on the Entra side: the application registration, the client secret, the admin group and the token's group setting are all covered step by step on the Entra ID SSO Setup page.
First login: automatic user creation and license seats
You do not pre-invite anyone from the provider into YEKE.
- Just-in-time creation. A user who authenticates against the provider but has no YEKE record yet is created automatically on their first successful login.
- It consumes a seat. An automatically created user consumes a license seat exactly like one created by hand. If the seat ceiling is reached, the login is refused with an explicit code.
- The username comes from the claim. The name YEKE stores is the value of the claim
you chose in
usernameClaim; that is the name shown in the user list and the audit trail. - A login is refused if an account with the same name exists. If the incoming username collides with an existing local or LDAP account, the login stops with a loud error; the OIDC user is not silently attached to that account. Silent attachment falls into the account-takeover class.
Second factor
For an OIDC user, the authority over the second factor is the IdP.
- An OIDC user cannot enroll YEKE's own TOTP. The provider decides who is asked for a second factor; YEKE does not open a second factor record for the same user.
- Nothing changes for local accounts. YEKE's own second factor stays exactly as it is for local users.
Limits
The line between what exists today and what does not.
- No SAML or SCIM. Everything on this page is about OIDC; SAML and SCIM remain in the demand-driven queue.
- End-to-end Entra ID login was tested against a real tenant. Group object ID
(GUID) → role and Kubernetes group mapping was part of the same test; this landed in
0.46.1 — earlier releases could not even register Entra ID as a provider. Still
unverified: Entra's "groups overage" behavior for a user who belongs to many groups, and
whether the user identity (
sub) changes when an app registration is recreated. - A login is refused on Entra "groups overage". When a user belongs to too many groups, Entra ID does not emit the group claim at all. YEKE refuses the login in that case; it does not silently continue with an empty group set, because that path would leave the user without access and without any error.
- One enabled provider at a time. There is no keeping more than one OIDC provider enabled simultaneously.
- A YEKE session does not end when the IdP session does. There is no back-channel logout: YEKE holds its own session, and the provider's token is used only at login and never stored.
- None of this works without a license. Provider configuration and OIDC login are
refused with an explicit error without the Enterprise
ssoitem; local login is never affected.
See what group mapping means on the RBAC side
Groups arriving from the provider flow into Kubernetes groups here — but the decision is still RBAC's. The directory path that feeds the same list lives on its own page.