mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-07-26 11:49:16 +00:00
9ff678a7bb
* docs(introduction): refresh for the redesigned UI and replace screenshots Bring the Getting Started Introduction page in line with the current product: - Add the Security top-level view to the navigation list and a dedicated Security section with a new screenshot. - Correct the Fleet tab names (Snapshots, Status, Map, Deployments, Routing, Federation, Actions, Secrets). - Split Settings out from security and list the current nine setting groups (Security graduated to its own view). - Refine the navigation paragraph so role, tier, and local-vs-remote context read accurately. Replace all four existing screenshots (Home, stack workspace, Fleet, Resources) with fresh captures of the redesigned UI and add a Security overview screenshot. * docs(configuration): document advanced env vars and clarify deployment vs runtime config Add an Advanced environment variables section (TRIVY_BIN, SENCHO_MESH_SUBNET, GITSOURCE_MAX_CLONE_BYTES, SENCHO_PUBLIC_URL, SENCHO_COMPOSE_STALL_TIMEOUT_MS) and reframe the intro to separate deployment-time configuration from the runtime settings that live in the in-app Settings Hub. Cross-link the pilot-agent variables to the Pilot Agent page instead of duplicating them. * docs(sso): refresh SSO Setup Guide and SSO & LDAP reference for the redesigned UI Refresh both SSO documentation pages against the current product and the redesigned settings UI. - Correct the navigation path to Settings -> Access -> SSO on both pages. - Fix the "Require 2FA on SSO sign-in" toggle location to Settings -> Personal -> Account. - Describe the login-page experience (the Local / LDAP toggle and the branded OIDC buttons under the "Or continue with" divider) and the SSO panel masthead (SCOPE, PROVIDERS, ENABLED). - Replace all six SSO screenshots with fresh captures of the redesigned UI. * docs(features): refresh the Features Overview page for the redesigned UI Rewrite docs/features/overview.mdx to mirror the current Features navigation grouping (Stacks, Deployment, Resources, Observability, Fleet, Automation, Security & Identity) and add the recently shipped capabilities surfaced in the redesign: Stack Dossier, Drift Detection, Compose Doctor, Compose Networking, Environment & secrets guardrails, Storage portability, Health-Gated Updates, Fleet Dossier, and the dedicated Security page. Correct stale claims (the file explorer now gates writes on stack edit permission, not an admin role; downloads are a read action; bulk label assign now spans nodes) and standardize the tier callouts so partly paid features read as "Admiral adds X". Replace the three pre-redesign screenshots and add a Security overview banner, all captured from a populated fleet. * docs(features): refresh the Appearance page for the redesigned UI Add fresh screenshots and a troubleshooting section to the Appearance page, verified against the live product. - Add four screenshots: the Theme card (live preview, mode, accent, and fine-tune sliders), the top-bar quick switcher, the Typography card, and the Display card. - Refresh the Density screenshot used by the Settings reference page. - State that the quick switcher also covers text size, and that the contrast, border, and glow sliders stay in Settings. - Add a Troubleshooting accordion covering per-browser persistence, resets to defaults, cross-operator scope, and the quick-switcher versus full-Settings split. * docs(introduction): refresh screenshots and correct stale content * docs(reference): refresh the Settings Reference page for the redesigned UI Replace all seven stale screenshots with fresh 1920x1080 captures. Add five new screenshots for the sections that previously had none. Content changes: - Sidebar table: rename Infrastructure "Fleet Mesh" entry to "Fleet"; add "Image update checks" to the Automation group list - Fleet section: rename heading to match registry label; add the Documentation snapshots subsection (snapshot_documentation toggle) - Container Alerts: add screenshot - Image update checks: add the full section (Registry checks table, scheduling mode, interval presets, cron expression support) - Stacks / Deploy Guardrails: add screenshot - Recovery: add the full section (System health snapshot, Environment preflight checks, Safe actions, Command-line recovery table) * docs(sso): refresh screenshots for SSO quickstart and feature pages * docs: refresh Features Overview screenshots and content Replace all 4 hero screenshots with fresh 1920x1080 production captures. Correct security posture state names (Action needed / Monitoring / Secure), add the Policies tab to the Security section tab list, mention the Simple mode in Scheduled operations, and update all alt text to match the new screenshots. * docs: refresh Appearance page screenshots and correct quick-switcher scope Replace all four Appearance screenshots with fresh production captures. Fix the quick-switcher control list: remove fonts (not present in the popover), add visual style and readability which are. Add Log chip color to the Display section. Update all screenshot alt text to match new captures. * docs: refresh stack management page with current UI and anatomy tabs * docs: fix convert-tab-error screenshot with fully visible error toast * docs: convert troubleshooting section to AccordionGroup format * docs(quickstart): refresh screenshots and align dashboard description Replace all three first-boot and dashboard screenshots with current UI. Add Security to the top navigation list, update gauge and Stack health descriptions to reflect sparklines and column detail, and align Configuration Status wording with the Introduction page. * docs(editor): rewrite anatomy panel, replace all screenshots - Correct the anatomy panel tab inventory: the panel has eight tabs (Anatomy, Activity, Dossier, Drift always; Environment, Networking, Doctor, Storage when the node advertises the matching capability), not three as previously documented - Add table describing all eight tabs with capability gates and links to dedicated feature pages - Add anatomy-tabs.png screenshot showing the scrollable tab row - Note the Doctor severity dot (red for blocker, amber for high-risk) - Remove the stale Markdown-export subsection; Dossier and Activity are now covered in the tab table - Replace all six stale screenshots with fresh 1920x1080 captures - Replace the compose diff preview screenshot * docs(files): refresh Files & Volumes screenshots and fix context-menu alt text Replace all 9 stale screenshots on the Files & Volumes page with fresh captures from the production node. Fix three alt-text strings that did not match the live UI: removed hardcoded octal value 644, and added the Duplicate, Copy to, and Move to entries missing from the context-menu alt text. * docs: rewrite Stack Activity page with full event categories and fresh screenshots Expands the event category table from 5 to 10 entries to cover drift detected, drift resolved, update started, health gate passed, and health gate failed. Adds a live-disconnected-state section, a background-actor attribution table, and a corrected troubleshooting accordion covering the WebSocket reconnect case. Replaces both stale screenshots with fresh 1920x1080 captures from the production node. * docs(drift): rewrite drift detection page with screenshots and full coverage Full rewrite of the Drift Detection feature page. Adds two previously undocumented finding types (network-undeclared, network-missing), expands the temporal section to distinguish the raw-file hash from the parsed-model hash, documents the two-layer spatial-engine and ledger architecture, explains when the ledger is reconciled (post-deploy vs manual re-check vs tab open), adds Activity timeline integration note, introduces a Limitations section (no background scanner, port-range caveat, history cap, advisory-only enforcement), expands Troubleshooting from five entries to seven using the AccordionGroup convention, and adds four production screenshots. * docs(drift): use CardGroup for Related section * docs(dossier): rewrite Stack Dossier page with full feature coverage * docs(networking): rewrite Compose Networking page with full feature coverage * docs(doctor): rewrite Compose Doctor with full 30-rule reference, screenshots, and cross-links * docs(networking): add production screenshots and correct alt text Adds 7 production screenshots for all sections of the Compose Networking page and updates the four placeholder alt texts written before screenshots were taken to match what the actual images show (arr-net external badge, swag service with 443/tcp and 80/tcp, single-service exposure intent row). Also adds the full-panel overview image at the top of the page. * docs(environment-guardrails): rewrite with project env file, env file status, and screenshots * docs(storage): rewrite Storage Portability page with screenshots and full coverage Rewrites compose-storage.mdx from a 61-line sketch into a complete reference page. Key additions: Where to find it section with screenshot, full storage inventory section documenting all mount type/access/status chips and the Linux owner display, expanded portability verdict section with per-reason detail and edge-case caveats (read-only binds, symlink escapes, anonymous volume risks), snapshot coverage section with admin scope and remote-node behavior, Findings in Doctor cross-reference, and six troubleshooting accordions covering tab visibility, bind status, external named volumes, render errors, and snapshot coverage states. Adds two production screenshots: storage-tab.png and storage-node-bound.png. * docs(stack-labels): rewrite with accurate permissions, capability gate, dry run, live preview, and color conflict docs * docs: rewrite Stack Sidebar page with accurate feature coverage Rewrites the Stack Sidebar documentation page to match the current UI. Key changes: - Fix branding header description (shows logo + version, not just version) - Fix bulk mode icon description (stacked-rows, not square) - Add cross-node search section (fan-out behavior, Other nodes section, unreachable-node warnings, click-to-switch navigation) - Update Labels submenu description (inline New label creation, Manage labels link) - Note that Delete only appears when the user has delete permission - Remove the auto-update implication from Schedule task description - Rewrite the Activity ticker section with the full 6-state priority cascade table; remove the non-existent IDLE state; correct pulsing-dot behavior - Replace all 7 stale screenshots with fresh production screenshots - Add new sidebar-cross-node-search.png screenshot * docs(atomic-deployments): refresh screenshot and document project env files, rollback readiness, and recovery actions * docs(atomic-deployments): fix rollback permission visibility and banner string accuracy The Rollback menu entry is hidden by the frontend when the user lacks stack:deploy; it never appears and does not 403. Fixed the step-4 narrative and troubleshooting accordion to match. The rollback-failure banner emitted by ComposeService is '=== Rollback failed. Manual intervention may be required ===' (period, capital M). Fixed both occurrences in the page. Updated the Settings navigation path from the nonexistent 'Roles & Access' to the real 'Access'. * docs(deploy-progress): rewrite with health gate, inline style, and 9 fresh screenshots Add health gate section covering all four states (observing, passed, failed, unknown) with exact UI banner text and the configurable observation window. Expand the inline style section with full band content, 4s auto-dismiss, and pill handoff. Add Scanning as a supported entry point. Replace all 6 existing screenshots and add 3 new ones (modal-health-gate, inline-banner, setting-style). Add two health gate troubleshooting accordions. Add Related CardGroup linking to health-gated-updates, stack-activity, deploy-enforcement, and atomic-deployments. * docs(health-gated-updates): refresh screenshots and correct signal row order and label * docs(deploy-enforcement): rewrite with fleet replication, honor suppressions location, scan-failed dialog state, and fresh screenshots Adds the Fleet policy replication section covering control/replica behavior, Managed by control node banner, and Demote to control. Documents the exact location of the Honor suppressions toggle (bottom of Policies tab). Expands the block dialog section with the scan-failed row state. Updates all three screenshots to the current visual design. Restores the Admiral license note and corrects the policy-card scope description. * docs(app-store): rewrite with mobile layout, fresh screenshots, and registry admin note - Replace all 5 stale screenshots with 1920x1080 production captures - Add app-store-mobile.png showing the status masthead layout - Document mobile single-column layout in a new Mobile subsection - Note that the featured hero has its own Deploy button - Mark the category rail as desktop only with a cross-link to Mobile - Add admin-account requirement to the custom registry section - Add Related CardGroup linking vulnerability scanning, deploy progress, deploy enforcement, and resources
321 lines
20 KiB
Plaintext
321 lines
20 KiB
Plaintext
---
|
|
title: SSO & LDAP Authentication
|
|
description: Authenticate with your existing identity provider, including LDAP, Google, GitHub, Okta, and any spec-compliant OIDC provider.
|
|
---
|
|
|
|
Sencho lets your team sign in with the identity provider you already use instead of maintaining a second set of credentials. SSO works **alongside** password authentication; it does not replace it.
|
|
|
|
SSO is available on every Sencho tier. Custom OIDC and the preset providers for Google, GitHub, and Okta work on every tier; LDAP and Active Directory require Sencho Admiral.
|
|
|
|
## Supported providers
|
|
|
|
| Provider | Protocol | Tier | Notes |
|
|
|----------|----------|------|-------|
|
|
| **Custom OIDC** | OpenID Connect | Community | Any spec-compliant OIDC provider: Authelia, Keycloak, Authentik, Zitadel, KanIDM, Pocket ID, and more |
|
|
| **Google** | OpenID Connect | Community | Preset for Google Workspace or personal Google accounts, with branded login button |
|
|
| **GitHub** | OAuth 2.0 | Community | Preset for GitHub personal accounts and GitHub orgs, with branded login button |
|
|
| **Okta** | OpenID Connect | Community | Preset for any Okta org or Okta-compatible IdP, with branded login button |
|
|
| **LDAP / Active Directory** | LDAP bind + search | Admiral | Works with OpenLDAP, Active Directory, FreeIPA, and any LDAPv3 server |
|
|
|
|
## How it works
|
|
|
|
### LDAP flow
|
|
|
|
1. User selects **LDAP** on the **Local / LDAP** toggle beside the **Sign in** heading and enters their directory username and password.
|
|
2. Sencho binds to LDAP with a service account, locates the user, then verifies their password.
|
|
3. On the user's first login, a Sencho account is created automatically.
|
|
4. Sencho issues a session JWT and the user is logged in, identical to a password login.
|
|
|
|
### OIDC / OAuth flow (Google, GitHub, Okta, Custom OIDC)
|
|
|
|
1. User clicks the provider button on the login page (the provider name under an **Or continue with** divider, e.g., **Google**).
|
|
2. The browser is redirected to the identity provider for authentication.
|
|
3. After granting consent, the provider redirects back to Sencho with an authorization code.
|
|
4. Sencho exchanges the code for tokens, verifies the ID token, and reads user information.
|
|
5. On the user's first login, a Sencho account is created automatically.
|
|
6. Sencho issues a session JWT and the user lands on the dashboard.
|
|
|
|
## Auto-provisioning
|
|
|
|
When a user signs in via SSO for the first time, Sencho creates a local account:
|
|
|
|
- **Username** is derived from the identity provider profile (display name, email prefix, or login handle).
|
|
- **Role** is assigned from [role mapping](#role-mapping); defaults to Viewer if no mapping matches.
|
|
- **Password** is set to an unusable placeholder. SSO users cannot sign in with the password form.
|
|
|
|
On every subsequent sign-in, the existing account is reused and the user's **email** and **role** are synced from the identity provider. Adding someone to your admin group promotes them to Admin on their next sign-in; removing them demotes them to the default role.
|
|
|
|
## Role mapping
|
|
|
|
### LDAP group mapping
|
|
|
|
Set the **Admin Group DN** to a group in your directory. Members of that group receive the Admin role; everyone else receives the default role (Viewer).
|
|
|
|
Example: if your admin group is `cn=sencho-admins,ou=groups,dc=example,dc=com`, set that as the **Admin Group DN**. Users whose `memberOf` attribute lists that DN are provisioned as Admin.
|
|
|
|
### OIDC claim mapping
|
|
|
|
For OIDC providers, configure two fields:
|
|
|
|
| Field | Description | Example |
|
|
|-------|-------------|---------|
|
|
| **Admin Claim** | The token claim name that contains role information | `groups` |
|
|
| **Admin Claim Value** | The value within that claim that grants Admin | `sencho-admins` |
|
|
|
|
If the user's ID token contains a `groups` claim with the value `sencho-admins`, they receive Admin. Otherwise, they receive the default role.
|
|
|
|
<Note>
|
|
Not every provider includes a `groups` claim by default. You may need to configure custom claims or scopes in your identity provider's admin console to surface group membership in the ID token.
|
|
</Note>
|
|
|
|
## Configuration
|
|
|
|
SSO can be configured two ways:
|
|
|
|
1. **Settings UI**: go to **Settings → Access → SSO** in the Sencho dashboard. Enable providers, paste credentials, and test connections from the UI. Changes take effect immediately, no restart required.
|
|
2. **Environment variables**: set `SSO_*` variables in your Docker Compose file. They seed the database on first boot; afterwards the Settings UI is authoritative.
|
|
|
|
### Via Settings UI
|
|
|
|
Admins manage SSO providers in **Settings → Access → SSO** (admin only; hidden on remote nodes). The masthead shows the SCOPE (global), the number of configured **PROVIDERS**, and how many are **ENABLED**. The page lists every provider as a collapsible card with a label, an **enable / disable** toggle pill on the right, and an **Active** badge on the header when the provider is on.
|
|
|
|
<Frame>
|
|
<img src="/images/sso/sso-settings.png" alt="SSO settings panel listing the five identity providers as collapsible cards with enable / disable toggles" />
|
|
</Frame>
|
|
|
|
Click a card to expand it. The footer of every expanded form has the same actions:
|
|
|
|
- **Save**: persists changes for that provider.
|
|
- **Test Connection**: runs a live check (LDAP bind for LDAP, OIDC discovery for the OIDC providers) and shows a green check or red X next to the button with the result.
|
|
- **Remove**: clears the saved configuration (only present once a config has been saved at least once).
|
|
|
|
A static helper sits below all five cards. It reminds you that SSO users are auto-provisioned on first login and shows the OAuth callback URL template for OIDC providers:
|
|
|
|
```
|
|
https://<your-sencho-url>/api/auth/sso/oidc/<provider>/callback
|
|
```
|
|
|
|
### LDAP fields
|
|
|
|
| Field | Description |
|
|
|-------|-------------|
|
|
| **Server URL** | LDAP server URL (e.g., `ldap://ldap.example.com:389` or `ldaps://...` for TLS) |
|
|
| **Bind DN** | Service account DN used to search the directory |
|
|
| **Bind Password** | Service account password |
|
|
| **Search Base** | Base DN for user searches (e.g., `ou=users,dc=example,dc=com`) |
|
|
| **Search Filter** | LDAP filter template using `{{username}}` as a placeholder |
|
|
| **Admin Group DN** | DN of the group whose members receive the Admin role |
|
|
| **Default Role** | Role assigned to users not in the admin group (Viewer or Admin) |
|
|
| **Verify TLS certificate** | Toggle to enable or disable TLS certificate verification |
|
|
|
|
For Active Directory, set **Search Filter** to `(sAMAccountName={{username}})`. The form's helper text shows the same example inline.
|
|
|
|
<Frame>
|
|
<img src="/images/sso/sso-settings-ldap.png" alt="LDAP / Active Directory configuration form with server URL, bind DN, search base, role mapping, and Verify TLS toggle" />
|
|
</Frame>
|
|
|
|
### OIDC fields (Google, GitHub, Okta)
|
|
|
|
| Field | Description |
|
|
|-------|-------------|
|
|
| **Issuer URL** | (Okta only) Your Okta org issuer URL, e.g., `https://dev-123456.okta.com` |
|
|
| **Client ID** | OAuth client ID from your identity provider |
|
|
| **Client Secret** | OAuth client secret |
|
|
| **Admin Claim** | Token claim name inspected for role mapping (default: `groups`) |
|
|
| **Admin Claim Value** | Value within the claim that grants Admin (default: `sencho-admins`) |
|
|
| **Scopes** | Space-separated OAuth scopes (default: `openid email profile`). Customize if your provider needs additional scopes to emit group claims. |
|
|
| **Default Role** | Role assigned when no claim mapping matches (Viewer or Admin) |
|
|
|
|
Google and GitHub already know their own issuer URL, so the form omits that field for those providers.
|
|
|
|
<Frame>
|
|
<img src="/images/sso/sso-settings-oidc.png" alt="Google OIDC configuration form with client ID, client secret, admin claim mapping, scopes, and default role" />
|
|
</Frame>
|
|
|
|
### Custom OIDC fields
|
|
|
|
The **Custom OIDC** form adds the fields needed to point Sencho at a self-hosted or third-party identity provider:
|
|
|
|
| Field | Description |
|
|
|-------|-------------|
|
|
| **Display Name** | Label shown on the login button (e.g., `Corporate SSO`) |
|
|
| **Issuer URL** | Base URL of the OIDC discovery endpoint (without `/.well-known/openid-configuration`) |
|
|
| **User ID Claim** | Claim used as the unique user identifier (default: `sub`) |
|
|
| **Username Claim** | Claim used for the display name (default: `preferred_username`) |
|
|
| **Email Claim** | Claim used for the email address (default: `email`) |
|
|
|
|
Leave the three claim fields blank to use the standard OIDC defaults. Most spec-compliant providers will work out of the box; override only when your provider emits non-standard claim names.
|
|
|
|
<Frame>
|
|
<img src="/images/sso/sso-settings-custom-oidc.png" alt="Custom OIDC configuration form with display name, issuer URL, claim mapping fields, scopes, and default role" />
|
|
</Frame>
|
|
|
|
<Note>
|
|
The **User ID Claim**, **Username Claim**, and **Email Claim** fields are also accepted on Google, GitHub, and Okta as environment variables (see [Custom OIDC env vars](#custom-oidc)). The Settings UI hides them on the presets because the defaults match those providers; reach for them only if you have a custom claim layout to map.
|
|
</Note>
|
|
|
|
### Via environment variables
|
|
|
|
Environment variables are useful for initial deployment and infrastructure-as-code workflows. They seed the SSO configuration on first startup. After that, changes made in the Settings UI take precedence.
|
|
|
|
## SSO environment variables reference
|
|
|
|
### LDAP
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `SSO_LDAP_ENABLED` | `false` | Enable LDAP authentication |
|
|
| `SSO_LDAP_DISPLAY_NAME` | `LDAP` | Label shown on the login button (e.g., `Corporate AD`) |
|
|
| `SSO_LDAP_URL` | - | LDAP server URL (e.g., `ldap://ldap.example.com:389` or `ldaps://ldap.example.com:636`) |
|
|
| `SSO_LDAP_BIND_DN` | - | Service account DN for searching users |
|
|
| `SSO_LDAP_BIND_PASSWORD` | - | Service account password (encrypted at rest in the database) |
|
|
| `SSO_LDAP_SEARCH_BASE` | - | Base DN for user searches (e.g., `ou=users,dc=example,dc=com`) |
|
|
| `SSO_LDAP_SEARCH_FILTER` | `(uid={{username}})` | LDAP filter template. Use `(sAMAccountName={{username}})` for Active Directory |
|
|
| `SSO_LDAP_ADMIN_GROUP_DN` | - | DN of the group whose members receive the Admin role |
|
|
| `SSO_LDAP_DEFAULT_ROLE` | `viewer` | Role assigned to LDAP users not in the admin group |
|
|
| `SSO_LDAP_TLS_REJECT_UNAUTHORIZED` | `true` | Set to the literal string `false` to skip TLS certificate verification (useful for self-signed certs in development) |
|
|
|
|
### Google OIDC
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `SSO_OIDC_GOOGLE_ENABLED` | `false` | Enable Google SSO |
|
|
| `SSO_OIDC_GOOGLE_CLIENT_ID` | - | OAuth client ID from Google Cloud Console |
|
|
| `SSO_OIDC_GOOGLE_CLIENT_SECRET` | - | OAuth client secret (encrypted at rest) |
|
|
|
|
### GitHub OAuth
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `SSO_OIDC_GITHUB_ENABLED` | `false` | Enable GitHub SSO |
|
|
| `SSO_OIDC_GITHUB_CLIENT_ID` | - | OAuth app client ID from GitHub Developer Settings |
|
|
| `SSO_OIDC_GITHUB_CLIENT_SECRET` | - | OAuth app client secret (encrypted at rest) |
|
|
|
|
### Okta OIDC
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `SSO_OIDC_OKTA_ENABLED` | `false` | Enable Okta SSO |
|
|
| `SSO_OIDC_OKTA_ISSUER_URL` | - | Okta issuer URL (e.g., `https://dev-123456.okta.com`) |
|
|
| `SSO_OIDC_OKTA_CLIENT_ID` | - | Okta application client ID |
|
|
| `SSO_OIDC_OKTA_CLIENT_SECRET` | - | Okta client secret (encrypted at rest) |
|
|
|
|
### Custom OIDC
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `SSO_OIDC_CUSTOM_ENABLED` | `false` | Enable the custom OIDC provider |
|
|
| `SSO_OIDC_CUSTOM_DISPLAY_NAME` | `Custom OIDC` | Label shown on the login button |
|
|
| `SSO_OIDC_CUSTOM_ISSUER_URL` | - | OIDC issuer URL (the base of the discovery endpoint) |
|
|
| `SSO_OIDC_CUSTOM_CLIENT_ID` | - | OAuth client ID from your identity provider |
|
|
| `SSO_OIDC_CUSTOM_CLIENT_SECRET` | - | OAuth client secret (encrypted at rest) |
|
|
| `SSO_OIDC_CUSTOM_SCOPES` | `openid email profile` | Space-separated OAuth scopes |
|
|
| `SSO_OIDC_CUSTOM_ID_CLAIM` | `sub` | Token claim for the unique user identifier |
|
|
| `SSO_OIDC_CUSTOM_USERNAME_CLAIM` | `preferred_username` | Token claim for the display name |
|
|
| `SSO_OIDC_CUSTOM_EMAIL_CLAIM` | `email` | Token claim for the email address |
|
|
|
|
The `*_ID_CLAIM`, `*_USERNAME_CLAIM`, and `*_EMAIL_CLAIM` variables are also accepted for Google, GitHub, and Okta (substitute the provider prefix, e.g., `SSO_OIDC_OKTA_USERNAME_CLAIM`). They override the per-provider defaults when your token layout differs.
|
|
|
|
### General
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `SSO_OIDC_ADMIN_CLAIM` | `groups` | Token claim name inspected for Admin role mapping |
|
|
| `SSO_OIDC_ADMIN_CLAIM_VALUE` | `sencho-admins` | Value in the admin claim that maps to the Admin role |
|
|
| `SSO_DEFAULT_ROLE` | `viewer` | Default role for all SSO users when no mapping matches |
|
|
| `SSO_CALLBACK_URL` | auto-detect | External base URL for OAuth callback URLs (see below) |
|
|
|
|
## Reverse proxy and callback URLs
|
|
|
|
<Warning>
|
|
If Sencho is behind a reverse proxy (nginx, Traefik, Caddy), you **must** set `SSO_CALLBACK_URL` to your external URL. Otherwise, OAuth callbacks will fail.
|
|
</Warning>
|
|
|
|
Set `SSO_CALLBACK_URL` to the URL users use to reach Sencho, for example, `https://sencho.example.com`. Sencho uses this to construct the OAuth redirect URI that your identity provider calls back to.
|
|
|
|
If not set, Sencho auto-detects the URL from the request's `Host` header and protocol, which works for direct access but fails behind proxies that rewrite the host.
|
|
|
|
## Provider-specific setup examples
|
|
|
|
### Keycloak
|
|
|
|
1. Create a new client in your Keycloak realm (Client type: **OpenID Connect**).
|
|
2. Set **Valid redirect URIs** to `https://sencho.example.com/api/auth/sso/oidc/oidc_custom/callback`.
|
|
3. Enable **Client authentication** (confidential access type) and copy the client secret from the **Credentials** tab.
|
|
4. The Issuer URL is your realm URL: `https://keycloak.example.com/realms/myrealm`.
|
|
5. Keycloak uses standard claim names by default, so claim mapping can be left blank.
|
|
|
|
### Authentik
|
|
|
|
1. Create a new **OAuth2 / OpenID Provider** in Authentik.
|
|
2. Set the redirect URI to `https://sencho.example.com/api/auth/sso/oidc/oidc_custom/callback`.
|
|
3. Copy the Client ID and Client Secret.
|
|
4. The Issuer URL is `https://authentik.example.com/application/o/<slug>/`.
|
|
5. Standard claims work. For group-based admin mapping, configure a `groups` scope in Authentik so it emits the claim into the ID token.
|
|
|
|
### Authelia
|
|
|
|
1. Add an OpenID Connect client to your Authelia configuration under `identity_providers.oidc.clients`.
|
|
2. Set `redirect_uris` to include `https://sencho.example.com/api/auth/sso/oidc/oidc_custom/callback`.
|
|
3. The Issuer URL is your Authelia domain: `https://auth.example.com`.
|
|
4. Authelia uses standard OIDC claims.
|
|
|
|
### Zitadel
|
|
|
|
1. Create a new **Web** application in your Zitadel project.
|
|
2. Add `https://sencho.example.com/api/auth/sso/oidc/oidc_custom/callback` as a redirect URI.
|
|
3. The Issuer URL is your Zitadel instance URL: `https://zitadel.example.com`.
|
|
4. Copy the Client ID and Client Secret from the application settings.
|
|
|
|
### KanIDM
|
|
|
|
1. Create a new OAuth2 client in KanIDM (`kanidm system oauth2 create ...`).
|
|
2. Add the redirect URL with `kanidm system oauth2 add-redirect-url ...` and fetch the basic secret with `kanidm system oauth2 show-basic-secret ...`.
|
|
3. The Issuer URL is `https://kanidm.example.com/oauth2/openid/<client_id>`.
|
|
4. KanIDM may emit `name` instead of `preferred_username` for the username claim. If usernames look wrong after the first login, set **Username Claim** to `name`.
|
|
|
|
### Pocket ID
|
|
|
|
1. Create a new OIDC client in Pocket ID.
|
|
2. Set the callback URL to `https://sencho.example.com/api/auth/sso/oidc/oidc_custom/callback`.
|
|
3. The Issuer URL is your Pocket ID instance URL.
|
|
4. Copy the Client ID and Client Secret from the client view (Pocket ID shows the secret only at creation; reset it from the same screen if you lose it).
|
|
|
|
## Security
|
|
|
|
- **PKCE**: All OIDC flows use `code_challenge_method=S256` to prevent authorization code interception.
|
|
- **State parameter**: A cryptographic random value protects against CSRF on the OAuth callback.
|
|
- **Encrypted secrets**: LDAP bind passwords and OIDC client secrets are encrypted at rest in the Sencho database.
|
|
- **No local password**: SSO users are created with an unusable password hash and cannot bypass SSO by using the password sign-in form.
|
|
- **Admin-only configuration**: Only administrators can enable or configure SSO providers.
|
|
|
|
## Troubleshooting
|
|
|
|
<AccordionGroup>
|
|
<Accordion title="Test Connection returns 'Discovery failed' or a network timeout">
|
|
The Sencho container could not reach the provider's discovery URL. Verify the **Issuer URL** is reachable from inside the container (not just from your browser), confirm it does not include `/.well-known/openid-configuration` (just the base issuer URL), and check that container DNS can resolve the hostname. For providers with HTTPS, make sure the certificate chain is valid; self-signed certs may need additional container configuration.
|
|
</Accordion>
|
|
|
|
<Accordion title="Sign-in fails with an issuer validation error">
|
|
The `issuer` value in the provider's discovery document does not match what Sencho expects. This commonly happens when the **Issuer URL** has a trailing-slash mismatch (e.g., `https://auth.example.com` vs `https://auth.example.com/`), or when the provider is accessed via a different hostname than it advertises in its discovery document. Fix: set the **Issuer URL** to exactly match the `issuer` field returned by your provider's `/.well-known/openid-configuration` endpoint.
|
|
</Accordion>
|
|
|
|
<Accordion title="Users land with the wrong username or no email">
|
|
Enable **Developer Mode** (Settings → Operations → Developer Diagnostics) to log the raw claims Sencho receives from the provider in the server logs. Check your provider's documentation for which claims it includes in the ID token and `userinfo` response, and verify that the configured **Scopes** include everything your provider needs to emit `email` and group claims. For Custom OIDC, override **User ID Claim**, **Username Claim**, or **Email Claim** to match the names your provider actually emits.
|
|
</Accordion>
|
|
|
|
<Accordion title="The provider returns 'invalid redirect URI' during sign-in">
|
|
The callback URL registered with your identity provider must exactly match `https://sencho.example.com/api/auth/sso/oidc/<provider>/callback`, where `<provider>` is `oidc_google`, `oidc_github`, `oidc_okta`, or `oidc_custom`. If Sencho sits behind a reverse proxy, set `SSO_CALLBACK_URL` to your external URL. Some providers are strict about trailing slashes and HTTP vs HTTPS.
|
|
</Accordion>
|
|
|
|
<Accordion title="SSO buttons do not appear on the login page">
|
|
Verify the provider is **enabled** (toggle on, showing the **Active** badge) in **Settings → Access → SSO** and that the configuration saved successfully. The login page fetches the list of enabled providers when it loads; hard-refresh the tab if changes were just made.
|
|
</Accordion>
|
|
</AccordionGroup>
|
|
|
|
The [operations troubleshooting page](/operations/troubleshooting#ldap-connection-refused) covers a few more cases that come up during initial setup, including LDAP connection refused, TLS certificate errors, and OAuth callback URL mismatches.
|
|
|
|
## Combining SSO with two-factor authentication
|
|
|
|
SSO and [two-factor authentication](/features/two-factor-authentication) work together. By default, SSO sign-ins skip the TOTP challenge, since the identity provider has already authenticated the user. Operators who want a stricter posture can turn on **Require 2FA on SSO sign-in** in **Settings → Personal → Account** to require both factors on every SSO sign-in. The toggle sits in the Two-factor authentication section and appears once you have 2FA enrolled and at least one SSO provider is enabled.
|