Once the first Open WebUI Entra ID SSO login works, the Day-2 failures trace to a short list of causes, pinned here to v0.11.4, the latest release on 7 October 2026. Provider registration is environment-only: MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET and MICROSOFT_CLIENT_TENANT_ID are read once at startup, the Admin Panel has no Microsoft fields, and issue #26917 about it has been open since July. Entra emits group object IDs by default; names need the cloud_displayname optional claim with groupMembershipClaims set to ApplicationGroup only, plus each group assigned to the Enterprise Application with users as its direct members, and AD-synced groups need sAMAccountName instead. Past 200 groups in a JWT, Entra omits the groups claim entirely, and Open WebUI has no overage handling (#17510 is an open feature request). With ENABLE_OAUTH_GROUP_MANAGEMENT on, every login removes the user from every group not in the claim, admins included, unless the group matches OAUTH_BLOCKED_GROUPS. JIT creation still creates blocked groups at v0.11.4 because the fix was merged after that release, so keep ENABLE_OAUTH_GROUP_CREATION off and pre-create groups with exact names. Start by setting GLOBAL_LOG_LEVEL=DEBUG for one test login and reading the 'User oauth groups' line before touching any setting.
The first Open WebUI Entra ID SSO login is the easy part. Day 2 is where it breaks: groups appear as strings of hex, a few users have no groups at all or sit in pending, a curated group that an admin filled by hand is empty by Friday, and settings changed in the Admin Panel do nothing.
Each of these traces to a documented Microsoft Entra ID (formerly Azure AD) behaviour or to specific Open WebUI code, and three have an open or unreleased upstream issue behind them. Everything below is pinned to Open WebUI v0.11.4, published on 21 September 2026 and still the latest release when this post went out, and checked against the source at that tag and Microsoft's identity platform documentation. Where the Open WebUI docs and the code disagree, the code wins and we say so.
If you are still choosing a workspace, start with our comparison of Open WebUI, LibreChat and AnythingLLM. SSO-related CVEs live in the Open WebUI advisories breakdown and are not repeated here.
Open WebUI Microsoft Entra ID setup: MICROSOFT_* variables, not generic OIDC
Open WebUI ships a dedicated microsoft provider. Use it. Configuring Entra through the generic OIDC variables (OAUTH_CLIENT_ID, OPENID_PROVIDER_URL) is the Entra mistake the official troubleshooting guide calls out.
At v0.11.4 the provider is registered only when all three of MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET and MICROSOFT_CLIENT_TENANT_ID are set. Open WebUI builds the discovery URL from MICROSOFT_CLIENT_LOGIN_BASE_URL (default https://login.microsoftonline.com), the tenant and the client ID. MICROSOFT_OAUTH_SCOPE defaults to openid email profile, which is what the group-name tutorial asks you to grant as delegated permissions with admin consent.
Three details on this layer decide whether sign-in works:
/oauth/microsoft/callback. When MICROSOFT_REDIRECT_URI is empty, Open WebUI derives the URI from the incoming request. Behind a reverse proxy that terminates TLS, the derived URI can come out as http:// and stop matching the registration in Entra. Set it explicitly.ENABLE_OAUTH_SIGNUP defaults to false. Without it, an Entra user who has no Open WebUI account yet is refused with a 403. Here and in the role checks below, the 403 is raised inside the callback, so the browser is redirected to the sign-in page with "You do not have permission to access this resource" rather than shown an HTTP 403 page. With it, new accounts get DEFAULT_USER_ROLE, which defaults to pending.OAuth providers configured (Microsoft) but OPENID_PROVIDER_URL not set - logout will not work! at startup. The warning is stale for a Microsoft-only setup. Ignore it, or set the variable to your tenant discovery URL to silence it.One more fact shapes every section that follows: Open WebUI reads groups and roles from the ID token. It parses the ID token first and only calls the userinfo endpoint when the email or username claim is missing. Every claim change you make in Entra has to target the ID token, not just the access token.
Open WebUI Entra ID SSO never activates, or Admin Panel changes do nothing
Two separate layers produce this symptom, and the fix depends on which one you hit.
ENABLE_PERSISTENT_CONFIG defaults to true and ENABLE_OAUTH_PERSISTENT_CONFIG defaults to false. While the OAuth flag is false, every key starting with oauth. is read from environment-derived defaults. If someone calls the API directly anyway, the value lands in the worker's memory only: it is not saved, and with several workers each one can hold a different answer.
Flipping the flag to true has a trap of its own. A July fix (PR #26928) stopped Open WebUI seeding oauth.* rows into the database while the flag is off, but the maintainer noted it only prevents new seeding. An install that booted with the flag off before that fix may carry stale oauth.* rows captured from an empty environment, and those rows win the moment the flag goes to true. The maintainer's stated cleanup is a one-time deletion of config rows whose key starts with oauth.. Take a database backup first.
Our recommendation: leave the flag false and treat the environment file as the single source of truth for SSO. It is reviewable and versioned, which is what a change board wants.
Layer 1: provider registration is environment-only
In v0.11.4, load_oauth_providers() reads the provider settings from environment-derived values, and its only call site is when config.py is imported at startup. The OAuth manager registers clients from that result once. Nothing re-registers a client from database values. The Admin Panel form has fields for generic OIDC (OPENID_PROVIDER_URL, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, OPENID_REDIRECT_URI, OAUTH_SCOPES) plus signup, role and group settings, and no Microsoft fields at all. So an Entra tenant cannot be configured as the microsoft provider from the Admin Panel, and a generic OIDC client typed into the form does not register either. Issue #26917, opened in July 2026 against v0.10.2 under the title "admin panel OAuth config is saved but never applied; SSO never activates without env vars", is still open. Two community fix PRs were closed unmerged, and there is no announced timeline. The fix is to put the MICROSOFT_* variables in the environment and restart.
Layer 2: OAuth runtime settings and the persistence flags
The second layer is documented. Two flags decide where settings come from:
| Setting family | ENABLE_OAUTH_PERSISTENT_CONFIG=false (default) | ENABLE_OAUTH_PERSISTENT_CONFIG=true |
|---|---|---|
| Microsoft client ID, secret, tenant, redirect URI | Environment, read once at startup | Environment, read once at startup (no change) |
| Signup, claim names, role mapping, group sync, blocked groups, allowed domains | Environment; the database is not consulted | Database; the stored value wins over the environment |
| Admin Panel OAuth section | Disabled fieldset, labelled as read from environment variables | Editable, but still no Microsoft client fields |
Open WebUI shows Entra ID groups as GUIDs instead of names
Microsoft Entra ID puts group object IDs in the groups claim by default. Open WebUI matches groups by exact, case-sensitive name. Put those two facts together and a GUID either matches nothing, so users join no groups, or, with JIT creation on, it creates a group named after the GUID.
The fix for cloud-only groups is in the app registration manifest: add cloud_displayname to the groups optional claim for the ID token, and set groupMembershipClaims to ApplicationGroup. Microsoft is explicit that cloud_displayname works only with ApplicationGroup; with SecurityGroup or All the claim reverts to IDs.
"groupMembershipClaims": "ApplicationGroup",
"optionalClaims": {
"idToken": [
{
"name": "groups",
"source": null,
"essential": false,
"additionalProperties": ["cloud_displayname"]
}
]
}The Open WebUI tutorial also adds access-token and SAML entries; idToken is the one Open WebUI reads. Then go to the Enterprise Application, open Users and groups, and assign every group that should reach Open WebUI. Only assigned groups appear in the token.
Microsoft's reason for that restriction is a control, not an inconvenience: display names are not unique, so without it any user could create a group with a duplicate name and gain access on the application side. Since Open WebUI matches on names, app assignment is what stops a look-alike group from granting access.
Hybrid tenants and groups synced from Active Directory
cloud_displayname does not resolve groups synced from on-premises Active Directory. For those, set the group identifier format under the ID token to sAMAccountName. Microsoft notes three conditions: For a mixed tenant, use the portal rather than the manifest: Enterprise app, Single sign-on, Attributes and Claims, then the group claim. Pick the on-premises source attribute and tick "Emit group name for cloud-only groups" to cover both kinds of group.
- sAMAccountName exists only on groups synced from AD. Groups created in Entra or Office 365 do not have it, and a group lacking the configured attribute is left out of the claim.
- Syncing the name attributes requires Microsoft Entra Connect 1.2.70 or later.
- When more than one AD domain syncs to the tenant, use a domain-qualified sAMAccountName to avoid name clashes.
Renames move users
Because matching is by name, renaming a group in Entra changes the claim value. On the next login the user is removed from the Open WebUI group under the old name and, if JIT creation is on, a new group is created under the new name, with none of the old group's model or knowledge permissions. Treat a rename in Entra as a change to Open WebUI and rename the Open WebUI group in the same change window.
Entra ID users missing groups or stuck in pending
When most users sync and a few do not, check four causes in order.
ApplicationGroup, unassigned groups never reach the token.SecurityGroup or All. Past it, Entra completely omits the groups claim and adds a pointer to Microsoft Graph instead.DEFAULT_USER_ROLE, which is pending unless you changed it.Open WebUI v0.11.4 has no overage handling. It does not follow the Graph pointer. Issue #17510, a feature request open since September 2025, describes users in roughly 200 or more directory groups landing in pending while users under about 170 to 180 groups mapped fine.
An absent or empty groups claim makes Open WebUI skip both removal and addition, so overage looks like "groups never update for this person", not "groups wiped". A new user simply gets none.
Three fixes, in order of preference:
roles claim is separate from groups, and Microsoft recommends app roles for in-app authorization in new applications that do not need nested groups. For why roles from the identity provider beat roles assigned by hand, see our guide to role-based access control for AI applications./Users and /Groups endpoints under /api/v1/scim/v2/, enabled with ENABLE_SCIM, SCIM_TOKEN and SCIM_AUTH_PROVIDER=microsoft. Provisioning pushes membership instead of carrying it in a token, so the 200-group limit does not apply. Pick one source of membership, though: login-time strict sync removes every group not in the claim, so running SCIM group provisioning and ENABLE_OAUTH_GROUP_MANAGEMENT together means the two will fight.ENABLE_OAUTH_GROUP_MANAGEMENT removes manually assigned groups
ENABLE_OAUTH_GROUP_MANAGEMENT defaults to false. When it is on, every browser SSO login runs the same sequence:
OAUTH_GROUPS_CLAIM, default groups; a string is split on OAUTH_GROUPS_SEPARATOR, default ;).ENABLE_OAUTH_GROUP_CREATION is on, create every claimed group that does not exist yet.OAUTH_BLOCKED_GROUPS.Steps 3 and 4 run only when the claim is non-empty. Both OAUTH_GROUPS_CLAIM and OAUTH_GROUP_CLAIM work at v0.11.4; the plural is read first and wins if both are set.
Admins are not exempt. The Entra group-name tutorial still says admin memberships are left alone, but that changed in 0.8.11 in March 2026, and v0.11.4 calls the sync with no role check.
The protection is OAUTH_BLOCKED_GROUPS. It accepts a JSON array or comma-separated text, matches exact names, shell wildcards (* and ?) and regex patterns (any pattern containing characters such as ^, $, [ or |). A group that matches is skipped by both add and remove, so its manual members survive every login. Before v0.11.4 the Admin Panel field saved comma-separated text as written and then read it back as nothing, so it looked filled in and protected nothing. Issue #12392 on this was closed on 22 September 2026, with a project member confirming the fix in v0.11.4.
That fix makes the field work; it does not change strict sync. Every manually assigned group that is not blocked is still emptied at login, and the same closing comment confirms that no allowlist or prefix-only mode exists. The practical pattern is a naming prefix for groups you manage inside Open WebUI and one blocked wildcard for that prefix.
The environment reference says blocked groups deny their members access. At v0.11.4 no code path refuses a sign-in because of a blocked group. To deny access, require assignment on the Enterprise Application in Entra, or use role mapping.
Open WebUI v0.11.4 upgrade: blocked groups created and 403 on login
The release note also says a sign-in whose roles cannot be read is refused; in the source that branch does not apply to browser sign-in. The upgrade risk for SSO is the third row: a deployment that ran with an empty admin list was never enforcing mapping, and after the upgrade any user whose Entra roles match neither list gets a 403. Before upgrading, compare the app role values assigned in Entra, not their display names, with OAUTH_ALLOWED_ROLES (default user,admin) and OAUTH_ADMIN_ROLES (default admin).
The environment block below puts the earlier sections into one file.
# Provider registration: environment only at v0.11.4 (the Admin Panel cannot set these) MICROSOFT_CLIENT_ID=<application-client-id> MICROSOFT_CLIENT_SECRET=<client-secret> MICROSOFT_CLIENT_TENANT_ID=<tenant-id> # MICROSOFT_OAUTH_SCOPE defaults to "openid email profile"; leave it unset # Set explicitly behind a TLS-terminating proxy; must match the Entra redirect URI exactly MICROSOFT_REDIRECT_URI=https://chat.internal.example.com/oauth/microsoft/callback # Keep OAuth settings in the environment (default, shown for reviewers) ENABLE_OAUTH_PERSISTENT_CONFIG=false # Let SSO create accounts; new accounts wait for approval unless a role maps ENABLE_OAUTH_SIGNUP=true # Not an oauth.* key: read from the environment on first boot only, then from the database DEFAULT_USER_ROLE=pending # Roles from Entra app roles (ID token 'roles' claim); values must equal the app role values ENABLE_OAUTH_ROLE_MANAGEMENT=true OAUTH_ROLES_CLAIM=roles OAUTH_ALLOWED_ROLES=user,admin OAUTH_ADMIN_ROLES=admin # Groups: strict sync from the ID token 'groups' claim ENABLE_OAUTH_GROUP_MANAGEMENT=true OAUTH_GROUPS_CLAIM=groups # Off until the blocked-groups creation fix (PR #31316) is in a release; pre-create groups instead ENABLE_OAUTH_GROUP_CREATION=false # Groups managed by hand inside Open WebUI: never added or removed by SSO OAUTH_BLOCKED_GROUPS=owui-local-*
owui-local-* is an example naming convention, not an Open WebUI default. v0.11.4 accepts the comma-separated form in the environment too, which avoids quoting a JSON array: docker run --env-file and a docker-compose environment: list keep quotes literally.
JIT creation ignores the blocklist in v0.11.4
With ENABLE_OAUTH_GROUP_CREATION on, the creation loop at v0.11.4 has no blocked-group check. Issue #29558 reports the result for users with large directory membership: thousands of empty auto-created groups. The fix, PR #31316, adds the check and was merged to the development branch on 25 September 2026, four days after v0.11.4 shipped. No release containing it existed on the date of this post. Until it ships, keep JIT creation off and pre-create each Open WebUI group with a name that equals the claim value character for character. Pre-creating also lets you attach model and knowledge permissions before the first member arrives.
Role mapping changed in v0.11.4
The v0.11.4 release note says roles sent by an identity provider "were in some setups not applied" and are now. Before, the role block ran only when OAUTH_ROLES_CLAIM, OAUTH_ALLOWED_ROLES and OAUTH_ADMIN_ROLES were all non-empty, so an empty admin list silently disabled role mapping. Now it runs whenever the claim name is set and ENABLE_OAUTH_ROLE_MANAGEMENT is true. On browser SSO the mapping works like this:
| Roles claim in the ID token | Existing user | New user |
|---|---|---|
Contains a value in OAUTH_ADMIN_ROLES | admin | admin |
Contains a value in OAUTH_ALLOWED_ROLES only | user | user |
| Present, matches neither list | Sign-in refused (403) | Sign-in refused (403) |
| Absent or empty | Keeps current role | DEFAULT_USER_ROLE (pending by default) |
Debug Open WebUI SSO from the logs, and what an auditor will ask
Before you change any Open WebUI setting, look at what Open WebUI actually received.
The Open WebUI tutorial suggests decoding the ID token in a web decoder. In a regulated firm, pasting a live identity token into a website is often against policy. The logs give you the same answer without handling a raw token. Set GLOBAL_LOG_LEVEL=DEBUG, restart, have one test user sign in, and filter the log:
docker logs open-webui 2>&1 | grep -E 'Oauth Groups claim|User oauth groups|Removing user from group|Adding user to group|User roles from oauth'
The User oauth groups: line shows the exact group values Open WebUI will match against, GUIDs or names. User roles from oauth: shows the roles claim. The removal and addition lines show strict sync acting. Compare them with the user's assignments in Entra, then set the level back. DEBUG output contains user identifiers and group names, so it should not stay on.
The on-prem angle: entitlements must be reproducible from the identity provider
An access review in a bank, an insurer or a hospital asks a simple question: can you show, from the identity provider, who has access to what in this system? For a self-hosted assistant, "what" includes which models, tools and knowledge collections each group can reach. Strict sync is how Open WebUI answers yes. With ENABLE_OAUTH_GROUP_MANAGEMENT on, Entra is the source of truth for every synced group, and membership is recomputed at each login. Documented exceptions belong in an OAUTH_BLOCKED_GROUPS pattern that the review can see, not in manual edits that the next login silently overwrites. Without strict sync, Open WebUI memberships drift from Entra the first time someone leaves a team. The financial-services version of this requirement is covered in our overview of AI compliance in financial services. Two other on-prem specifics change the answer. Environment-only provider registration suits change control, but teams on an isolated network who expected to manage SSO from the browser have to ship it through the deployment pipeline. And where a firm still syncs from on-premises AD, sAMAccountName, domain qualification and the Entra Connect version are not edge cases. For an instance with no inbound internet access, Microsoft documents an on-premises provisioning agent for SCIM apps (Entra ID P1, outbound connectivity only); its documentation describes user provisioning. Group membership in the chat workspace is half of the entitlement picture. If the workspace answers from a knowledge base, document-level permissions in that index drift the same way; our post on stale ACLs in RAG indexes covers that half. For the wider business decisions around private AI workspaces, see the AI for business guide.
Open WebUI Entra ID troubleshooting table
Three of the nine rows trace to upstream work that had not shipped by v0.11.4, each with a workaround. The other six are configuration on one side or the other, which is why the logs come before the settings.
This week, pick one user from each group that gates something sensitive: a restricted model, a knowledge collection with regulated data, admin access. Turn on DEBUG for one sign-in each, copy the User oauth groups: and User roles from oauth: lines, and diff them against those users' assignments in Entra. Any difference is either one of the rows above or an access finding, and either way you want to know before the auditor does.
| Symptom | Cause | Fix | Upstream status at v0.11.4 |
|---|---|---|---|
| Microsoft button never appears; Admin Panel OAuth edits do nothing | Provider registration is read from the environment once at startup | Set MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET, MICROSOFT_CLIENT_TENANT_ID and restart | #26917 open |
| Admin Panel OAuth section greyed out | ENABLE_OAUTH_PERSISTENT_CONFIG is false (default) | Edit the environment; flip the flag only for DB-managed runtime settings, after clearing stale oauth.* rows | Documented behaviour |
| Groups appear as GUIDs | Entra emits object IDs by default | cloud_displayname on the ID token groups claim, groupMembershipClaims set to ApplicationGroup | Entra configuration |
| AD-synced groups missing | cloud_displayname does not cover synced groups | sAMAccountName (Entra Connect 1.2.70+), plus "Emit group name for cloud-only groups" in mixed tenants | Entra configuration |
| Some users have no groups | Group not assigned to the Enterprise Application, or user only a nested member | Assign the group; make users direct members | Entra configuration |
| Heavy directory users never get groups or stay pending | Over 200 groups in a JWT, so Entra omits the claim | Scope with ApplicationGroup, use app roles, or provision through SCIM | #17510 open feature request |
| Manually assigned groups emptied at login | Strict sync removes groups absent from the claim, admins included | Prefix local groups and block the prefix in OAUTH_BLOCKED_GROUPS | Comma-separated field fixed in v0.11.4; no allowlist mode |
| Blocked groups created anyway | JIT creation has no blocked check | ENABLE_OAUTH_GROUP_CREATION=false, pre-create groups with exact names | PR #31316 merged to dev, not in a release |
| 403 after upgrading | Role mapping now runs; roles present but unmatched | Align Entra app role values with OAUTH_ALLOWED_ROLES and OAUTH_ADMIN_ROLES | v0.11.4 behaviour |
FAQ
Quick answers to the questions this post tends to raise.



