From c3649b13c02543b656c9369f1e63ebd8bf1d41f6 Mon Sep 17 00:00:00 2001 From: DrMelone <27028174+Classic298@users.noreply.github.com> Date: Fri, 13 Feb 2026 22:27:30 +0100 Subject: [PATCH] scim --- docs/features/auth/scim.mdx | 38 ++++++++++++++++++++-- docs/getting-started/env-configuration.mdx | 6 ++++ docs/tutorials/tips/sqlite-database.md | 28 ++++++++++++++++ 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/docs/features/auth/scim.mdx b/docs/features/auth/scim.mdx index db6a4cb5..0f04dae7 100644 --- a/docs/features/auth/scim.mdx +++ b/docs/features/auth/scim.mdx @@ -25,6 +25,7 @@ Configure SCIM by setting these environment variables: - **`SCIM_ENABLED`**: Set to `true` to enable SCIM support (default: `false`) - **`SCIM_TOKEN`**: The bearer token for SCIM authentication (required when SCIM is enabled) +- **`SCIM_AUTH_PROVIDER`**: The OAuth provider name to associate with SCIM `externalId` values (e.g., `microsoft`, `oidc`). Required for `externalId` storage and account linking. :::warning @@ -46,6 +47,9 @@ export SCIM_ENABLED=true # Set a secure token (replace with your own generated token) export SCIM_TOKEN="your-secure-token-here" + +# Set the OAuth provider name for externalId linking +export SCIM_AUTH_PROVIDER="microsoft" ``` ## SCIM API Configuration @@ -88,9 +92,9 @@ Open WebUI's SCIM implementation supports the following operations: - `userName`: The user's email address (required, unique) - `name.givenName`: First name - `name.familyName`: Last name -- `emails`: Email addresses +- `emails`: Email addresses (when multiple are provided, the entry marked `primary: true` is used) - `active`: User status (active/inactive) -- `externalId`: External identifier from the identity provider +- `externalId`: External identifier from the identity provider (stored per-provider in the user's `scim` JSON field, see [externalId and Account Linking](#externalid-and-account-linking)) #### Group Attributes - `displayName`: Group name (required) @@ -103,6 +107,7 @@ The SCIM API supports filtering for both users and groups: ``` GET /api/v1/scim/v2/Users?filter=userName eq "user@example.com" +GET /api/v1/scim/v2/Users?filter=externalId eq "abc-123" GET /api/v1/scim/v2/Groups?filter=displayName eq "Engineering" ``` @@ -118,6 +123,29 @@ Supported filter operators: - `lt`: Less than - `le`: Less than or equal +## externalId and Account Linking + +When `SCIM_AUTH_PROVIDER` is configured, Open WebUI stores `externalId` values in a per-provider structure within the user's `scim` JSON field: + +```json +{ + "microsoft": { "external_id": "abc-123" }, + "okta": { "external_id": "def-456" } +} +``` + +This enables several behaviors: + +- **User lookup by externalId**: When an identity provider sends a `filter=externalId eq "..."` request, Open WebUI searches the `scim` field for a matching entry under the configured provider. +- **OAuth fallback**: If no user is found by `externalId`, Open WebUI falls back to matching against OAuth `sub` values, automatically linking SCIM-provisioned accounts with existing OAuth-authenticated users. +- **Create and update**: When creating or updating users via SCIM, the `externalId` is stored in the `scim` field and returned in subsequent responses. + +:::warning + +If `SCIM_AUTH_PROVIDER` is not set while SCIM is enabled, any operation that requires `externalId` (creation, lookup, or update) will return a `500` error. A warning is also logged on startup to alert you. + +::: + ## Troubleshooting ### Common Issues @@ -133,7 +161,10 @@ Supported filter operators: 3. **User Creation Failures** - Ensure the `userName` field contains a valid email address - - Check that the email is not already in use + - Check that the email or `externalId` is not already in use + +4. **500 Error on externalId Operations** + - Verify that `SCIM_AUTH_PROVIDER` is set to the correct OAuth provider name ### Testing SCIM Endpoints @@ -156,6 +187,7 @@ curl -X POST \ -d '{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], "userName": "test@example.com", + "externalId": "idp-user-id-123", "displayName": "Test User", "name": { "givenName": "Test", diff --git a/docs/getting-started/env-configuration.mdx b/docs/getting-started/env-configuration.mdx index d119419f..3b2d92ca 100644 --- a/docs/getting-started/env-configuration.mdx +++ b/docs/getting-started/env-configuration.mdx @@ -5090,6 +5090,12 @@ This is useful when you need a JWT access token for downstream validation or whe - Description: Sets the bearer token for SCIM authentication. This token must be provided by identity providers when making SCIM API requests. Generate a secure random token (e.g., using `openssl rand -base64 32`) and configure it in both Open WebUI and your identity provider. - Persistence: This environment variable is a `PersistentConfig` variable. +#### `SCIM_AUTH_PROVIDER` + +- Type: `str` +- Default: `""` +- Description: Specifies the OAuth provider name to associate with SCIM `externalId` values (e.g., `microsoft`, `oidc`). When set, SCIM operations store and look up `externalId` under this provider key in the user's `scim` JSON field, enabling account linking between SCIM-provisioned identities and OAuth logins. A warning is logged on startup if SCIM is enabled but this variable is not set. + ## User Permissions ### Chat Permissions diff --git a/docs/tutorials/tips/sqlite-database.md b/docs/tutorials/tips/sqlite-database.md index 5795a782..1925cf67 100644 --- a/docs/tutorials/tips/sqlite-database.md +++ b/docs/tutorials/tips/sqlite-database.md @@ -553,6 +553,33 @@ Things to know about the tag table: | settings | JSON | nullable | User preferences | | info | JSON | nullable | Additional user info | | oauth_sub | Text | UNIQUE | OAuth subject identifier | +| scim | JSON | nullable | SCIM provisioning data | + +Things to know about the user table: + +- Uses UUID for primary key +- One-to-One relationship with `auth` table (shared id) +- One-to-One relationship with `oauth_session` table (via `user_id` foreign key) + +The `scim` field's expected structure: + +```python +{ + "": { + "external_id": string, # externalId from the identity provider + }, + # Multiple providers can be stored simultaneously + # Example: + # "microsoft": { "external_id": "abc-123" }, + # "okta": { "external_id": "def-456" } +} +``` + +**Why this column was added:** + +- **SCIM account linking**: Stores per-provider `externalId` values from SCIM provisioning, enabling identity providers (like Azure AD, Okta) to match users by their external identifiers rather than relying solely on email. +- **Multi-provider support**: The per-provider key structure allows a single user to be provisioned from multiple identity providers simultaneously, each storing their own `externalId`. +- **OAuth fallback**: When looking up a user by `externalId`, the system falls back to matching against `oauth_sub` if no `scim` entry is found, enabling seamless linking of SCIM-provisioned and OAuth-authenticated accounts. ## Entity Relationship Diagram @@ -604,6 +631,7 @@ erDiagram json settings json info text oauth_sub + json scim } auth {