Files
pangolin/.tasks/artifacts/openwebui-research.md
Olaf b428721b07 Initial commit: cleaned project structure
- Consolidated documentation from Ralph Loop iterations
- Archived 20+ outdated/superseded files to .archive/
- Kept essential docs: OIDC integration, mobile setup, quick start
- Added operational scripts for health monitoring and backup
- Research artifacts preserved in .tasks/artifacts/

Current state:
- 3 VPS sites (fry, proton, photon) ONLINE in Pangolin
- brn-home site pending for local services (Jellyfin, etc.)
- Mobile access configuration pending

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:15:04 +00:00

459 lines
16 KiB
Markdown

# OpenWebUI OIDC Integration Research
**Research Task:** RESEARCH-005
**Date:** 2026-01-20
**Version:** OpenWebUI v0.7.1+
## Executive Summary
OpenWebUI supports OIDC/OAuth2 authentication with comprehensive role and group management capabilities. This document details all environment variables, multi-user configurations, and admin designation methods via OIDC claims.
**Key Limitations:**
- Only ONE OIDC provider supported at a time via `OPENID_PROVIDER_URL`
- Cannot configure Microsoft AND Google OIDC simultaneously (workaround exists)
- Some variables are `PersistentConfig` - values persist to DB after first launch
---
## Complete Environment Variables List
### Core OIDC/OAuth Configuration
| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `WEBUI_URL` | String | (required) | **REQUIRED.** Public WebUI address (e.g., `http://localhost:8080`). Must be set before OAuth/SSO. |
| `WEBUI_SECRET_KEY` | String | (auto-generated) | Session encryption key. **Required** in clustered/production environments. |
| `OPENID_PROVIDER_URL` | String | (none) | **REQUIRED for OIDC.** OpenID Connect discovery URL (e.g., `https://accounts.google.com/.well-known/openid-configuration`). |
| `OAUTH_CLIENT_ID` | String | (none) | **REQUIRED.** OAuth client ID from IdP. |
| `OAUTH_CLIENT_SECRET` | String | (none) | **REQUIRED.** OAuth client secret from IdP. |
### OAuth Behavior Controls
| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `ENABLE_OAUTH_SIGNUP` | Boolean | `false` | Allow new account creation via OAuth login (separate from `ENABLE_SIGNUP`). |
| `ENABLE_OAUTH_PERSISTENT_CONFIG` | Boolean | `true` | Persist OAuth config to database. Set to `false` for stateless/containerized environments. |
| `OAUTH_MERGE_ACCOUNTS_BY_EMAIL` | Boolean | `false` | Merge OAuth logins by matching email. **CAUTION:** Insecure if provider doesn't verify emails. |
| `OAUTH_UPDATE_PICTURE_ON_LOGIN` | Boolean | `false` | Update user profile pictures from OAuth provider on each login. |
| `ENABLE_OAUTH_ID_TOKEN_COOKIE` | Boolean | `true` | Store ID token in cookie (for backward compatibility). |
### Token & Session Management
| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `OAUTH_SESSION_TOKEN_ENCRYPTION_KEY` | String | (auto-generated) | Encrypts OAuth session tokens server-side. |
| `OAUTH_CLIENT_INFO_ENCRYPTION_KEY` | String | (auto-generated) | Encrypts OAuth client information for MCP servers. |
| `WEBUI_AUTH_SIGNOUT_REDIRECT_URL` | String | (empty) | Redirect URL after signout (e.g., `https://idp.example.com/logout`). |
### Claim Mapping Variables
| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `OAUTH_USERNAME_CLAIM` | String | `preferred_username` | Claim field containing username. |
| `OAUTH_EMAIL_CLAIM` | String | `email` | Claim field containing user email. **NOTE:** May need customization for some IdPs (e.g., Microsoft Entra). |
| `OAUTH_PICTURE_CLAIM` | String | `picture` | Claim field containing profile picture URL. Set to empty string to disable. |
**Important:** Microsoft Entra ID sometimes returns email in `preferred_username` instead of `email` claim. Custom configuration may be required.
---
## Role Management Configuration
### Role Synchronization
| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `ENABLE_OAUTH_ROLE_MANAGEMENT` | Boolean | `false` | **Enable role synchronization from OIDC claims.** |
| `OAUTH_ROLES_CLAIM` | String | `roles` | Claim field containing user roles. Supports nested paths (e.g., `resource_access.client.roles`). |
| `OAUTH_ALLOWED_ROLES` | String (CSV) | (none) | Comma-separated list of roles allowed to access OpenWebUI. Empty = all authenticated users allowed. |
| `OAUTH_ADMIN_ROLES` | String (CSV) | (none) | **Comma-separated list of roles that grant admin privileges.** Users with these roles become OpenWebUI admins. |
### Role Management Behavior
**When `ENABLE_OAUTH_ROLE_MANAGEMENT=true`:**
- User roles are synchronized from OIDC claims on **every login**
- `OAUTH_ROLES_CLAIM` can use dot notation for nested claims (e.g., `realm_access.roles`)
- If user has role in `OAUTH_ADMIN_ROLES`, they receive admin privileges
- If user doesn't have role in `OAUTH_ALLOWED_ROLES`, login is denied
**Example Configuration:**
```bash
ENABLE_OAUTH_ROLE_MANAGEMENT=true
OAUTH_ROLES_CLAIM=roles
OAUTH_ALLOWED_ROLES=openwebui-user,openwebui-admin
OAUTH_ADMIN_ROLES=openwebui-admin
```
---
## Group Management Configuration
### Group Synchronization
| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `ENABLE_OAUTH_GROUP_MANAGEMENT` | Boolean | `false` | **Enable group membership synchronization from OIDC claims.** |
| `OAUTH_GROUP_CLAIM` | String | `groups` | Claim field containing group memberships. |
| `ENABLE_OAUTH_GROUP_CREATION` | Boolean | `false` | **Enable Just-in-Time (JIT) group creation.** Groups from claims are auto-created if they don't exist. |
### Group Management Behavior
**CRITICAL:** When `ENABLE_OAUTH_GROUP_MANAGEMENT=true`:
- User's group memberships in OpenWebUI are **STRICTLY SYNCHRONIZED** with OAuth claims on **every login**
- Manually assigned groups will be removed if not present in OAuth claims
- Groups are identified by name matching between claim values and OpenWebUI group names
**Just-in-Time Group Creation:**
When `ENABLE_OAUTH_GROUP_CREATION=true`:
- Groups from OIDC claims are automatically created in OpenWebUI if they don't exist
- Useful for dynamic group provisioning without manual setup
- Groups are created with default permissions
**Example Configuration:**
```bash
ENABLE_OAUTH_GROUP_MANAGEMENT=true
OAUTH_GROUP_CLAIM=groups
ENABLE_OAUTH_GROUP_CREATION=true
```
---
## Provider-Specific Variables
### Google OAuth
| Variable | Description |
|----------|-------------|
| `GOOGLE_CLIENT_ID` | Google OAuth client ID |
| `GOOGLE_CLIENT_SECRET` | Google OAuth client secret |
| `OPENID_PROVIDER_URL` | Set to `https://accounts.google.com/.well-known/openid-configuration` |
**Redirect URI:** `https://your-domain/oauth/google/callback`
### Microsoft OAuth (Entra ID)
| Variable | Description |
|----------|-------------|
| `MICROSOFT_CLIENT_ID` | Microsoft OAuth client ID |
| `MICROSOFT_CLIENT_SECRET` | Microsoft OAuth client secret |
| `MICROSOFT_CLIENT_TENANT_ID` | Microsoft tenant ID |
| `OPENID_PROVIDER_URL` | Set to Microsoft OIDC discovery URL |
**Redirect URI:** `https://your-domain/oauth/microsoft/callback`
**Known Issues:**
- Email may be in `preferred_username` claim instead of `email`
- May require `OAUTH_EMAIL_CLAIM=preferred_username` for some users
### Generic OIDC Provider
| Variable | Description |
|----------|-------------|
| `OAUTH_CLIENT_ID` | Generic OAuth client ID |
| `OAUTH_CLIENT_SECRET` | Generic OAuth client secret |
| `OPENID_PROVIDER_URL` | **REQUIRED.** OIDC discovery URL |
| `OAUTH_SCOPES` | OAuth scopes to request (default: `openid profile email`) |
**Redirect URI:** `https://your-domain/oauth/oidc/callback`
---
## Trusted Header Authentication (Alternative to OIDC)
For reverse proxy-based authentication (Tailscale, Cloudflare Tunnel, oauth2-proxy, Authentik, Authelia):
| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `WEBUI_AUTH_TRUSTED_EMAIL_HEADER` | String | (none) | HTTP header containing authenticated user's email |
| `WEBUI_AUTH_TRUSTED_NAME_HEADER` | String | (none) | HTTP header containing user's display name |
| `WEBUI_AUTH_TRUSTED_GROUPS_HEADER` | String | (none) | HTTP header containing comma-separated group list |
**SECURITY WARNING:**
- Misconfiguration allows **unauthorized authentication bypass**
- **ONLY use if reverse proxy strictly blocks direct access to OpenWebUI**
- Ensure headers cannot be spoofed by end users
---
## Multi-User Role Mapping Configuration
### Method 1: OIDC Role Claims (Recommended)
**Step 1: Configure IdP to include roles in token**
- Add custom claims to OIDC token
- Include roles in `roles` claim (or custom claim path)
**Step 2: Configure OpenWebUI**
```bash
ENABLE_OAUTH_ROLE_MANAGEMENT=true
OAUTH_ROLES_CLAIM=roles # or custom path like "realm_access.roles"
OAUTH_ALLOWED_ROLES=user,admin,power-user # Users must have one of these roles
OAUTH_ADMIN_ROLES=admin # Users with this role become admins
```
**Step 3: Map users in IdP**
- Assign roles to users in IdP (Authentik, Keycloak, Okta, etc.)
- Users sync roles on every login
### Method 2: OIDC Group Claims
**Step 1: Configure IdP to include groups in token**
- Add groups to OIDC token claims
- Ensure group names match desired OpenWebUI groups
**Step 2: Configure OpenWebUI**
```bash
ENABLE_OAUTH_GROUP_MANAGEMENT=true
OAUTH_GROUP_CLAIM=groups
ENABLE_OAUTH_GROUP_CREATION=true # Auto-create groups from claims
```
**Step 3: Manage permissions in OpenWebUI**
- Groups are synced automatically
- Admin assigns permissions to groups within OpenWebUI
### Method 3: Combined Role + Group Management
```bash
# Enable both
ENABLE_OAUTH_ROLE_MANAGEMENT=true
ENABLE_OAUTH_GROUP_MANAGEMENT=true
# Role configuration
OAUTH_ROLES_CLAIM=roles
OAUTH_ALLOWED_ROLES=openwebui-user
OAUTH_ADMIN_ROLES=openwebui-admin
# Group configuration
OAUTH_GROUP_CLAIM=groups
ENABLE_OAUTH_GROUP_CREATION=true
```
**Behavior:**
1. Roles control access (allowed) and admin privileges
2. Groups control resource/team organization within OpenWebUI
3. Both sync on every login
---
## Admin Designation via OIDC Claims
### Option 1: Role-Based Admin (Primary Method)
**Configuration:**
```bash
ENABLE_OAUTH_ROLE_MANAGEMENT=true
OAUTH_ROLES_CLAIM=roles
OAUTH_ADMIN_ROLES=openwebui-admin,superuser
```
**How it works:**
- Users with `openwebui-admin` OR `superuser` role become admins
- Admin status is synchronized on every login
- Removing role in IdP removes admin privileges on next login
### Option 2: Group-Based Admin (Indirect)
**Configuration:**
```bash
ENABLE_OAUTH_GROUP_MANAGEMENT=true
OAUTH_GROUP_CLAIM=groups
```
**How it works:**
- Groups are synced to OpenWebUI
- Admin must manually grant admin privileges to specific users/groups within OpenWebUI
- Less automated than role-based approach
### Option 3: First User Auto-Admin
**Default Behavior:**
- When OpenWebUI is first deployed, the first user to sign in becomes admin
- Subsequent users require admin assignment or role-based configuration
**Not recommended for production** - use role-based admin instead.
---
## Example Configurations
### Authentik OIDC with Role Management
```bash
# Core OIDC
WEBUI_URL=https://openwebui.example.com
OPENID_PROVIDER_URL=https://authentik.example.com/application/o/openwebui/.well-known/openid-configuration
OAUTH_CLIENT_ID=<client-id-from-authentik>
OAUTH_CLIENT_SECRET=<client-secret-from-authentik>
# OAuth behavior
ENABLE_OAUTH_SIGNUP=true
ENABLE_OAUTH_PERSISTENT_CONFIG=false # For containerized deployments
# Role management
ENABLE_OAUTH_ROLE_MANAGEMENT=true
OAUTH_ROLES_CLAIM=roles
OAUTH_ALLOWED_ROLES=openwebui-user,openwebui-admin
OAUTH_ADMIN_ROLES=openwebui-admin
# Group management (optional)
ENABLE_OAUTH_GROUP_MANAGEMENT=true
OAUTH_GROUP_CLAIM=groups
ENABLE_OAUTH_GROUP_CREATION=true
```
### Okta OIDC with Group JIT Provisioning
```bash
# Core OIDC
WEBUI_URL=https://openwebui.company.com
OPENID_PROVIDER_URL=https://dev-12345.okta.com/.well-known/openid-configuration
OAUTH_CLIENT_ID=<okta-client-id>
OAUTH_CLIENT_SECRET=<okta-client-secret>
# OAuth behavior
ENABLE_OAUTH_SIGNUP=true
# Role management
ENABLE_OAUTH_ROLE_MANAGEMENT=true
OAUTH_ROLES_CLAIM=groups # Okta uses groups claim for roles
OAUTH_ADMIN_ROLES=OpenWebUI-Admins
# Group management with JIT
ENABLE_OAUTH_GROUP_MANAGEMENT=true
OAUTH_GROUP_CLAIM=groups
ENABLE_OAUTH_GROUP_CREATION=true
```
### Microsoft Entra ID with Email Claim Fix
```bash
# Core OIDC
WEBUI_URL=https://openwebui.contoso.com
OPENID_PROVIDER_URL=https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration
MICROSOFT_CLIENT_ID=<application-id>
MICROSOFT_CLIENT_SECRET=<client-secret>
MICROSOFT_CLIENT_TENANT_ID=<tenant-id>
# Fix email claim issue (Entra specific)
OAUTH_EMAIL_CLAIM=preferred_username # Or upn
OAUTH_USERNAME_CLAIM=preferred_username
# OAuth behavior
ENABLE_OAUTH_SIGNUP=true
# Role management (if using app roles)
ENABLE_OAUTH_ROLE_MANAGEMENT=true
OAUTH_ROLES_CLAIM=roles
OAUTH_ADMIN_ROLES=OpenWebUI.Admin
```
---
## Important Notes & Gotchas
### PersistentConfig Behavior
**Variables marked as `PersistentConfig`:**
- Values are saved to database on **first launch**
- Subsequent container restarts **ignore environment variables**
- Changes must be made via OpenWebUI Admin UI or database
**Workaround:**
```bash
ENABLE_OAUTH_PERSISTENT_CONFIG=false # Disable persistence, use env vars only
```
### Common Misconfigurations
**Incorrect Variables (Do NOT use):**
```bash
# WRONG - these don't exist
OIDC_CONFIG=...
WEBUI_OIDC_CLIENT_ID=...
WEBUI_ENABLE_SSO=...
WEBUI_AUTH_TYPE=...
OPENID_CLIENT_ID=...
OPENID_CLIENT_SECRET=...
# CORRECT - use these instead
OPENID_PROVIDER_URL=...
OAUTH_CLIENT_ID=...
OAUTH_CLIENT_SECRET=...
ENABLE_OAUTH_SIGNUP=...
```
### Security Considerations
1. **Always use HTTPS** for production OIDC deployments
2. **Validate redirect URIs** match exactly in IdP configuration
3. **Don't enable `OAUTH_MERGE_ACCOUNTS_BY_EMAIL`** unless provider verifies emails
4. **Use `OAUTH_ALLOWED_ROLES`** to restrict access to authorized users
5. **Trusted Headers** require strict reverse proxy configuration
### Role vs Group Management
| Feature | Roles | Groups |
|---------|-------|--------|
| **Purpose** | Access control, admin privileges | Resource organization, team structure |
| **Sync Behavior** | Strict sync on login | Strict sync on login |
| **Admin Assignment** | Via `OAUTH_ADMIN_ROLES` | Manual in OpenWebUI UI |
| **Access Control** | Via `OAUTH_ALLOWED_ROLES` | Not built-in (manual management) |
| **JIT Creation** | N/A | Via `ENABLE_OAUTH_GROUP_CREATION` |
---
## Troubleshooting
### OIDC Provider Not Activating
**Check:**
1. `WEBUI_URL` is set in environment **and** Admin Panel
2. `OPENID_PROVIDER_URL` is valid and accessible from container
3. `OAUTH_CLIENT_ID` and `OAUTH_CLIENT_SECRET` are correct
4. Redirect URI in IdP matches `https://<WEBUI_URL>/oauth/oidc/callback`
### OAuth Callback Failed - Email Missing
**Solution:**
```bash
OAUTH_EMAIL_CLAIM=preferred_username # Or other claim containing email
```
### Users Not Getting Admin Privileges
**Check:**
1. `ENABLE_OAUTH_ROLE_MANAGEMENT=true`
2. User has role listed in `OAUTH_ADMIN_ROLES`
3. `OAUTH_ROLES_CLAIM` matches claim path in token (use JWT debugger)
4. Role claim is included in scopes requested
### Groups Not Syncing
**Check:**
1. `ENABLE_OAUTH_GROUP_MANAGEMENT=true`
2. `OAUTH_GROUP_CLAIM` matches claim name in token
3. Groups claim is included in requested scopes
4. `ENABLE_OAUTH_GROUP_CREATION=true` if groups don't exist yet
---
## References
- [OpenWebUI SSO Documentation](https://docs.openwebui.com/features/auth/sso/)
- [OpenWebUI Environment Variables](https://docs.openwebui.com/getting-started/env-configuration/)
- [Troubleshooting SSO Issues](https://docs.openwebui.com/troubleshooting/sso/)
- [Authentik Integration Guide](https://integrations.goauthentik.io/miscellaneous/open-webui/)
- [Authelia Integration Guide](https://www.authelia.com/integration/openid-connect/clients/open-webui/)
- [Okta OIDC Tutorial](https://docs.openwebui.com/tutorials/integrations/okta-oidc-sso/)
---
## Research Metadata
- **Task ID:** RESEARCH-005
- **Completed:** 2026-01-20
- **OpenWebUI Version:** v0.7.1+
- **Research Method:** Web documentation review via Exa MCP
- **Primary Sources:** Official OpenWebUI documentation, GitHub issues, integration guides