Rather not set up SSO for Open WebUI yourself? The WZ-IT AI platform is Open WebUI as a managed service: your own instance, models operated in Germany by German providers and SSO are included in the monthly price from €149.90 net. View the AI platform · Clarify the integration together
Open WebUI signs users in through OpenID Connect (OIDC) at an identity provider. The configuration consists of a few environment variables and fails in practice on details: a redirect URI that is off by one character, a claim that is not in the token, or a first login that turns the wrong account into the administrator. This guide walks through the setup with Microsoft Entra ID and Keycloak, places Authentik and ZITADEL and ends with a checklist. It is based on the Open WebUI documentation, the source code of Open WebUI v0.12.4 and the documentation of the identity providers. As of 28 October 2026.
Table of contents
- Which sign-in path fits
- Settle before the first login
- Base configuration
- Microsoft Entra ID
- Keycloak
- Authentik and ZITADEL
- Roles and groups
- SCIM and offboarding
- Emergency access and password login
- Multiple replicas and reverse proxy
- Typical failure patterns
- Checklist after setup
- SSO and licence at WZ-IT
- As of and methodology
- Our approach at WZ-IT
- Further guides
Which sign-in path fits
| Path | Suited for | Redirect URI | Core variables |
|---|---|---|---|
| Generic OIDC | Keycloak, Authentik, ZITADEL, Okta and any OIDC provider | /oauth/oidc/callback |
OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, OPENID_PROVIDER_URL |
| Microsoft provider | Entra ID, one tenant | /oauth/microsoft/callback |
MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET, MICROSOFT_CLIENT_TENANT_ID |
| Trusted header | Authenticating reverse proxy (oauth2-proxy, Cloudflare Access, Tailscale Serve) | none | WEBUI_AUTH_TRUSTED_EMAIL_HEADER |
Only one OIDC provider can be configured at a time, and the Microsoft provider supports a single tenant (SSO documentation). With a trusted header, Open WebUI must only be reachable by the proxy: anyone who can set the header themselves signs in as any user. The rest of this guide covers OIDC.
Settle before the first login
- Create the local administrator first. The first account on a fresh instance becomes administrator, even if it is created through SSO: the code assigns the role
adminas soon as exactly one user exists after the insert.WEBUI_ADMIN_EMAILandWEBUI_ADMIN_PASSWORDcreate the account on first start and switch off self-registration (environment variables). - Set
WEBUI_URLbefore the first SSO login. The variable is a persistent setting: later changes to the environment variable no longer apply, only the admin area orENABLE_PERSISTENT_CONFIG=falsedo. - Assign a fixed
WEBUI_SECRET_KEY. It signs session tokens and encrypts OAuth tokens. An automatically generated key lives inside the container; if the container is recreated, all sessions become invalid. - Set the redirect URI explicitly. Without
OPENID_REDIRECT_URI, Open WebUI derives it from the request; behind a proxy that changes the URL it then differs from the entry at the identity provider.
Base configuration
services:
open-webui:
image: ghcr.io/open-webui/open-webui:v0.12.4 # pin the version
environment:
WEBUI_URL: "https://chat.example.com"
WEBUI_SECRET_KEY: "${WEBUI_SECRET_KEY}"
ENABLE_OAUTH_SIGNUP: "true"
OAUTH_PROVIDER_NAME: "Keycloak"
OAUTH_CLIENT_ID: "open-webui"
OAUTH_CLIENT_SECRET: "${OAUTH_CLIENT_SECRET}"
OPENID_PROVIDER_URL: "https://id.example.com/realms/company/.well-known/openid-configuration"
OPENID_REDIRECT_URI: "https://chat.example.com/oauth/oidc/callback"
OAUTH_SCOPES: "openid email profile"
| Variable | Default | Effect |
|---|---|---|
ENABLE_OAUTH_SIGNUP |
false |
Without true, SSO creates no new accounts and the first login is rejected with 403 |
DEFAULT_USER_ROLE |
pending |
New accounts wait for approval as long as no roles come from the token |
OAUTH_MERGE_ACCOUNTS_BY_EMAIL |
false |
Links SSO accounts to local accounts with the same address; unsafe if the provider does not verify addresses |
ENABLE_OAUTH_PERSISTENT_CONFIG |
false |
Environment variables stay authoritative, the OAuth section in the admin panel is read-only |
OAUTH_TOKEN_ENDPOINT_AUTH_METHOD |
not set | client_secret_basic or client_secret_post if the provider accepts only one method |
Microsoft Entra ID
- Register the app. Platform "Web", redirect URI
https://chat.example.com/oauth/microsoft/callback. Microsoft requires https (exception: localhost) and treats the URL path as case-sensitive (redirect URI rules). - Create a client secret. Its lifetime is at most 24 months, and Microsoft recommends less than 12 (credentials). When the secret expires, nobody can sign in; the expiry date and renewal belong in the operations calendar.
- Permissions: delegated
openid,emailandprofilewith administrator consent. The scopeoffline_accessis added inMICROSOFT_OAUTH_SCOPE; it needs no further configuration in Entra. Without it, token renewal fails after about an hour; model connections using OAuth and SharePoint access are affected, the chat itself is not (SSO documentation).
MICROSOFT_CLIENT_ID=<application ID>
MICROSOFT_CLIENT_SECRET=<client secret>
MICROSOFT_CLIENT_TENANT_ID=<directory ID>
MICROSOFT_REDIRECT_URI=https://chat.example.com/oauth/microsoft/callback
MICROSOFT_OAUTH_SCOPE=openid email profile offline_access
ENABLE_OAUTH_SIGNUP=true
OPENID_PROVIDER_URL is not required for Microsoft: sign-in and sign-out use the tenant's own discovery URL (SSO documentation, troubleshooting). The community group name sync tutorial still sets it as "Required for logout to work properly" (https://login.microsoftonline.com/<directory ID>/v2.0/.well-known/openid-configuration).
Restrict access. A registered app is open to all users of the tenant by default. With "Assignment required", only assigned users and groups get through, Global Administrators excepted (Microsoft). Combined with ENABLE_OAUTH_SIGNUP=true, every person in the tenant would otherwise get an account. Assigning groups (instead of individual users) requires Entra ID P1 or P2, and nested groups are not taken into account (Microsoft).
Roles through app roles. Create the app roles admin and user and assign groups; Entra writes them into the claim roles (Microsoft). In Open WebUI, ENABLE_OAUTH_ROLE_MANAGEMENT=true is enough; the defaults OAUTH_ROLES_CLAIM=roles, OAUTH_ALLOWED_ROLES=user,admin and OAUTH_ADMIN_ROLES=admin match.
Groups, with pitfalls. The groups claim contains object IDs by default, and a JWT carries at most 200 groups; for large organisations Microsoft recommends "Groups assigned to the application" (optional claims). Open WebUI contains no Graph lookup for the overflow case (checked in utils/oauth.py). Plain-text names come from groupMembershipClaims: ApplicationGroup and the property cloud_displayname, which only works in that combination.
Email claim. Open WebUI needs email. Microsoft calls the value not guaranteed to be correct and mutable, and advises never to use it for authorisation (claims reference). OAUTH_MERGE_ACCOUNTS_BY_EMAIL should therefore only be active for a limited time, for example to take over local accounts.
Keycloak
- Create the client in its own realm (not in
master): type OpenID Connect, client authentication on (confidential client), standard flow on. The redirect URIhttps://chat.example.com/oauth/oidc/callbackis compared exactly and case-sensitively; wildcards are only possible at the end of the pattern, and the full wildcard*does not belong in production (Keycloak). The secret is on the "Credentials" tab. - Discovery URL:
https://id.example.com/realms/<realm>/.well-known/openid-configuration(Keycloak, endpoints). The variables match the base configuration.
Roles: realm roles are in the claim realm_access.roles by default, but only in the access token and the introspection endpoint (Keycloak, token roles). Open WebUI reads claims from the ID token and userinfo. In the "realm roles" mapper, "Add to ID token" therefore has to be on; then OAUTH_ROLES_CLAIM=realm_access.roles applies (nested paths are allowed) together with OAUTH_ADMIN_ROLES=admin.
Groups: the "Group Membership" mapper with the claim name groups and "Add to ID token" on. "Full group path" is on by default and produces values such as /engineering; switch it off for names without the slash (mapper source code). Then set ENABLE_OAUTH_GROUP_MANAGEMENT=true.
Authentik and ZITADEL
Authentik: an application with an OAuth2/OpenID provider, redirect URI of type "Strict" on /oauth/oidc/callback, discovery at https://<authentik>/application/o/<slug>/.well-known/openid-configuration. Roles come from application entitlements and a scope mapping roles; add OAUTH_SCOPES="openid email profile roles" (Authentik, support level: community). The example there switches off the login form and password login, which removes local emergency access.
ZITADEL: application type Web; ZITADEL recommends PKCE (ZITADEL), in Open WebUI with OAUTH_CODE_CHALLENGE_METHOD=S256. Discovery: <instance>/.well-known/openid-configuration. The role claim urn:zitadel:iam:org:project:roles is an object (role to organisation) (ZITADEL, claims); Open WebUI reads lists or strings. The ZITADEL documentation shows an action (Actions V1) that writes roles as a flat list with values of the form project ID:role into a claim of its own; Actions V1 are planned to be sunset in ZITADEL V5, and new implementations belong on Actions V2 (ZITADEL, migration).
Roles and groups
| Roles | Groups | |
|---|---|---|
| Purpose | System role user or admin, access at all |
Rights to models, knowledge bases, tools |
| Switch | ENABLE_OAUTH_ROLE_MANAGEMENT |
ENABLE_OAUTH_GROUP_MANAGEMENT |
| Claim | OAUTH_ROLES_CLAIM (default roles) |
OAUTH_GROUP_CLAIM (default groups) |
| Further variables | OAUTH_ALLOWED_ROLES (user,admin), OAUTH_ADMIN_ROLES (admin) |
ENABLE_OAUTH_GROUP_CREATION, OAUTH_BLOCKED_GROUPS |
| Claim present, value does not match | login rejected with 403 | memberships are removed |
| Claim missing or empty | role stays, new users get DEFAULT_USER_ROLE |
memberships stay unchanged |
Group synchronisation is strict: anyone manually added in Open WebUI to a group that is not in the claim loses the membership at the next login, administrators included. Local groups can be excluded with OAUTH_BLOCKED_GROUPS. Role and group changes only apply after a new sign-in (documentation). How groups carry rights is described on the page about groups.
SCIM and offboarding
Open WebUI documents SCIM 2.0 for provisioning users and groups (SCIM documentation). It is enabled with SCIM_ENABLED=true, a random SCIM_TOKEN and SCIM_AUTH_PROVIDER (microsoft or oidc); the base URL is https://chat.example.com/api/v1/scim/v2/. According to the documentation, active: false sets the role to pending and ends the running WebSocket connections, and a pending account is turned away by the API and the WebSocket; administrators can be neither deleted nor demoted through SCIM, and locally created accounts are invisible to SCIM. On v0.12.0, the SSO sign-in of SCIM users failed with 401; since v0.12.1 this is fixed. Neither the SCIM page nor the licence page names a licence restriction for SCIM, and routers/scim.py contains no licence check; the licence text remains authoritative. Entra syncs applications outside the gallery roughly every 40 minutes (Microsoft).
Without SCIM, a blocked account stays usable in Open WebUI until the session token expires. JWT_EXPIRES_IN defaults to four weeks. Without Redis, signing out does not revoke individual tokens, and back-channel logout (ENABLE_OAUTH_BACKCHANNEL_LOGOUT) also needs Redis (SSO troubleshooting). Three routes remain for offboarding: SCIM, Redis with back-channel logout, or a short lifetime of hours to a few days. Administrators end all sessions of an account with "Sign out all devices".
Emergency access and password login
| Setting | Effect | Consequence |
|---|---|---|
ENABLE_SIGNUP=false |
no local self-registration (default: true) |
always set |
ENABLE_LOGIN_FORM=false |
form hidden, local registration via API rejected | password sign-in via API and at /auth?form=true remains possible |
ENABLE_PASSWORD_AUTH=false |
blocks every password sign-in, API and LDAP included | no local emergency access any more |
OAUTH_AUTO_REDIRECT=true |
straight to the provider, only with one provider and ENABLE_LOGIN_FORM=false |
/auth?form=true shows the local form |
The documentation ties ENABLE_PASSWORD_AUTH=false to ENABLE_OAUTH_SIGNUP being on and SSO working, and recommends it for SSO-only instances that are publicly reachable (environment variables). A robust interim state: self-registration off, form hidden, one local administrator with a long password in a vault. Open WebUI offers two-factor sign-in with an authenticator app; SSO logins can be exempted if the identity provider already enforces a second factor. /auth?form=true and /api/v1/auths/signin should only be reachable from the admin network, for example through VPN or NetBird. The full block ENABLE_PASSWORD_AUTH=false is a second step, secured by a test with the identity provider switched off.
Multiple replicas and reverse proxy
WEBUI_SECRET_KEYidentical on all replicas, otherwise login loops, 401 errors and "Error decrypting tokens".OAUTH_SESSION_TOKEN_ENCRYPTION_KEYtakes the same value by default.- External PostgreSQL instead of SQLite, Redis (
REDIS_URL,WEBSOCKET_MANAGER=redis) and an external vector database (scaling). - The proxy does not cache
/api,/oauthand/wsand passes WebSocket headers through. Cookies withSameSite=lax; for slow providersOAUTH_TIMEOUThelps.
Typical failure patterns
| Symptom | Cause | Fix |
|---|---|---|
| Error at the provider, with Entra AADSTS50011 | redirect URI differs: path, case, http instead of https, oidc instead of microsoft |
register the URI exactly as https://<domain>/oauth/<provider>/callback (Microsoft) |
| Back at the sign-in page with "Sign-in with your identity provider failed" | catch-all message, among others for a failed token exchange, missing email, missing sub claim, domain not allowed; roles that are not allowed or ENABLE_OAUTH_SIGNUP=false report "You do not have permission to access this resource" instead |
read the backend log |
| New user waits for approval | DEFAULT_USER_ROLE=pending and no role claim |
set up role mapping or deliberately set user |
| "Email already registered" | local account with the same address | merge accounts, for a limited time with OAUTH_MERGE_ACCOUNTS_BY_EMAIL |
Loop after login, mismatching_state |
inconsistent key, cookie settings, proxy cache, deviating WEBUI_URL |
section on replicas and proxy |
Checklist after setup
- Login with a standard user, an administrator and an unauthorised person; the last one is turned away.
- New users get the expected role, not an unintended
pending. - Groups are correct after signing in again; removal at the identity provider takes effect at the next login.
- Local emergency administrator: password in a vault, two-factor active, access path tested and limited to the admin network.
-
ENABLE_SIGNUP=false; decision on the login form andENABLE_PASSWORD_AUTHdocumented. -
WEBUI_SECRET_KEYpersistent and backed up, identical across replicas; image version pinned. - Client secret expiry date in the calendar, renewal rehearsed.
- Offboarding test: block an account at the identity provider and measure when access ends.
- MFA enforced at the identity provider (Conditional Access or the Keycloak authentication flow).
SSO and licence at WZ-IT
On the AI platform, SSO is included in every package in the monthly price (sign-in with Microsoft Entra ID, Google or Keycloak; packages from €149.90 net per month, depending on the number of users). For an Open WebUI instance in another environment, WZ-IT connects Keycloak or Authentik depending on the environment and plans SSO, groups and roles together with the customer; existing identity providers can be taken over after an interface check. According to the manufacturer's licence page, connecting SSO and LDAP is allowed without an enterprise licence as long as the Open WebUI branding stays visible and unchanged (licence page). The assessment is in the article Open WebUI License 2026 and is not legal advice. WZ-IT runs Open WebUI with the original branding.
As of and methodology
Checked on 28 October 2026 against the Open WebUI documentation, the source code of open-webui/open-webui v0.12.4 (25 October 2026; utils/oauth.py, routers/auths.py, routers/scim.py), the Microsoft Learn pages, the Keycloak documentation including the mapper source code, and the Authentik and ZITADEL pages. The LICENSE file last changed on 14 April 2026. The configurations are derived from documentation and code, not a record of a test run. Not covered: Okta, Google, GitHub, LDAP.
Our approach at WZ-IT
The order of an integration: define roles and groups at the identity provider before the first sign-in runs, set up the local administrator with two-factor sign-in and check the offboarding path, that is the moment access ends after an account is blocked. This includes a fixed WEBUI_SECRET_KEY, a pinned version and a test of emergency access.
Further guides
- Running Open WebUI as a local AI appliance in production - operations, backup, updates and monitoring
- Open WebUI License 2026 - branding clause and enterprise licence
- Open WebUI vs. LibreChat - comparison of the two interfaces
- Secure remote access to local AI - VPN and NetBird for admin paths
- RAG permissions - what groups achieve with knowledge sources
- Keycloak, Authentik, ZITADEL and Open WebUI - expertise pages
Run Open WebUI with SSO in production? The AI platform includes SSO in the monthly price from €149.90 net. Book a call











