People Picker — IDP Directory Browse¶
Overview¶
Cesivi's people picker can fan-out search queries to external OIDC identity providers (Keycloak, Entra ID, Okta, Authentik), returning remote users and groups alongside local Cesivi users. When configured, typing in a user field on any list form triggers a parallel search across all enabled providers. Results from different providers appear with a colored provider badge (e.g., keycloak-corp) so users can distinguish identity sources at a glance.
Prerequisites¶
- PLAN-1613: multi-provider config shape must be in
appsettings.json - Each provider must have a dedicated admin/service-account client with user-read permissions:
- Keycloak:
realm-management→view-users,view-groups - Entra ID: Microsoft Graph
User.Read.All,GroupMember.Read.All - Okta: API token with
okta.users.read,okta.groups.read - Authentik: API token with user/group read scope
Configuration¶
Add a DirectoryBrowse sub-section inside each provider entry in appsettings.json:
"Cesivi": {
"Identity": {
"OidcProviders": [
{
"Name": "keycloak-corp",
"Enabled": true,
"Authority": "https://sso.example.com/realms/corp",
"ClientId": "cesivi-webui",
"ClientSecret": "...",
"DirectoryBrowse": {
"Enabled": true,
"ClientId": "cesivi-admin",
"ClientSecret": "...",
"TimeoutSeconds": 5,
"PageSize": 20
}
},
{
"Name": "entra-corp",
"Enabled": true,
"Authority": "https://login.microsoftonline.com/{tenantId}/v2.0",
"ClientId": "...",
"ClientSecret": "...",
"DirectoryBrowse": {
"Enabled": true,
"ClientId": "...",
"ClientSecret": "..."
}
}
]
}
}
Fields:
| Field | Required | Default | Description |
|---|---|---|---|
Enabled |
Yes | false |
Enable directory browse for this provider |
ClientId |
Yes | — | Admin client ID (may differ from the login client ID) |
ClientSecret |
Yes | — | Admin client secret |
TimeoutSeconds |
No | 5 |
Per-provider fan-out timeout |
PageSize |
No | 20 |
Max results returned per provider per query |
How It Works¶
- User types ≥ 2 characters into a User field picker.
- Cesivi fans out to all
DirectoryBrowse.Enabledproviders in parallel using a service-account token. - Results are merged: local users (from the Cesivi user store) come first, then remote users, deduplicated by claims key.
- A provider badge appears on any result whose login name encodes a provider (
i:0e.t|{providerName}|{subject}). - If a provider is slow (exceeds
TimeoutSeconds) or returns an error, it is soft-failed — the picker returns whatever other providers and local results are available. No error is shown to the user.
Provider Detection¶
Cesivi auto-detects the IDP type from the Authority URL:
| Pattern | Provider | Notes |
|---|---|---|
/realms/ in URL |
Keycloak | Uses admin REST API |
microsoftonline.com |
Entra ID | Uses Microsoft Graph /v1.0 |
.okta.com |
Okta | Flat groups (SupportsGroupHierarchy=false) |
/application/o/ |
Authentik | Uses Authentik REST API v3 |
Provider Badges¶
When a suggestion or chip comes from a remote OIDC provider, a small badge shows the provider name:
- Suggestions dropdown: badge appears inline with the display name
- Chips (selected users): badge appears inside the chip, right of the display name
Badge styling is in wwwroot/css/modern/forms.css (.sp-picker-provider-badge). The badge uses a blue-tint background by default; high-contrast / dark themes inherit adjusted colors.
Operator Checklist¶
- [ ] Each provider's admin client has been granted the required read permissions in the IDP
- [ ]
DirectoryBrowse.ClientId/ClientSecretare populated inappsettings.json(or secrets manager) - [ ]
TimeoutSecondsis set appropriately for your network latency (≥ 3s for remote IDPs) - [ ] Tested by typing a known remote user's name into a User field and seeing their result with badge
Troubleshooting¶
| Symptom | Likely Cause | Fix |
|---|---|---|
| No remote results | DirectoryBrowse.Enabled is false or missing |
Set to true and restart |
| Remote results vanish intermittently | TimeoutSeconds too low |
Increase to 8–10s |
| "Alice" returns 0 results from Entra | Graph scopes not granted | Add User.Read.All to the admin app registration |
| Badge missing on provisioned OIDC user | LoginName not in OIDC format |
Check EnsureUser created the user with i:0e.t|… login |
| Keycloak returns 401 | Admin client secret expired | Rotate the secret in Keycloak and update config |
PLAN-1618 (People-Picker IDP Directory Browse). Finalized in PLAN-1619.