From 4ea7b3934d2bcacdb6dc7e09600823a3c0c51f16 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 7 Sep 2026 19:50:37 -0700 Subject: [PATCH 1/2] fix(identity): streamline SSO settings and harden SCIM provisioning --- .github/workflows/test-build.yml | 74 +- .../content/docs/platform/enterprise/scim.mdx | 86 +- .../content/docs/platform/enterprise/sso.mdx | 74 +- .../platform/enterprise/verified-domains.mdx | 23 +- .../static/enterprise/scim-provisioning.png | Bin 0 -> 99814 bytes .../public/static/enterprise/sso-domains.png | Bin 0 -> 53141 bytes .../public/static/enterprise/sso-form.png | Bin 214287 -> 70646 bytes .../api/workspaces/invitations/batch/route.ts | 3 +- .../api/workspaces/invitations/route.test.ts | 22 + apps/sim/components/settings/navigation.ts | 2 +- apps/sim/ee/scim/TESTING.md | 119 + apps/sim/ee/scim/components/options.ts | 2 +- .../ee/scim/components/scim-section.test.tsx | 143 + apps/sim/ee/scim/components/scim-section.tsx | 307 +- .../application/groups/manage-groups.test.ts | 125 + .../lib/application/groups/manage-groups.ts | 1 + .../application/users/provision-user.test.ts | 41 +- .../lib/application/users/provision-user.ts | 20 +- .../lib/application/users/update-user.test.ts | 20 + apps/sim/ee/scim/lib/entitlement.test.ts | 17 +- apps/sim/ee/scim/lib/entitlement.ts | 20 +- .../lib/identity/account-identity.test.ts | 47 + .../ee/scim/lib/identity/account-identity.ts | 4 +- .../lib/managed-membership.postgres.test.ts | 206 + .../ee/scim/lib/managed-membership.test.ts | 5 +- apps/sim/ee/scim/lib/managed-membership.ts | 24 +- .../sim/ee/scim/lib/projection/grants.test.ts | 20 +- apps/sim/ee/scim/lib/projection/grants.ts | 25 +- .../lib/projection/reconcile-user.test.ts | 182 +- .../ee/scim/lib/projection/reconcile-user.ts | 146 +- .../ee/scim/lib/protocol/canonical.test.ts | 8 + apps/sim/ee/scim/lib/protocol/canonical.ts | 4 +- apps/sim/ee/scim/lib/protocol/filter.test.ts | 16 +- apps/sim/ee/scim/lib/protocol/filter.ts | 22 +- apps/sim/ee/scim/lib/protocol/normalize.ts | 5 + .../ee/scim/lib/protocol/resources.test.ts | 94 +- apps/sim/ee/scim/lib/protocol/resources.ts | 76 +- .../ee/scim/lib/protocol/user-patch.test.ts | 138 +- apps/sim/ee/scim/lib/protocol/user-patch.ts | 130 +- apps/sim/ee/scim/lib/reconcile/job.test.ts | 58 + apps/sim/ee/scim/lib/reconcile/job.ts | 66 +- apps/sim/ee/scim/lib/repository/groups.ts | 20 +- apps/sim/ee/scim/lib/repository/users.ts | 25 +- .../sso/components/sso-provider-settings.tsx | 1131 + .../ee/sso/components/sso-settings.test.tsx | 79 +- apps/sim/ee/sso/components/sso-settings.tsx | 1292 +- .../components/verified-domains-section.tsx | 54 +- apps/sim/ee/sso/search-params.ts | 9 + apps/sim/lib/api/contracts/auth.ts | 2 + apps/sim/lib/api/contracts/scim.ts | 24 +- apps/sim/lib/auth/auth.ts | 93 +- apps/sim/lib/auth/database-context.ts | 15 + apps/sim/lib/auth/security-policy.test.ts | 31 + apps/sim/lib/auth/security-policy.ts | 33 +- apps/sim/lib/auth/session-hooks.test.ts | 111 + apps/sim/lib/auth/session-hooks.ts | 53 + apps/sim/lib/auth/session-policy.test.ts | 69 +- apps/sim/lib/auth/session-policy.ts | 21 +- apps/sim/lib/auth/sim-auth-adapter.test.ts | 20 + apps/sim/lib/auth/sim-auth-adapter.ts | 3 +- .../admit-sso-user.postgres.test.ts | 171 + .../sso/application/admit-sso-user.test.ts | 16 + .../auth/sso/application/admit-sso-user.ts | 2 +- apps/sim/lib/billing/core/access.ts | 46 +- apps/sim/lib/billing/core/subscription.ts | 24 +- apps/sim/lib/core/config/env-flags.ts | 9 +- apps/sim/lib/core/config/scim-rollout.test.ts | 23 + .../organizations/members/lifecycle.test.ts | 25 + .../lib/organizations/members/lifecycle.ts | 13 + apps/sim/package.json | 1 + apps/sim/scripts/test-scim-e2e.ts | 928 + .../0325_scim_manual_workspace_baseline.sql | 1 + .../db/migrations/meta/0325_snapshot.json | 23938 ++++++++++++++++ packages/db/migrations/meta/_journal.json | 7 + packages/db/schema.ts | 2 + packages/testing/src/mocks/schema.mock.ts | 1 + 76 files changed, 28976 insertions(+), 1691 deletions(-) create mode 100644 apps/docs/public/static/enterprise/scim-provisioning.png create mode 100644 apps/docs/public/static/enterprise/sso-domains.png create mode 100644 apps/sim/ee/scim/TESTING.md create mode 100644 apps/sim/ee/scim/components/scim-section.test.tsx create mode 100644 apps/sim/ee/scim/lib/application/groups/manage-groups.test.ts create mode 100644 apps/sim/ee/scim/lib/identity/account-identity.test.ts create mode 100644 apps/sim/ee/scim/lib/managed-membership.postgres.test.ts create mode 100644 apps/sim/ee/sso/components/sso-provider-settings.tsx create mode 100644 apps/sim/ee/sso/search-params.ts create mode 100644 apps/sim/lib/auth/database-context.ts create mode 100644 apps/sim/lib/auth/session-hooks.test.ts create mode 100644 apps/sim/lib/auth/session-hooks.ts create mode 100644 apps/sim/lib/auth/sso/application/admit-sso-user.postgres.test.ts create mode 100644 apps/sim/lib/core/config/scim-rollout.test.ts create mode 100644 apps/sim/scripts/test-scim-e2e.ts create mode 100644 packages/db/migrations/0325_scim_manual_workspace_baseline.sql create mode 100644 packages/db/migrations/meta/0325_snapshot.json diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 83017381cd2..ca01e27127f 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -9,7 +9,7 @@ permissions: jobs: oauth-postgres: - name: OAuth PostgreSQL (${{ matrix.provision }}) + name: OAuth and SCIM PostgreSQL (${{ matrix.provision }}) runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-8vcpu-ubuntu-2404' || 'ubuntu-latest' }} timeout-minutes: 15 strategy: @@ -22,17 +22,17 @@ jobs: env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres - POSTGRES_DB: sim_oauth + POSTGRES_DB: sim_auth_scim ports: - 5432:5432 options: >- - --health-cmd "pg_isready -U postgres -d sim_oauth" + --health-cmd "pg_isready -U postgres -d sim_auth_scim" --health-interval 5s --health-timeout 5s --health-retries 10 env: - DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/sim_oauth - OAUTH_TOKEN_FAMILY_TEST_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/sim_oauth + DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/sim_auth_scim + OAUTH_TOKEN_FAMILY_TEST_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/sim_auth_scim BETTER_AUTH_SECRET: oauth-postgres-ci-secret-at-least-32-characters OAUTH_PROVIDER_ENABLED: 'true' NEXT_PUBLIC_APP_URL: https://test.sim.ai @@ -73,7 +73,7 @@ jobs: working-directory: packages/db run: bun run db:migrate - - name: Verify provider issuance and token lifecycle in PostgreSQL + - name: Verify OAuth lifecycle and SCIM membership guards in PostgreSQL working-directory: apps/sim run: >- bunx vitest run @@ -81,6 +81,68 @@ jobs: lib/auth/oauth-provider-lifecycle.postgres.test.ts app/api/auth/oauth2/token/route.postgres.test.ts lib/auth/sim-auth-adapter.test.ts + ee/scim/lib/managed-membership.postgres.test.ts + lib/auth/sso/application/admit-sso-user.postgres.test.ts + + - name: Verify SCIM and administration over real HTTP + working-directory: apps/sim + env: + NEXT_PUBLIC_APP_URL: http://127.0.0.1:3017 + BETTER_AUTH_URL: http://127.0.0.1:3017 + NEXT_PUBLIC_FORCE_HOSTED: 'true' + BILLING_ENABLED: 'true' + NEXT_PUBLIC_BILLING_ENABLED: 'true' + ENTERPRISE_ENABLED: 'true' + NEXT_PUBLIC_ENTERPRISE_ENABLED: 'true' + SCIM_ENABLED: 'true' + NEXT_PUBLIC_SCIM_ENABLED: 'true' + SSO_ENABLED: 'true' + NEXT_PUBLIC_SSO_ENABLED: 'true' + ORGANIZATIONS_ENABLED: 'true' + NEXT_PUBLIC_ORGANIZATIONS_ENABLED: 'true' + INTERNAL_API_SECRET: scim-http-ci-local-secret-at-least-32-characters + DB_TX_TRIPWIRE: throw + DISABLE_TELEMETRY: 'true' + NEXT_TELEMETRY_DISABLED: '1' + NEXT_PUBLIC_CHAT_DISABLED: 'true' + run: | + server_log="$RUNNER_TEMP/scim-next.log" + node ../../node_modules/next/dist/bin/next dev --hostname 127.0.0.1 --port 3017 > "$server_log" 2>&1 & + server_pid=$! + finish() { + kill "$server_pid" 2>/dev/null || true + wait "$server_pid" 2>/dev/null || true + awk '/^ (GET|POST|PUT|PATCH|DELETE|HEAD) \/api\// { print }' "$server_log" > "$RUNNER_TEMP/scim-http-status.log" + } + trap finish EXIT + deadline=$((SECONDS + 120)) + until curl --fail --silent --max-time 3 http://127.0.0.1:3017/api/health > /dev/null; do + if ! kill -0 "$server_pid" 2>/dev/null; then + echo 'Local SCIM app exited during startup.' + exit 1 + fi + if [ "$SECONDS" -ge "$deadline" ]; then + echo 'Local SCIM app did not become ready within 120 seconds.' + exit 1 + fi + sleep 2 + done + SCIM_E2E_BASE_URL="$NEXT_PUBLIC_APP_URL" \ + SCIM_E2E_DATABASE_URL="$DATABASE_URL" \ + SCIM_E2E_AUTH_SECRET="$BETTER_AUTH_SECRET" \ + SCIM_E2E_REPORT_PATH="$RUNNER_TEMP/scim-e2e-report.json" \ + bun run test:scim:e2e + + - name: Upload SCIM failure report and HTTP status log + if: failure() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: scim-failure-${{ matrix.provision }} + path: | + ${{ runner.temp }}/scim-e2e-report.json + ${{ runner.temp }}/scim-http-status.log + if-no-files-found: ignore + retention-days: 7 test-build: name: Lint and Test diff --git a/apps/docs/content/docs/platform/enterprise/scim.mdx b/apps/docs/content/docs/platform/enterprise/scim.mdx index c64ee14d26c..b928662b833 100644 --- a/apps/docs/content/docs/platform/enterprise/scim.mdx +++ b/apps/docs/content/docs/platform/enterprise/scim.mdx @@ -6,28 +6,29 @@ description: Create, update, and deactivate Sim members automatically from your import { Callout } from 'fumadocs-ui/components/callout' import { Step, Steps } from 'fumadocs-ui/components/steps' import { Tab, Tabs } from 'fumadocs-ui/components/tabs' +import { Image } from '@/components/ui/image' import { FAQ } from '@/components/ui/faq' -Directory provisioning connects your identity provider to Sim over SCIM 2.0. Your provider creates members when someone joins, updates them when their details change, and deactivates them the moment they leave — without anyone touching Sim. +Directory provisioning connects your identity provider to Sim over SCIM 2.0. Your provider creates members when someone joins, updates them when their details change, and deactivates them when it sends a deactivation request — without anyone touching Sim. It pairs with [SSO](/platform/enterprise/sso). SSO proves who someone is when they sign in. Directory provisioning decides who exists and what they can reach, before and after that. - Included with Enterprise plans. Requires [SSO](/platform/enterprise/sso) to be enabled, because provisioning is configured from the SSO settings page, and at least one [verified domain](/platform/enterprise/verified-domains) for your organization. Self-hosted deployments get it with the other enterprise features through `ENTERPRISE_ENABLED=true`, or turn just this feature on or off with `SCIM_ENABLED` and `NEXT_PUBLIC_SCIM_ENABLED`, alongside the [SSO variables](/platform/enterprise/sso#self-hosted-setup). + Included with Enterprise plans. The settings are under **Single sign-on → Provisioning**. On self-hosted deployments, enable the SSO settings page to reach this tab. A saved SSO provider is not required for SCIM; [verify each email domain](/platform/enterprise/verified-domains) before provisioning users at that domain. Self-hosted deployments get it with the other enterprise features through `ENTERPRISE_ENABLED=true` and `NEXT_PUBLIC_ENTERPRISE_ENABLED=true`, or turn just this feature on or off with `SCIM_ENABLED` and `NEXT_PUBLIC_SCIM_ENABLED`, alongside the [SSO variables](/platform/enterprise/sso#self-hosted-setup). ## What it does | Your provider does this | Sim does this | | --- | --- | -| Assigns a person to the Sim app | Creates their account and adds them to your organization as a Member | +| Assigns a person to the Sim app | Creates or links their account; new organization members join as Members | | Updates their name or email | Updates the Sim account, and ends their sessions if the address changed | | Deactivates them | Blocks sign-in and stops their personal API keys. Everything they own, and every grant they hold, is left untouched; shared workspace keys keep working | -| Reactivates them | Restores access exactly as it was | -| Removes them from the app | Removes their organization membership, ends their sessions, deletes their personal API keys, and reassigns what they owned | +| Reactivates them | Lifts the suspension; current group memberships and mappings determine access | +| Sends a SCIM DELETE request | Removes their organization membership, ends their sessions, deletes their personal API keys, and reassigns what they owned | | Adds them to a group | Grants whatever that group maps to | -Deactivation is reversible and never destructive. Someone on leave keeps their workflows, their credentials, and their workspace history; they simply cannot sign in. +Deactivation preserves ownership, credentials, and workspace history. It also blocks scheduled runs and triggers acting as that person. Changes to group membership or mappings can still withdraw access while someone is suspended. ## Turn it on @@ -44,7 +45,7 @@ This is what stops another tenant's directory from claiming an address it does n ### Enable directory provisioning -In **Settings → SSO → Directory provisioning**, turn it on. Sim shows your SCIM base URL: +Open **Settings → Organization → Single sign-on → Provisioning** and turn on **Enable directory provisioning**. Sim shows your SCIM base URL: ``` https:///api/scim/v2 @@ -54,7 +55,7 @@ https:///api/scim/v2 ### Issue a token -Choose whether the token expires (never, 90 days, or a year) and select **Issue token**. It appears once — copy it straight into your provider. +In **Tokens**, choose whether the token expires (never, 90 days, or a year) and select **Issue token**. It appears once — copy it straight into your provider. Two tokens can be active at a time, so you can rotate without downtime: issue the new one, update your provider, confirm a sync succeeds, then revoke the old one. @@ -65,14 +66,16 @@ Two tokens can be active at a time, so you can rotate without downtime: issue th -In your Okta app, open **Provisioning → Integration** and select **Configure API Integration**. +If you use OIDC for sign-in, create a separate provisioning integration: Okta cannot add SCIM to a custom OIDC app. In the Okta Integration Network catalog, add **SCIM 2.0 Test App (Header Auth)** for a private integration. See [Okta's setup guide](https://developer.okta.com/docs/guides/scim-provisioning-integration-connect/main/). -- **SCIM connector base URL**: `https:///api/scim/v2` -- **Unique identifier field for users**: `userName` -- **Supported provisioning actions**: Push New Users, Push Profile Updates, Push Groups -- **Authentication Mode**: HTTP Header, with your Sim token +In that app, open **Provisioning → Integration → Configure API Integration**, enable API integration, and enter: -Select **Test API Credentials**, then save. Under **Provisioning → To App**, enable Create Users, Update User Attributes, and Deactivate Users. +- **SCIM 2.0 Base Url**: `https:///api/scim/v2` +- **API Token**: your Sim token + +Select **Test API Credentials**, then save. Under **Provisioning → To App**, enable Create Users, Update User Attributes, and Deactivate Users. Assign a test user first, then use **Push Groups** for groups you want to map in Sim. Keep assignment groups separate from groups you push, as required by Okta. + +For an existing custom SAML or SWA app instead, follow [Okta's custom-app SCIM guide](https://help.okta.com/en-us/Content/Topics/apps/apps_app_integration_wizard_scim.htm). Its SCIM connection fields differ: set the unique identifier to `userName`, choose HTTP Header authentication, and enable the relevant provisioning actions. Okta never deletes users over SCIM. Unassigning someone, or deactivating them in Okta, sends a deactivation — which Sim applies as a suspension. @@ -86,27 +89,30 @@ In your enterprise application, open **Provisioning** and set Provisioning Mode Select **Test Connection**, then save and start provisioning. -Entra runs an initial cycle over everyone in scope, then incremental cycles roughly every 40 minutes. Removing someone from the app sends a deactivation; a permanent delete in Entra sends a removal about 30 days later. +Entra runs an initial cycle over everyone in scope, then incremental cycles roughly every 40 minutes. Unassignment normally sends a deactivation. Soft-deleted directory users are retained for 30 days; hard deletion can then send a SCIM DELETE during a provisioning cycle. An administrator can hard-delete earlier, and users already unassigned may no longer be managed. See [Microsoft’s provisioning lifecycle](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/how-provisioning-works). -Add a **SCIM Provisioner with SAML** app. +Add **SCIM Provisioner with SAML (SCIM v2 Core)**. Use the SCIM 2.0 connector, since Sim does not support SCIM 1.1. - **SCIM Base URL**: `https:///api/scim/v2` - **SCIM Bearer Token**: your Sim token -Enable provisioning and choose what happens when a user is removed. Suspend maps to a Sim suspension; Delete removes their membership. +In **Parameters**, map `scimusername` to the user's email. Check that **SCIM JSON Template** uses `urn:ietf:params:scim:schemas:core:2.0:User` and sends that email as `userName` or in `emails`. Save, enable the API connection, then enable provisioning. See [OneLogin's custom connector guide](https://onelogin.service-now.com/kb?id=kb_article_view&sysparm_article=KB0013904). + +Choose what happens when a user is deleted in OneLogin. **Suspend** maps to a Sim suspension; **Delete** removes their membership. If administrative approval is enabled, approve the pending provisioning actions in OneLogin before expecting a sync. See [OneLogin's provisioning test guide](https://developers.onelogin.com/docs/scim/test-your-scim/). -Add a **Custom SCIM** identity management integration. +Open an application's **Provisioning** tab and configure a **Custom SCIM** integration. You can use an existing application, a custom SAML application, or a URL Bookmark for provisioning without SAML. - **Base URL**: `https:///api/scim/v2` -- **Token Key**: your Sim token +- **Token** (also called **Token Key**): your Sim token +- **Test User Email**: an unused address in a domain verified by your Sim organization -Enable group sync if you plan to map groups. +Select **Test Connection**, enable group management if you plan to map groups, then select **Activate**. Activation creates and deletes a test user and, with group management enabled, a test group. See [JumpCloud's custom SCIM guide](https://jumpcloud.com/support/provision-and-manage-users-and-groups-in-apps-using-custom-scim-identity-management-integration). @@ -115,7 +121,7 @@ Enable group sync if you plan to map groups. ### Map your groups -Groups mean nothing to Sim until you say what they stand for. In **Settings → SSO → Directory provisioning → Group mappings**, point each pushed group at one or more of: +Groups mean nothing to Sim until you say what they stand for. In **Single sign-on → Provisioning → Group mappings**, point each pushed group at one or more of: - a **permission group**, which governs models, integrations, and capabilities - a **workspace**, at Read, Write, or Admin @@ -123,7 +129,7 @@ Groups mean nothing to Sim until you say what they stand for. In **Settings → A group can carry several mappings. When two groups grant the same workspace at different levels, the stronger one wins. The organization's default permission group cannot be a target: it governs by having no members. -Turning on **Match permission groups by name** maps a pushed group to an existing permission group of the same name automatically, and remaps it when the group is renamed. Nothing is created. +Under **Provisioning rules**, select **Manage rules**. **Match permission groups by name** maps new or renamed directory groups to existing permission groups with the exact same name, including capitalization. After enabling it for groups already synced, select **Reconcile now** or wait for the next scheduled reconciliation. Sim creates no permission groups; renaming a directory group updates its automatic mapping and preserves mappings added manually. Mapping a permission group to a directory group switches that permission group to explicit membership permanently: it governs exactly the people in it, and an empty group governs nobody. A permission group that governed everyone in its workspaces stops doing so the moment it is mapped, so map groups you created for the directory rather than your organization-wide ones. @@ -131,25 +137,39 @@ Mapping a permission group to a directory group switches that permission group t +Provisioning tab with an active SCIM connection, tokens, provisioning rules, group mappings, and recent activity + ## How access is withdrawn Sim records every grant it makes on your behalf. When someone leaves a group, what the directory granted is taken back. -**Managed membership locking**, on by default, makes the directory the source of truth for provisioned members: Sim refuses invitations, workspace grants, workspace role changes, and organization role changes for them, because the next sync would revert them anyway. Access a member already held by hand when a mapping started covering it counts as directory access from then on, so it is withdrawn with the mapping. Removals stay possible so an administrator can always act in an emergency. +**Lock managed membership**, on by default for a new connection, makes the directory the source of truth for provisioned members: Sim refuses invitations, workspace grants, workspace role changes, and organization role changes for them, because the next sync would revert them anyway. Access a member already held by hand when a mapping started covering it counts as directory access from then on, so it is withdrawn with the mapping. Removals stay possible so an administrator can always act in an emergency. -With locking off, manual access layers on top of directory access: access granted by hand stays when a group is left, and a workspace role raised by hand above what the directory set is left alone. +With locking off, access held before the directory mapping is preserved. If someone had manual Read access and the directory raises it to Admin, removing the mapping restores Read. A workspace role raised by hand above the directory's level is also left alone. The upgrade limitation below applies to grants recorded by older versions. ## Provisioning and SSO together A member the directory created can sign in with SSO immediately; the two resolve to the same account through your verified domain. -If you want the directory to be the only way in, enable **Disable just-in-time provisioning** in the connection settings. Sim then refuses to create membership for someone signing in who was never provisioned. +To stop SSO from creating organization memberships, open **Provisioning rules → Manage rules** and enable **Disable just-in-time provisioning**. While the SCIM connection is active and entitled, this overrides **Sign-in → First sign-in → Automatic**. Existing organization members can still sign in, including members added by invitation; the setting does not require every existing member to have been provisioned by SCIM. ## Watching a sync -**Settings → SSO → Directory provisioning → Activity** lists recent authenticated requests with their status and, for a failure, what was wrong. Providers report a failed cycle without saying what they sent, so this is usually the fastest way to see the cause. A request that fails to authenticate has no connection to log against, so a wrong or revoked token shows up only as your provider's own authentication error. +Changes to the enable switch, provisioning rules, tokens, and mappings save immediately. There is no page-level Save button on this tab. + +**Single sign-on → Provisioning → Activity** lists recent authenticated requests with their status and, for a failure, what was wrong. Providers report a failed cycle without saying what they sent, so this is usually the fastest way to see the cause. A request that fails to authenticate has no connection to log against, so a wrong or revoked token shows up only as your provider's own authentication error. + +The scheduled reconciliation task re-applies group mappings hourly when the background task runner is configured and running. You can run it on demand with **Reconcile now**, which is also how a change to the connection settings reaches members before the next sync. + +## Deployment and upgrades + +Apply the database migrations before deploying the new application code. The SCIM tables and suspension fields are additive, so the older application can continue running against the expanded schema during rollout. + +Keep `SCIM_ENABLED=false` and `NEXT_PUBLIC_SCIM_ENABLED=false` on the new deployment until all older application instances and workers have been drained. Older versions do not enforce SCIM suspensions or explicit permission-group membership. Enable provisioning only after every instance runs the new code. These explicit flags also override the hosted default. + +Once SCIM has suspended users or established managed access, rolling back to code that predates SCIM is not safe: it cannot enforce those restrictions. Disabling the SCIM connection stops synchronization but does not undo suspensions or restore old membership semantics. -Sim also re-applies every group mapping once an hour, so drift cannot persist. You can run it on demand with **Reconcile now**, which is also how a change to the connection settings reaches members before the next sync. +Migration `0325_scim_manual_workspace_baseline` adds tracking of prior manual workspace access. It cannot reconstruct levels overwritten by older SCIM code. Review those existing directory-owned grants before withdrawing mappings with membership locking off, and restore prior manual access explicitly where needed. ## Reference @@ -157,15 +177,15 @@ Sim also re-applies every group mapping once an hour, so drift cannot persist. Y - Authentication: `Authorization: Bearer ` - Resources: `/Users`, `/Groups`, plus `/ServiceProviderConfig`, `/ResourceTypes`, and `/Schemas` - Filters: `eq` only, up to ten terms joined with `and`. Users: `id`, `userName`, `externalId`, `emails.value` (also `emails[type eq "work"].value`), `active`. Groups: `id`, `displayName`, `externalId` -- Limits: 1,500 requests per minute per connection, 1 MB per request, 5,000 members per group -- `userName` is stored and returned lower-cased; top-level attributes and schema extensions Sim does not model (custom attributes included) are kept and returned as sent, and a PUT preserves ones it omits +- Limits: sustained 1,500 requests per minute per connection with a burst capacity of 3,000, 1 MB per request, 5,000 members per group +- `userName` is stored and returned lower-cased. Unmodeled top-level attributes and custom schema extensions are retained, and a PUT preserves ones it omits. Passwords are neither stored nor returned; Sim controls `id`, `meta`, and group membership - Group display names are unique within a connection, ignoring case - Page size: up to 100 per request diff --git a/apps/docs/content/docs/platform/enterprise/sso.mdx b/apps/docs/content/docs/platform/enterprise/sso.mdx index a89267d677d..282de16413e 100644 --- a/apps/docs/content/docs/platform/enterprise/sso.mdx +++ b/apps/docs/content/docs/platform/enterprise/sso.mdx @@ -28,7 +28,15 @@ Decide your **Provider ID** before configuring your identity provider. It become ### 1. Open SSO settings -Go to **Settings → Organization → Single sign-on** in your organization settings. +Go to **Settings → Organization → Single sign-on**. The page has three tabs: + +| Tab | Manage | +| --- | --- | +| **Sign-in** | OIDC or SAML configuration, callback URLs, and first-sign-in membership | +| **Domains** | DNS verification shared by SSO and SCIM | +| **Provisioning** | SCIM connection, tokens, rules, group mappings, and activity | + +Use **Domains** to verify ownership, then return to **Sign-in** to configure your provider. Switching tabs preserves an unsaved sign-in draft while you stay on this page; use **Save** or **Update** to commit it. The selected tab is included in the URL, so it can be bookmarked or shared. On self-hosted deployments, Provisioning appears when SCIM is enabled. ### 2. Choose a protocol @@ -39,24 +47,24 @@ Go to **Settings → Organization → Single sign-on** in your organization sett ### 3. Fill in the form -Single Sign-On configuration form showing Provider Type (OIDC), Provider ID, Issuer URL, Domain, Client ID, Client Secret, Scopes, and Callback URL fields +Sign-in tab showing the OIDC configuration form with advanced options collapsed **Fields required for both protocols:** | Field | What to enter | |-------|--------------| -| **Provider ID** | A short slug identifying this connection. Letters, numbers, and dashes only. It must be **unique across every Sim organization**, so include something specific to you — `azure-ad-acme`, not `azure-ad`. If the ID is taken, Sim tells you and suggests a free one. | +| **Provider ID** | A short slug identifying this connection. Letters, numbers, and dashes only. It must be **unique across every Sim organization**, so include something specific to you, such as `azure-ad-acme`. If the ID is taken, Sim asks you to choose another. | | **Issuer URL** | The identity provider's issuer URL. Must be HTTPS. | | **Domain** | Your organization's email domain, e.g. `company.com`. Users with this domain will be routed through SSO at sign-in. | -| **Member provisioning** | **Automatic** adds a user authenticated through this verified SSO connection to the organization as a Member and consumes a billed seat. Team seat counts grow with membership; fixed-seat plans require available capacity. **Invite only** authenticates the user without creating organization membership. Neither mode grants workspace access automatically. | +| **First sign-in → On first SSO sign-in** | **Automatic** adds a user authenticated through this verified SSO connection to the organization as a Member and consumes a billed seat. Team seat counts grow with membership; fixed-seat plans require available capacity. **Invite only** authenticates the user without creating organization membership. Neither mode grants workspace access automatically. | **OIDC additional fields:** | Field | What to enter | |-------|--------------| | **Client ID** | The application client ID from your IdP. | -| **Client Secret** | The client secret from your IdP. | -| **Scopes** | Comma-separated OIDC scopes. Default: `openid,profile,email`. | +| **Client secret** | The client secret from your IdP. | +| **Scopes** | Under **Advanced options**. Comma-separated OIDC scopes; default: `openid,profile,email`. | For OIDC, Sim automatically fetches endpoints (`authorization_endpoint`, `token_endpoint`, `userinfo_endpoint`, `jwks_uri`) from your issuer's `/.well-known/openid-configuration` discovery document. You only need to provide the issuer URL. @@ -66,12 +74,12 @@ Go to **Settings → Organization → Single sign-on** in your organization sett | Field | What to enter | |-------|--------------| -| **Entry Point URL** | The IdP's SSO service URL where Sim sends authentication requests. | -| **Identity Provider Certificate** | The Base-64 encoded X.509 certificate from your IdP for verifying assertions. | +| **Entry point URL** | The IdP's SSO service URL where Sim sends authentication requests. | +| **Identity provider certificate** | The Base-64 encoded X.509 certificate from your IdP for verifying assertions. | -### 4. Copy the Callback URL +### 4. Copy the callback URL -The **Callback URL** shown in the form is the endpoint your identity provider must redirect users back to after authentication. Copy it and register it in your IdP before saving. +Copy **Callback URL** for OIDC or **ACS URL (Reply URL)** for SAML. This is the endpoint that receives your identity provider's authentication response. Register it in your IdP before saving. **OIDC providers** (Okta, Microsoft Entra ID, Google Workspace, Auth0): ``` @@ -89,6 +97,14 @@ Click **Save**. To test, sign out and use the **Sign in with SSO** button on the --- +## Editing and advanced configuration + +For a saved connection, open **Sign-in** and select **Edit**. The Provider ID remains fixed. A saved OIDC client secret appears as a mask with a suffix when available; **Replace** lets you enter a new secret, and **Keep saved** cancels that replacement. Select **Update** to save the provider, or **Discard** to abandon changes. + +**Advanced options** contains OIDC scopes and optional authorization, token, and JWKS endpoint overrides. For SAML, it contains Audience, Callback URL override, signed-assertion requirements, NameID format, and optional IdP metadata XML. **Attribute mapping** lets either protocol override the email, name, and stable user-ID claim names. Leave a mapping blank to use the protocol default. + +SCIM settings save immediately in the **Provisioning** tab. Its **Disable just-in-time provisioning** rule overrides Automatic first-sign-in membership while the connection is active and entitled. Existing members can still sign in. See [directory provisioning](/platform/enterprise/scim#provisioning-and-sso-together). + ## Provider Guides @@ -107,7 +123,7 @@ Click **Save**. To test, sign out and use the **Sign in with SSO** button on the ``` 4. Under **Assignments**, grant access to the relevant users or groups 5. Copy the **Client ID** and **Client Secret** from the app's **General** tab -6. Your Okta domain is the hostname of your admin console, e.g. `dev-1234567.okta.com` +6. Copy your Okta organization domain from the account menu in the Admin Console, e.g. `dev-1234567.okta.com`. The Admin Console's `-admin` hostname is a different URL. See [Find your Okta domain](https://developer.okta.com/docs/guides/find-your-domain/main/). **In Sim:** @@ -115,12 +131,12 @@ Click **Save**. To test, sign out and use the **Sign in with SSO** button on the |-------|-------| | Provider Type | OIDC | | Provider ID | `okta` | -| Issuer URL | `https://dev-1234567.okta.com/oauth2/default` | +| Issuer URL | `https://dev-1234567.okta.com` | | Domain | `company.com` | | Client ID | From Okta app | | Client Secret | From Okta app | -The issuer URL uses Okta's default authorization server, which is pre-configured on every Okta org. If you created a custom authorization server, replace `default` with your server name. +For ordinary OIDC sign-in, use your Okta organization issuer as shown. A custom authorization server requires API Access Management; its issuer is `https:///oauth2/`. The `default` custom server is included in Okta's Integrator Free Plan but is not available in every production organization. See [Okta's authorization server guide](https://developer.okta.com/docs/concepts/auth-servers/). @@ -137,7 +153,7 @@ The issuer URL uses Okta's default authorization server, which is pre-configured ``` 3. After registration, go to **Certificates & secrets → New client secret** and copy the value immediately — it won't be shown again 4. Go to **Overview** and copy the **Application (client) ID** and **Directory (tenant) ID** -5. Go to **Token configuration → Add optional claim**, choose **ID**, and add **email**. Entra omits the email address for managed users without this claim, and sign-in then fails with a missing-user-info error +5. Keep `email` in Sim's OIDC scopes. On Entra's v2.0 endpoint, this scope requests the email claim; alternatively, add **email** under **Token configuration → Add optional claim → ID**. Confirm the account supplies an email in your verified domain: a user principal name is not necessarily that email, and the claim is not guaranteed for every account. See [Microsoft's ID token claims reference](https://learn.microsoft.com/en-us/entra/identity-platform/id-token-claims-reference) 6. If **Enterprise applications → Sim → Properties → Assignment required** is **Yes**, assign the users or groups who should sign in. Microsoft rejects unassigned users before they reach Sim **In Sim:** @@ -165,9 +181,9 @@ Use this when your tenant is configured for SAML rather than OIDC. Both are supp 2. Open **Single sign-on** and select **SAML** 3. Edit **Basic SAML Configuration** and set both values from Sim's SSO settings page: - **Identifier (Entity ID)** — the **SP Entity ID** field - - **Reply URL (Assertion Consumer Service URL)** — the **ACS URL** field + - **Reply URL (Assertion Consumer Service URL)** — the **ACS URL (Reply URL)** field 4. Under **Attributes & Claims**, confirm the default claims are present. Sim reads the standard schema claim URIs for email, name, and name identifier -5. Under **SAML Certificates**, download **Certificate (Base64)**. Its contents go in Sim's **Certificate** field, which is required. You can optionally also download **Federation Metadata XML** and paste it into Sim's **IDP Metadata XML** field under **Advanced Options** — it does not replace the certificate +5. Under **SAML Certificates**, download **Certificate (Base64)**. Its contents go in Sim's required **Identity provider certificate** field. You can optionally also download **Federation Metadata XML** and paste it into Sim's **IdP metadata XML** field under **Advanced options** — it does not replace the certificate 6. From the **Set up** panel for your application, copy the **Login URL** and the **Microsoft Entra Identifier** 7. Under **Users and groups**, assign the people who should be able to sign in — Microsoft rejects unassigned users before they reach Sim @@ -179,8 +195,8 @@ Use this when your tenant is configured for SAML rather than OIDC. Both are supp | Provider ID | `azure-ad-acme` (must be globally unique) | | Issuer URL | **Microsoft Entra Identifier**, e.g. `https://sts.windows.net/{tenant-id}/` | | Domain | `company.com` | -| Entry Point URL | **Login URL** from Entra | -| Certificate | Contents of the Base64 certificate | +| Entry point URL | **Login URL** from Entra | +| Identity provider certificate | Contents of the Base64 certificate | The **Identifier (Entity ID)** you set in Entra is what Sim validates the assertion's audience against. If it does not match the **SP Entity ID** shown in Sim exactly, sign-in fails with an audience mismatch. @@ -235,7 +251,7 @@ Use this when your tenant is configured for SAML rather than OIDC. Both are supp ``` https:///api/auth/sso/saml2/callback/adfs ``` -5. Export the **Token-signing certificate** from **Certificates**: right-click → **View Certificate → Details → Copy to File**, choose **Base-64 encoded X.509 (.CER)**. The `.cer` file is PEM-encoded — rename it to `.pem` before pasting its contents into Sim. +5. Export the **Token-signing certificate** from **Certificates**: right-click → **View Certificate → Details → Copy to File**, choose **Base-64 encoded X.509 (.CER)**. Paste the file's text into **Identity provider certificate**, including the certificate header and footer. 6. Note the **ADFS Federation Service endpoint URL** (e.g. `https://adfs.company.com/adfs/ls`) **In Sim:** @@ -246,8 +262,8 @@ Use this when your tenant is configured for SAML rather than OIDC. Both are supp | Provider ID | `adfs` | | Issuer URL | `https://adfs.company.com/adfs/services/trust` (the ADFS Federation Service identifier) | | Domain | `company.com` | -| Entry Point URL | `https://adfs.company.com/adfs/ls` | -| Certificate | Contents of the `.pem` file | +| Entry point URL | `https://adfs.company.com/adfs/ls` | +| Identity provider certificate | Contents of the exported Base64 certificate | The **Issuer URL** is the identity provider's own identifier, found in ADFS under **Service → Federation Service Properties → Federation Service identifier**. It is not Sim's URL — Sim's identifier is the **SP Entity ID** shown in the SSO settings, which you register in ADFS as the relying party identifier. @@ -269,13 +285,13 @@ Once SSO is configured, users with your domain (`company.com`) can sign in throu 2. They enter their work email (e.g. `alice@company.com`) 3. Sim redirects them to your identity provider 4. After authenticating, they are returned to Sim -5. If **Member provisioning** is **Automatic**, Sim adds them to the organization as a Member, growing a Team seat count or validating available fixed-seat capacity +5. If **First sign-in** is **Automatic**, Sim adds them to the organization as a Member, growing a Team seat count or validating available fixed-seat capacity 6. They land in an accessible workspace, or see a clear no-access state until an admin grants workspace access With **Automatic** provisioning, no invitation is required for organization membership. The join follows the organization's seat policy and does not infer a role from IdP claims: every newly provisioned user starts as a Member. Team subscriptions grow their billed seat count with membership; fixed-seat plans reject the join when capacity is full. With **Invite only**, SSO proves identity but does not create new membership or workspace access; new access must be granted separately, while existing organization membership and workspace access remain available. - Sign-in must start from Sim. Launching from your identity provider's app portal (Microsoft's **My Apps**, Okta's dashboard tile) sends an unsolicited assertion, which Sim rejects. This is deliberate — accepting them would let anyone replay an assertion into your tenant — but it means an IdP-initiated test fails even when the configuration is correct. + Start SAML sign-in from Sim's **Sign in with SSO** flow. Sim rejects unsolicited SAML assertions, so an IdP-initiated SAML test from an app portal can fail even when the configuration is correct. SSO provisioning creates internal organization members but does not grant workspace access. To grant workspace access from your identity provider, use [directory provisioning](/platform/enterprise/scim) and map a pushed group to a workspace. External workspace members are different: they are invited to a specific workspace without joining your organization or consuming one of your seats. Existing invitations and external access take precedence over automatic provisioning so their intended role and workspace grants are preserved. @@ -301,11 +317,11 @@ SSO provisioning creates internal organization members but does not grant worksp }, { question: "What happens when a user signs in with SSO for the first time?", - answer: "Sim creates or links their account. If Member provisioning is Automatic and a seat is available, Sim adds them to your organization as a Member; no manual organization invite is needed. Workspace access is always granted separately. If provisioning is Invite only, or the user already has a pending invitation or external workspace access, Sim preserves that flow instead of creating membership automatically." + answer: "Sim creates or links their account. If first-sign-in provisioning is Automatic and a seat is available, Sim adds them to your organization as a Member; no manual organization invite is needed. Workspace access is always granted separately. If provisioning is Invite only, or the user already has a pending invitation or external workspace access, Sim preserves that flow instead of creating membership automatically." }, { question: "Does disabling someone in the identity provider remove their Sim access?", - answer: "With [directory provisioning](/platform/enterprise/scim) connected, yes: your identity provider sends the deactivation, and Sim blocks sign-in and stops their API keys while leaving everything they own intact. With SSO alone, disabling the IdP account only blocks future SSO authentication — remove or suspend the user in Sim as part of offboarding." + answer: "When [directory provisioning](/platform/enterprise/scim) sends a deactivation, Sim blocks sign-in and personal API keys while preserving ownership. Shared workspace keys keep working. With SSO alone, disabling the IdP account only blocks future SSO authentication; remove the member in Sim as part of offboarding." }, { question: "Can I still use email/password login after enabling SSO?", @@ -313,7 +329,7 @@ SSO provisioning creates internal organization members but does not grant worksp }, { question: "A user already has an account with the same email — what happens when they sign in with SSO?", - answer: "Sim links the SSO identity to that account automatically. Linking is authorized by your verified domain: because you proved ownership of the domain before configuring SSO, Sim treats your identity provider as authoritative for email addresses on it. This works the same for OIDC and SAML, and does not depend on your IdP sending an email_verified claim — Microsoft Entra, for example, never sends one. Matching is by email address, so the address your IdP asserts must be identical to the one on the existing account. If it differs — a privileged or admin variant such as p-alice@company.com, or a different alias — Sim treats it as a new person and creates a separate account rather than linking." + answer: "Sim links the SSO identity to that account automatically. Linking is authorized by your verified domain: because you proved ownership of the domain before configuring SSO, Sim treats your identity provider as authoritative for email addresses on it. This works for OIDC and SAML without requiring an email_verified claim. Matching uses the address sent as email; Sim does not resolve different aliases or user principal names to an existing account. If the asserted address differs from the existing account, Sim treats it as a separate account." }, { question: "Who can configure SSO on Sim Cloud?", @@ -325,7 +341,7 @@ SSO provisioning creates internal organization members but does not grant worksp }, { question: "How do I update or replace an existing SSO configuration?", - answer: "Open Settings → Organization → Single sign-on and click Edit. Update the fields and save. The existing provider configuration is replaced." + answer: "Open Settings → Organization → Single sign-on → Sign-in and select Edit. Change the fields and select Update. The Provider ID cannot be changed; replacing it requires deleting the provider and creating a new one." } ]} /> @@ -342,7 +358,7 @@ Self-hosted deployments use environment variables instead of the billing/plan ch SSO_ENABLED=true NEXT_PUBLIC_SSO_ENABLED=true -# Optional: directory provisioning (SCIM), configured from the SSO settings page +# Optional: directory provisioning (SCIM), configured from Single sign-on → Provisioning SCIM_ENABLED=true NEXT_PUBLIC_SCIM_ENABLED=true @@ -376,7 +392,7 @@ SSO_ENABLED=true \ NEXT_PUBLIC_APP_URL=https://your-instance.com \ SSO_PROVIDER_TYPE=oidc \ SSO_PROVIDER_ID=okta \ -SSO_ISSUER=https://dev-1234567.okta.com/oauth2/default \ +SSO_ISSUER=https://dev-1234567.okta.com \ SSO_DOMAIN=company.com \ SSO_USER_EMAIL=admin@company.com \ SSO_OIDC_CLIENT_ID=your-client-id \ diff --git a/apps/docs/content/docs/platform/enterprise/verified-domains.mdx b/apps/docs/content/docs/platform/enterprise/verified-domains.mdx index 4a4dedcd684..cfdd8d6c277 100644 --- a/apps/docs/content/docs/platform/enterprise/verified-domains.mdx +++ b/apps/docs/content/docs/platform/enterprise/verified-domains.mdx @@ -1,22 +1,25 @@ --- title: Verified Domains -description: Prove ownership of your email domains before configuring single sign-on +description: Prove ownership of your email domains for single sign-on and directory provisioning --- import { Callout } from 'fumadocs-ui/components/callout' +import { Image } from '@/components/ui/image' import { FAQ } from '@/components/ui/faq' -Verified Domains let organization owners and admins on Enterprise plans prove they control an email domain (like `acme.com`) with a DNS TXT record. Verifying a domain is the security precondition for configuring single sign-on for it. +Verified Domains let organization owners and admins on Enterprise plans prove they control an email domain (like `acme.com`) with a DNS TXT record. Verify a domain before configuring single sign-on for it or provisioning members at that domain through SCIM. - Configuring SSO for a domain requires it to be verified first. Verifying proves your organization controls the domain — without it, anyone could point another company's domain at their own identity provider. Domains you had already configured for SSO are automatically treated as verified. + Configuring SSO for a domain requires it to be verified first. Verifying proves your organization controls the domain — without it, anyone could point another company's domain at their own identity provider. The domain-verification migration preserved domains configured for SSO before this requirement was introduced. --- ## Verify a domain -Go to **Settings → Organization → Single sign-on** in your organization settings. Domains are managed in the **Verified domains** section at the top of that page, directly above the identity provider configuration. +Go to **Settings → Organization → Single sign-on → Domains**. The **Verified domains** section is shared by sign-in and directory provisioning. + +Domains tab showing a verified domain and the DNS record for a pending domain 1. Enter the domain, for example `acme.com`, and click **Add domain**. 2. Sim shows a DNS **TXT record** to publish — a host (`_sim-challenge.acme.com`) and a unique value (`sim-domain-verification=…`). @@ -24,10 +27,10 @@ Go to **Settings → Organization → Single sign-on** in your organization sett 4. Click **Verify**. Sim looks up the record; on success the domain is marked **Verified**. - Some DNS providers — GoDaddy, Namecheap, Hover, and most cPanel panels — append your zone to whatever you type in the host field. If yours does, enter the host with the trailing zone removed, or you will end up with `_sim-challenge.acme.com.acme.com` and verification will never succeed. If you manage the `acme.com` zone, enter `_sim-challenge`. To verify the subdomain `eng.acme.com` from that same zone, enter `_sim-challenge.eng`. Cloudflare and Route 53 take the full host as shown. + Some DNS providers append the zone automatically. If yours does, enter `_sim-challenge` when managing the `acme.com` zone, or `_sim-challenge.eng` to verify `eng.acme.com` from that zone. Check the resulting record name: it must match the full host Sim shows, without a repeated domain such as `_sim-challenge.acme.com.acme.com`. -DNS changes can take up to 48 hours to propagate — if verification does not succeed immediately, wait and retry. Leave the TXT record published — removing it can cause the domain to fail a later re-verification. +DNS changes can take time to propagate. If verification does not succeed immediately, check the record name and value, then wait and retry. Keep the TXT record published. Sim verifies it when you select **Verify**; removing the DNS record does not itself revoke a completed verification. Add each domain you own separately. Subdomains (`eng.acme.com`) are verified independently of the apex. @@ -40,12 +43,12 @@ Add each domain you own separately. Subdomains (`eng.acme.com`) are verified ind { question: 'Where does the TXT record go?', answer: - 'On a dedicated host, _sim-challenge., rather than the root of your domain — this avoids colliding with your SPF, DMARC, or other root TXT records.', + 'On the dedicated host _sim-challenge.. Add the supplied TXT value there without replacing existing records on your domain.', }, { question: 'What happens to domains we already use for SSO?', answer: - 'They are automatically treated as verified, so existing single sign-on keeps working with no action needed.', + 'Domains configured before domain verification was introduced were preserved as verified by the migration. New domains must complete DNS verification.', }, { question: 'Can two organizations verify the same domain?', @@ -55,7 +58,7 @@ Add each domain you own separately. Subdomains (`eng.acme.com`) are verified ind { question: 'What if I remove a verified domain?', answer: - 'You lose the ownership proof, so you cannot configure SSO for that domain until you re-add and re-verify it. Removing it does not sign anyone out — an already-configured SSO provider keeps working.', + 'New SSO sign-ins for that domain stop immediately, including through an existing provider. SCIM cannot create users or change an email to that domain until it is verified again. Removing the domain does not itself end existing sessions. Re-add and verify it to restore the ownership proof.', }, ]} /> @@ -73,4 +76,4 @@ NEXT_PUBLIC_SSO_ENABLED=true `ENTERPRISE_ENABLED` turns both on together, but it needs its own browser twin — set `NEXT_PUBLIC_ENTERPRISE_ENABLED` alongside it, or the server and the settings page enable SSO while the login page still hides its SSO entry point. See the [self-hosted enterprise guide](/platform/enterprise/self-hosted). -Once enabled, verify domains from **Settings → Organization → Single sign-on**, in the **Verified domains** section above the identity provider configuration. The older `/workspace//settings/domains` path still resolves to the same page. +Once enabled, verify domains from **Settings → Organization → Single sign-on → Domains**. The older `/workspace//settings/domains` path still resolves to the same page. diff --git a/apps/docs/public/static/enterprise/scim-provisioning.png b/apps/docs/public/static/enterprise/scim-provisioning.png new file mode 100644 index 0000000000000000000000000000000000000000..8a7edec11a9f11cd87cfe951672495c706ad5950 GIT binary patch literal 99814 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⪻Qxt{H~i&zpTGTy@77JhW+S@wkW{;^ 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 YFL{MWGr#j<;5TSmYWk{G$~IyD2d%N|IsgCw literal 0 HcmV?d00001 diff --git a/apps/docs/public/static/enterprise/sso-form.png b/apps/docs/public/static/enterprise/sso-form.png index f44f5f80d14bc69f923de9e96ebba70a92e76c1d..8c25220647c0d23df7223c3f1fc772a2c3d09f21 100644 GIT binary patch literal 70646 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 C)w`Vl literal 214287 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 diff --git a/apps/sim/app/api/workspaces/invitations/batch/route.ts b/apps/sim/app/api/workspaces/invitations/batch/route.ts index 3a0303158ab..b10dcdee454 100644 --- a/apps/sim/app/api/workspaces/invitations/batch/route.ts +++ b/apps/sim/app/api/workspaces/invitations/batch/route.ts @@ -1,5 +1,4 @@ import { createLogger } from '@sim/logger' -import { getErrorMessage } from '@sim/utils/errors' import { normalizeEmail } from '@sim/utils/string' import { type NextRequest, NextResponse } from 'next/server' import { batchWorkspaceInvitationsContract } from '@/lib/api/contracts/invitations' @@ -117,7 +116,7 @@ export const POST = withRouteHandler(async (req: NextRequest) => { }) failed.push({ email: normalizedEmail, - error: getErrorMessage(error, 'Failed to create invitation'), + error: 'Failed to create invitation', }) } } diff --git a/apps/sim/app/api/workspaces/invitations/route.test.ts b/apps/sim/app/api/workspaces/invitations/route.test.ts index 8460eba4129..ccbef3c9db2 100644 --- a/apps/sim/app/api/workspaces/invitations/route.test.ts +++ b/apps/sim/app/api/workspaces/invitations/route.test.ts @@ -173,6 +173,28 @@ describe('POST /api/workspaces/invitations/batch', () => { resetDbChainMock() }) + it('keeps unexpected database details out of per-email failures', async () => { + mockCreatePendingInvitation.mockRejectedValueOnce( + new Error('Failed query: select "id" from "user"; params: private-data') + ) + + const response = await POST( + createMockRequest('POST', { + workspaceIds: ['workspace-1'], + emails: ['new@example.com'], + permission: 'read', + }) + ) + const data = await response.json() + + expect(response.status).toBe(200) + expect(data.success).toBe(false) + expect(data.failed).toEqual([ + { email: 'new@example.com', error: 'Failed to create invitation' }, + ]) + expect(mockSendInvitationEmail).not.toHaveBeenCalled() + }) + it('blocks invites for personal workspaces with an upgrade prompt', async () => { mockGetWorkspaceWithOwner.mockResolvedValueOnce({ id: 'workspace-1', diff --git a/apps/sim/components/settings/navigation.ts b/apps/sim/components/settings/navigation.ts index b1f09e3054c..eef5fa375ec 100644 --- a/apps/sim/components/settings/navigation.ts +++ b/apps/sim/components/settings/navigation.ts @@ -689,7 +689,7 @@ export const SETTINGS_SECTION_REGISTRY: readonly SettingsSectionRegistryEntry[] docsLink: 'https://docs.sim.ai/platform/enterprise/sso', unified: { id: 'sso', - description: 'Configure single sign-on for your organization.', + description: 'Manage sign-in, verified domains, and provisioning.', group: 'organization', order: 7, requiresHosted: true, diff --git a/apps/sim/ee/scim/TESTING.md b/apps/sim/ee/scim/TESTING.md new file mode 100644 index 00000000000..d27c54fa25d --- /dev/null +++ b/apps/sim/ee/scim/TESTING.md @@ -0,0 +1,119 @@ +# SCIM integration verification + +The local integration harness sends real HTTP requests to a running Next.js app +and inspects the resulting PostgreSQL records. It does not mock route handlers, +authentication, application operations, or persistence. Okta and Microsoft Entra +request shapes are emulated; this is not certification against either provider's +provisioning service. + +## Requirements + +- Bun and the repository dependencies installed. +- A running local app configured for Enterprise SCIM, using a dedicated local + PostgreSQL database with all migrations applied (including `0325`). Leave + Redis unconfigured so the app uses PostgreSQL for rate-limit storage. +- The app's local `BETTER_AUTH_SECRET`, at least 32 characters long. +- An app URL using HTTP on `localhost`, `127.0.0.1`, or `::1`. The database must + also use a loopback host, and its name must include `test` or `scim`. + +The harness creates two isolated synthetic organizations, owner accounts, active +Enterprise subscriptions, workspaces, verified `.test` domains, and signed owner +sessions. It obtains bearer tokens through the real administration API. Database +setup also supplies scenarios unavailable through the SCIM API, such as manual +suspension, pre-existing workspace access, and credential expiry. +The rate-limit scenario exhausts only its own connection's database bucket and +verifies that overlapping credentials share it while another tenant remains +unaffected. + +Use a disposable database. The harness deletes only its generated fixtures in a +`finally` block. If the process is forcibly terminated, discard the disposable +database or remove the organizations and users whose generated domain starts +with `scim-e2e-`. Existing organizations are not used by the suite. + +## Run + +From `apps/sim`, set these values for the local app and database, then run: + +```sh +export SCIM_E2E_BASE_URL=http://localhost:3000 +export SCIM_E2E_DATABASE_URL='postgresql://:@127.0.0.1:/' +export SCIM_E2E_AUTH_SECRET='' +export SCIM_E2E_REPORT_PATH=/tmp/sim-scim-e2e-report.json +bun run test:scim:e2e +``` + +The first three variables are required; the report path is optional. The app and +the harness must use the same database and authentication secret. The report +contains check names, outcomes, timing, and HTTP request count; it excludes +bearer credentials, session cookies, and secrets. A failed check exits nonzero +after cleanup. Request redirects are rejected and each request has a 60-second +timeout. + +## Coverage + +- Discovery, session-authenticated configuration, credential hashing, tenant + isolation, bearer authentication, content type, and malformed JSON errors. +- User and group creation, reads, replacement, PATCH, deletion, conflict errors, + stable pagination, count-only queries, and group/member attribute projection. +- Case-insensitive user lookup, external IDs, secondary/work/primary email + filters, account email drift, and filters reflecting manual suspension. +- Entra-shaped complex name and extension PATCH, case-insensitive core-qualified + password fields, atomic failure, and partial complex attribute selection. +- Group membership idempotency and membership-only replacement timestamps. +- Workspace, organization-role, and permission-group mappings, reconciliation, + drift repair, withdrawal, and preservation of pre-existing manual workspace access. +- Managed-membership enforcement through the actual batch invitation and + workspace permission APIs, including successful edits to unmanaged members. +- Session revocation on deactivation, membership retention, directory + reactivation, manual suspension protection, owner protection, and account + relinking after deletion and rehire. +- Credential scopes, overlapping rotation, the active credential limit, + connection rate limits and retry headers, revocation, connection + disable/re-enable, expiry, and activity records. + +## Continuous integration and PostgreSQL regressions + +The `OAuth and SCIM PostgreSQL` job in `.github/workflows/test-build.yml` runs +against both supported database provisioning paths, `db:push` and `db:migrate`. +After the OAuth and SCIM PostgreSQL tests, it starts a local Next.js app with +hosted Enterprise configuration and runs the HTTP suite above. Startup is +bounded to 120 seconds; the server is stopped when the step exits. A failure +uploads the credential-free scenario report and an allowlist of HTTP status log +lines. Raw application logs are not uploaded. + +The focused PostgreSQL suite uses the same database variable as the OAuth tests: + +```sh +OAUTH_TOKEN_FAMILY_TEST_DATABASE_URL="$SCIM_E2E_DATABASE_URL" \ + bunx vitest run ee/scim/lib/managed-membership.postgres.test.ts +``` + +Without that variable, the PostgreSQL tests are skipped. With it, they execute +real Drizzle queries against the provisioned schema, covering the invitation +lookup, aliases (including quoted identifiers), unmanaged and foreign-tenant +accounts, disabled and unlocked connections, and the permission guard inside a +transaction. Hosted billing flags are configured for the test; subscription +and entitlement reads use real PostgreSQL with the transaction tripwire enabled. +The suite checks an active Enterprise subscription, an ended one, and a real +billing query failure that must propagate instead of releasing directory locks. +The same CI job runs `lib/auth/sso/application/admit-sso-user.postgres.test.ts`, +which verifies that SCIM's `disableJit` setting blocks fresh SSO membership, +preserves existing membership, and permits JIT when disabled. These checks run +the admission operation and Enterprise entitlement reads through PostgreSQL. + +## Remaining provider verification + +Before claiming a provider integration has been validated, use an actual Okta +or Microsoft Entra tenant to run its connection test and provisioning job against +an externally reachable test deployment. Verify assignment, profile updates, +group pushes, unassignment, reactivation, and token rotation in the provider's +logs. The local suite does not exercise provider scheduling/retries, provider +portal configuration, real SSO redirects, production rate-limit infrastructure, +or billing-provider webhooks. + +Focused unit tests remain useful for malformed payload variants and policy +branches that do not belong in a local HTTP scenario: + +```sh +bunx vitest run ee/scim lib/api/server/routes/scim-route.test.ts +``` diff --git a/apps/sim/ee/scim/components/options.ts b/apps/sim/ee/scim/components/options.ts index 9005a3421a9..5b3afe46ebf 100644 --- a/apps/sim/ee/scim/components/options.ts +++ b/apps/sim/ee/scim/components/options.ts @@ -28,7 +28,7 @@ export const SETTING_TOGGLES = [ key: 'disableJit', label: 'Disable just-in-time provisioning', description: - 'Refuse membership for someone signing in with SSO who the directory never provisioned. The directory becomes the only way in.', + 'Prevent SSO from creating new organization memberships. Existing members can still sign in, including members added by invitation.', }, { key: 'autoMapPermissionGroupsByName', diff --git a/apps/sim/ee/scim/components/scim-section.test.tsx b/apps/sim/ee/scim/components/scim-section.test.tsx new file mode 100644 index 00000000000..0d7df7d6396 --- /dev/null +++ b/apps/sim/ee/scim/components/scim-section.test.tsx @@ -0,0 +1,143 @@ +/** + * @vitest-environment jsdom + */ +import { act } from 'react' +import { createRoot, type Root } from 'react-dom/client' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import type { ScimConnectionView } from '@/lib/api/contracts/organization-scim' + +const { connectionQuery, issueCredential, useConnection, useGroups, useActivity } = vi.hoisted( + () => ({ + connectionQuery: { + data: undefined as { connection: ScimConnectionView } | undefined, + isLoading: false, + isError: false, + error: null as Error | null, + isFetching: false, + refetch: vi.fn(), + }, + issueCredential: vi.fn(), + useConnection: vi.fn(), + useGroups: vi.fn(), + useActivity: vi.fn(), + }) +) + +vi.mock('@/lib/core/config/deployment-shape', () => ({ + useDeploymentShape: () => ({ features: { scim: true } }), +})) + +vi.mock('@/ee/access-control/hooks/permission-groups', () => ({ + usePermissionGroups: () => ({ data: [] }), + useOrganizationWorkspaces: () => ({ data: [] }), +})) + +vi.mock('@/ee/scim/hooks/scim', () => ({ + useScimConnection: useConnection, + useScimGroupMappings: useGroups, + useScimActivity: useActivity, + useIssueScimCredential: () => ({ mutateAsync: issueCredential, isPending: false }), + useConfigureScimConnection: () => ({ mutateAsync: vi.fn(), isPending: false }), + useRevokeScimCredential: () => ({ mutateAsync: vi.fn(), isPending: false }), + useReconcileScimConnection: () => ({ mutateAsync: vi.fn(), isPending: false }), + useUpsertScimGroupMapping: () => ({ mutateAsync: vi.fn(), isPending: false }), + useDeleteScimGroupMapping: () => ({ mutateAsync: vi.fn(), isPending: false }), +})) + +import { ScimSection } from '@/ee/scim/components/scim-section' + +let container: HTMLDivElement +let root: Root + +function renderSection(active = true) { + act(() => { + root.render() + }) +} + +function issueToken() { + const button = Array.from(container.querySelectorAll('button')).find( + (entry) => entry.textContent === 'Issue token' + ) + expect(button).toBeDefined() + button?.click() +} + +beforeEach(() => { + ;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true + container = document.createElement('div') + document.body.appendChild(container) + root = createRoot(container) + connectionQuery.data = { + connection: { + id: 'connection-1', + status: 'active', + baseUrl: 'https://sim.example.com/api/scim/v2', + settings: {}, + lastRequestAt: null, + reconciledAt: null, + createdAt: '2026-09-07T00:00:00.000Z', + credentials: [], + userCount: 0, + groupCount: 0, + }, + } + connectionQuery.isError = false + connectionQuery.error = null + useConnection.mockReturnValue(connectionQuery) + useGroups.mockReturnValue({ data: [], isLoading: false, isError: false }) + useActivity.mockReturnValue({ data: [], isLoading: false, isError: false }) + issueCredential.mockResolvedValue({ secret: 'one-time-token' }) +}) + +afterEach(() => { + act(() => root.unmount()) + container.remove() + vi.clearAllMocks() +}) + +describe('SCIM credential recovery', () => { + it('keeps the issued token available when a background connection refresh fails', async () => { + renderSection() + await act(async () => issueToken()) + expect(document.querySelector('input[value="one-time-token"]')).not.toBeNull() + + connectionQuery.isError = true + connectionQuery.error = new Error('Connection refresh failed') + renderSection() + + expect(document.querySelector('input[value="one-time-token"]')).not.toBeNull() + }) + + it('retains a token issued while inactive and pauses its queries until the tab returns', async () => { + const issued = Promise.withResolvers<{ secret: string }>() + issueCredential.mockReturnValue(issued.promise) + renderSection() + act(issueToken) + renderSection(false) + await act(async () => issued.resolve({ secret: 'one-time-token' })) + + expect(document.querySelector('input[value="one-time-token"]')).toBeNull() + expect(useConnection).toHaveBeenLastCalledWith('org-1', false) + expect(useGroups).toHaveBeenLastCalledWith('org-1', false) + expect(useActivity).toHaveBeenLastCalledWith('org-1', false) + + renderSection() + expect(document.querySelector('input[value="one-time-token"]')).not.toBeNull() + }) + + it('shows an actionable error when the first connection request fails', () => { + connectionQuery.data = undefined + connectionQuery.isError = true + connectionQuery.error = new Error('Connection unavailable') + renderSection() + + expect(container).toHaveTextContent('Connection unavailable') + const retry = Array.from(container.querySelectorAll('button')).find( + (button) => button.textContent === 'Try again' + ) + expect(retry).toBeDefined() + act(() => retry?.click()) + expect(connectionQuery.refetch).toHaveBeenCalledOnce() + }) +}) diff --git a/apps/sim/ee/scim/components/scim-section.tsx b/apps/sim/ee/scim/components/scim-section.tsx index 53a701cbd69..1e02e3994ce 100644 --- a/apps/sim/ee/scim/components/scim-section.tsx +++ b/apps/sim/ee/scim/components/scim-section.tsx @@ -12,6 +12,8 @@ import { ChipModalHeader, ChipSelect, ChipTag, + Expandable, + ExpandableContent, Switch, toast, } from '@sim/emcn' @@ -60,6 +62,8 @@ import { interface ScimSectionProps { organizationId: string + active: boolean + onOpenDomains: () => void } const RELATIVE_TIME = new Intl.RelativeTimeFormat('en', { numeric: 'auto' }) @@ -202,9 +206,10 @@ function AddMapping({ organizationId, groupId, permissionGroups, workspaces }: A interface GroupMappingsProps { organizationId: string + active: boolean } -function GroupMappings({ organizationId }: GroupMappingsProps) { +function GroupMappings({ organizationId, active }: GroupMappingsProps) { const { data: groups, isLoading, @@ -212,11 +217,11 @@ function GroupMappings({ organizationId }: GroupMappingsProps) { error, isFetching, refetch, - } = useScimGroupMappings(organizationId) - const { data: allPermissionGroups = [] } = usePermissionGroups(organizationId) + } = useScimGroupMappings(organizationId, active) + const { data: allPermissionGroups = [] } = usePermissionGroups(organizationId, active) /** The default group governs by having no members, so it cannot be a membership target. */ const permissionGroups = allPermissionGroups.filter((group) => !group.isDefault) - const { data: workspaces = [] } = useOrganizationWorkspaces(organizationId) + const { data: workspaces = [] } = useOrganizationWorkspaces(organizationId, active) const deleteMapping = useDeleteScimGroupMapping() const names = { @@ -236,7 +241,7 @@ function GroupMappings({ organizationId }: GroupMappingsProps) { if (isLoading) { return Loading groups... } - if (isError) { + if (groups === undefined && isError) { return ( Loading activity... } - if (isError) { + if (entries === undefined && isError) { return ( (null) const [credentialExpiry, setCredentialExpiry] = useState('never') - const [pendingRevoke, setPendingRevoke] = useState(null) + const [pendingRevokeId, setPendingRevokeId] = useState(null) + const pendingRevoke = + connection.credentials.find((credential) => credential.id === pendingRevokeId) ?? null async function handleToggleSetting(key: (typeof SETTING_TOGGLES)[number]['key'], value: boolean) { try { @@ -395,7 +405,7 @@ function ConnectionDetails({ organizationId, connection }: ConnectionDetailsProp if (!pendingRevoke) return try { await revokeCredential.mutateAsync({ organizationId, credentialId: pendingRevoke.id }) - setPendingRevoke(null) + setPendingRevokeId(null) toast.success('Token revoked') } catch (error) { toast.error(getErrorMessage(error, 'Failed to revoke token')) @@ -418,102 +428,134 @@ function ConnectionDetails({ organizationId, connection }: ConnectionDetailsProp return ( <> - - - - - -

    - {connection.userCount} provisioned member{connection.userCount === 1 ? '' : 's'},{' '} - {connection.groupCount} group{connection.groupCount === 1 ? '' : 's'}. Last request{' '} - {formatRelative(connection.lastRequestAt)}; last reconciled{' '} - {formatRelative(connection.reconciledAt)}. -

    -
    + +
    + + + + + +

    + {connection.userCount} provisioned member{connection.userCount === 1 ? '' : 's'},{' '} + {connection.groupCount} group{connection.groupCount === 1 ? '' : 's'}. Last request{' '} + {formatRelative(connection.lastRequestAt)}; last reconciled{' '} + {formatRelative(connection.reconciledAt)}. +

    +
    +
    +
    - {SETTING_TOGGLES.map((toggle) => ( + - void handleToggleSetting(toggle.key, checked)} - disabled={configure.isPending} - /> - - ))} - - -
    - {connection.credentials.length === 0 ? ( - No tokens yet. - ) : ( - connection.credentials.map((credential) => ( - + {connection.credentials.length === 0 ? ( + No tokens yet. + ) : ( + connection.credentials.map((credential) => ( + setPendingRevokeId(credential.id)} + /> + )) + )} +
    + setCredentialExpiry(next as CredentialExpiry)} + options={[...CREDENTIAL_EXPIRY_OPTIONS]} /> - )) - )} -
    - setCredentialExpiry(next as CredentialExpiry)} - options={[...CREDENTIAL_EXPIRY_OPTIONS]} - /> - = 2} - > - {issueCredential.isPending ? 'Issuing...' : 'Issue token'} - + = 2} + > + {issueCredential.isPending ? 'Issuing...' : 'Issue token'} + +
    -
    -
    + +
    - setShowRules(!showRules)} + > + {showRules ? 'Hide rules' : 'Manage rules'} + + } > - - +

    + Control managed membership, first sign-in, and automatic group matching. +

    + + +
    + {SETTING_TOGGLES.map((toggle) => ( + + void handleToggleSetting(toggle.key, checked)} + disabled={configure.isPending} + /> + + ))} +
    +
    +
    + - -
    - -
    - - {reconcile.isPending ? 'Reconciling...' : 'Reconcile now'} - + + + + + + + + +
    + +
    + + {reconcile.isPending ? 'Reconciling...' : 'Reconcile now'} + +
    -
    - + + !open && setIssuedSecret(null)} > setIssuedSecret(null)}> @@ -526,6 +568,7 @@ function ConnectionDetails({ organizationId, connection }: ConnectionDetailsProp hint='Copy it into your identity provider now. Sim stores only a digest and cannot show it again.' > !open && setPendingRevoke(null)} + open={active && pendingRevoke !== null} + onOpenChange={(open) => !open && setPendingRevokeId(null)} title='Revoke token' text={[ 'Revoke ', @@ -559,23 +602,21 @@ function ConnectionDetails({ organizationId, connection }: ConnectionDetailsProp } /** - * Directory provisioning (SCIM) settings, rendered as a section of the SSO page. - * SSO decides who someone is; provisioning decides who exists and what they can - * reach, so the two are configured together. + * Manages the SCIM connection in the Provisioning tab of organization sign-in settings. */ -export function ScimSection({ organizationId }: ScimSectionProps) { - const { hosted, features } = useDeploymentShape() - /** Hosted ships provisioning with the enterprise plan, which the SSO page already gates; self-hosted follows the flag. */ - const available = hosted || features.scim +export function ScimSection({ organizationId, onOpenDomains, active }: ScimSectionProps) { + const { features } = useDeploymentShape() + /** The deployment flag also allows activation to wait until older app instances are drained. */ + const available = features.scim const { data, isLoading, isError, error, isFetching, refetch } = useScimConnection( organizationId, - available + available && active ) const configure = useConfigureScimConnection() if (!available) return null - if (isError) { + if (data === undefined && isError) { return ( -
    - - void handleToggleEnabled(checked)} - disabled={isLoading || configure.isPending} - /> - +
    + +
    + + void handleToggleEnabled(checked)} + disabled={isLoading || configure.isPending} + /> + - {connection && enabled && ( - - )} -
    -
    + {!enabled && ( +
    +

    + Verify an email domain, then enable provisioning to connect your directory. +

    + Manage domains +
    + )} +
    + + {connection && enabled && ( + + )} +
    ) } diff --git a/apps/sim/ee/scim/lib/application/groups/manage-groups.test.ts b/apps/sim/ee/scim/lib/application/groups/manage-groups.test.ts new file mode 100644 index 00000000000..c89a95c8663 --- /dev/null +++ b/apps/sim/ee/scim/lib/application/groups/manage-groups.test.ts @@ -0,0 +1,125 @@ +/** + * @vitest-environment node + */ +import type { Principal } from '@sim/auth/principal' +import { scimConnection } from '@sim/db/schema' +import { queueTableRows, resetDbChainMock } from '@sim/testing' +import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest' + +const mocks = vi.hoisted(() => ({ + locks: vi.fn(), + findGroup: vi.fn(), + filterUsers: vi.fn(), + memberIds: vi.fn(), + members: vi.fn(), + addMember: vi.fn(), + removeMember: vi.fn(), + countMembers: vi.fn(), + touch: vi.fn(), + update: vi.fn(), + reconcile: vi.fn(), +})) + +vi.mock('@/lib/billing/organizations/membership', () => ({ + acquireOrganizationMutationLock: mocks.locks, +})) +vi.mock('@/ee/scim/lib/projection/reconcile-user', () => ({ + reconcileUsersProjection: mocks.reconcile, +})) +vi.mock('@/ee/scim/lib/projection/auto-map', () => ({ + autoMapPermissionGroupByName: vi.fn(), + settleMappedPermissionGroupsExplicit: vi.fn(), +})) +vi.mock('@/ee/scim/lib/repository/groups', () => ({ + findScimGroupById: mocks.findGroup, + filterOwnedUsers: mocks.filterUsers, + loadGroupMemberIds: mocks.memberIds, + loadGroupMembers: mocks.members, + addGroupMember: mocks.addMember, + removeGroupMember: mocks.removeMember, + countGroupMembers: mocks.countMembers, + touchScimGroup: mocks.touch, + updateScimGroup: mocks.update, + deleteScimGroupRow: vi.fn(), + insertScimGroup: vi.fn(), + loadGroupMembersForGroups: vi.fn(), + pageScimGroups: vi.fn(), +})) +vi.mock('@/ee/scim/lib/application/audit', () => ({ recordScimAuditEntries: vi.fn() })) +vi.mock('@/ee/scim/lib/base-url', () => ({ scimBaseUrl: () => 'https://sim.test/api/scim/v2' })) + +import { replaceScimGroup } from '@/ee/scim/lib/application/groups/manage-groups' +import { toGroupResource } from '@/ee/scim/lib/protocol/resources' + +const principal: Principal = { + kind: 'scim_connection', + connectionId: 'conn-1', + organizationId: 'org-1', + credentialId: 'cred-1', + scopes: ['groups:write'], +} +const initialGroup = { + id: 'group-1', + externalId: null, + displayName: 'Engineering', + createdAt: new Date('2026-01-01T00:00:00.000Z'), + updatedAt: new Date('2026-01-01T00:00:00.000Z'), +} + +afterAll(resetDbChainMock) + +describe('replaceScimGroup', () => { + beforeEach(() => { + vi.clearAllMocks() + resetDbChainMock() + queueTableRows(scimConnection, [ + { id: 'conn-1', organizationId: 'org-1', status: 'active', settings: {} }, + ]) + let group = { ...initialGroup } + const memberIds = new Set(['user-1']) + mocks.findGroup.mockImplementation(async () => group) + mocks.filterUsers.mockImplementation(async (_tx, _connectionId, ids: string[]) => ids) + mocks.memberIds.mockImplementation(async () => [...memberIds]) + mocks.members.mockImplementation(async () => + [...memberIds].map((scimUserId) => ({ scimUserId, displayName: scimUserId })) + ) + mocks.addMember.mockImplementation(async (_tx, { scimUserId }: { scimUserId: string }) => { + const added = !memberIds.has(scimUserId) + memberIds.add(scimUserId) + return added + }) + mocks.removeMember.mockImplementation(async (_tx, { scimUserId }: { scimUserId: string }) => + memberIds.delete(scimUserId) + ) + mocks.countMembers.mockImplementation(async () => memberIds.size) + mocks.touch.mockImplementation(async () => { + group = { ...group, updatedAt: new Date('2026-01-02T00:00:00.000Z') } + }) + }) + + it('advances resource metadata and version for a membership-only replacement', async () => { + const previous = toGroupResource(initialGroup, 'https://sim.test/api/scim/v2') + const result = await replaceScimGroup.execute({ + principal, + input: { groupId: 'group-1', group: { displayName: 'Engineering', memberIds: ['user-2'] } }, + }) + expect(result.resource.members?.map((entry) => entry.value)).toEqual(['user-2']) + expect(result.resource.meta.lastModified).toBe('2026-01-02T00:00:00.000Z') + expect(result.resource.meta.version).not.toBe(previous.meta.version) + expect(mocks.update).not.toHaveBeenCalled() + expect(mocks.reconcile).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ scimUserIds: ['user-1', 'user-2'] }) + ) + }) + + it('preserves metadata and version when the replacement changes nothing', async () => { + const previous = toGroupResource(initialGroup, 'https://sim.test/api/scim/v2') + const result = await replaceScimGroup.execute({ + principal, + input: { groupId: 'group-1', group: { displayName: 'Engineering', memberIds: ['user-1'] } }, + }) + expect(result.resource.meta).toEqual(previous.meta) + expect(mocks.touch).not.toHaveBeenCalled() + }) +}) diff --git a/apps/sim/ee/scim/lib/application/groups/manage-groups.ts b/apps/sim/ee/scim/lib/application/groups/manage-groups.ts index 7fc9ee761e0..41f71151eaa 100644 --- a/apps/sim/ee/scim/lib/application/groups/manage-groups.ts +++ b/apps/sim/ee/scim/lib/application/groups/manage-groups.ts @@ -293,6 +293,7 @@ export const replaceScimGroup = defineAuthorizedScimUseCase({ if (await addGroupMember(tx, { groupId: current.id, scimUserId })) touched.add(scimUserId) } await assertMemberCount(tx, current.id) + if (touched.size > 0) await touchScimGroup(tx, current.id) await reconcileUsersProjection(tx, { connectionId: context.connection.id, diff --git a/apps/sim/ee/scim/lib/application/users/provision-user.test.ts b/apps/sim/ee/scim/lib/application/users/provision-user.test.ts index cce4073a03c..a905cacaca7 100644 --- a/apps/sim/ee/scim/lib/application/users/provision-user.test.ts +++ b/apps/sim/ee/scim/lib/application/users/provision-user.test.ts @@ -19,6 +19,7 @@ const mocks = vi.hoisted(() => ({ suspend: vi.fn(), unsuspend: vi.fn(), invalidate: vi.fn(), + revokeSessions: vi.fn(), captureEvent: vi.fn(), deleteAccount: vi.fn(), syncIdentity: vi.fn(), @@ -62,6 +63,7 @@ vi.mock('@/lib/organizations/members/lifecycle', () => ({ })) vi.mock('@/lib/organizations/members/revocation', () => ({ invalidateAfterSessionRevocation: mocks.invalidate, + revokeUserSessionsTx: mocks.revokeSessions, })) vi.mock('@/lib/posthog/server', () => ({ captureServerEvent: mocks.captureEvent, @@ -103,6 +105,7 @@ vi.mock('@/ee/scim/lib/application/audit', () => ({ vi.mock('@/ee/scim/lib/base-url', () => ({ scimBaseUrl: () => 'https://sim.test/api/scim/v2' })) import type { Principal } from '@sim/auth/principal' +import { OrchestrationError } from '@/lib/core/orchestration/types' import { provisionScimUser } from '@/ee/scim/lib/application/users/provision-user' import { ScimError, uniqueness } from '@/ee/scim/lib/protocol/errors' @@ -162,7 +165,7 @@ describe('provisionScimUser', () => { mocks.assertUserNameAvailable.mockResolvedValue(undefined) mocks.assertEmailAvailable.mockResolvedValue(undefined) mocks.consumeTombstone.mockResolvedValue(undefined) - mocks.syncIdentity.mockResolvedValue(undefined) + mocks.syncIdentity.mockResolvedValue(false) mocks.suspend.mockResolvedValue(undefined) mocks.unsuspend.mockResolvedValue(undefined) mocks.isInstanceMode.mockReturnValue(false) @@ -449,6 +452,28 @@ describe('provisionScimUser', () => { expect(mocks.invalidate).toHaveBeenCalledWith({ userId: 'u-new', organizationId: 'org-1' }) }) + it('refuses an inactive create that links the organization owner without reporting success', async () => { + stageConnection() + mocks.resolveIdentity.mockResolvedValue({ + action: 'link', + userId: 'owner', + via: 'verified-domain', + }) + mocks.ensureMember.mockResolvedValue({ + success: true, + memberId: 'm-owner', + alreadyMember: true, + }) + mocks.suspend.mockRejectedValueOnce( + new OrchestrationError('conflict', 'Transfer ownership first') + ) + await expect(run(attributes({ active: false }))).rejects.toMatchObject({ code: 'conflict' }) + expect(mocks.consumeTombstone).not.toHaveBeenCalled() + expect(mocks.reconcile).not.toHaveBeenCalled() + expect(mocks.recordAudit).not.toHaveBeenCalled() + expect(mocks.deleteAccount).not.toHaveBeenCalled() + }) + it('relinks a tombstoned account instead of creating a new one', async () => { stageConnection() mocks.resolveIdentity.mockResolvedValue({ action: 'link', userId: 'u-old', via: 'tombstone' }) @@ -504,6 +529,20 @@ describe('provisionScimUser', () => { }) }) + it('ends sessions under the old address when a tombstone relink renames the account', async () => { + stageConnection() + mocks.resolveIdentity.mockResolvedValue({ action: 'link', userId: 'u-old', via: 'tombstone' }) + mocks.syncIdentity.mockResolvedValue(true) + stageReadBack('u-old', attributes(), null) + await run(attributes()) + expect(mocks.revokeSessions).toHaveBeenCalledWith(db, { + userId: 'u-old', + organizationId: 'org-1', + }) + expect(mocks.invalidate).toHaveBeenCalledWith({ userId: 'u-old', organizationId: 'org-1' }) + expect(mocks.suspend).not.toHaveBeenCalled() + }) + it('refuses to provision an account this connection already links', async () => { stageConnection() mocks.resolveIdentity.mockResolvedValue({ diff --git a/apps/sim/ee/scim/lib/application/users/provision-user.ts b/apps/sim/ee/scim/lib/application/users/provision-user.ts index c5728fedf60..9f37c414269 100644 --- a/apps/sim/ee/scim/lib/application/users/provision-user.ts +++ b/apps/sim/ee/scim/lib/application/users/provision-user.ts @@ -14,7 +14,10 @@ import { isInstanceOrganizationMode, } from '@/lib/organizations/instance-org' import { suspendMemberTx, unsuspendMemberTx } from '@/lib/organizations/members/lifecycle' -import { invalidateAfterSessionRevocation } from '@/lib/organizations/members/revocation' +import { + invalidateAfterSessionRevocation, + revokeUserSessionsTx, +} from '@/lib/organizations/members/revocation' import { captureServerEvent } from '@/lib/posthog/server' import { deleteUserAccount } from '@/lib/users/account-deletion' import { @@ -55,6 +58,7 @@ export interface ProvisionScimUserResult { /** The subscription seats were validated against, so the post-commit seat sync targets the same one. */ subscriptionId: string | undefined organizationId: string + emailChanged: boolean resource: ReturnType } @@ -153,6 +157,7 @@ export const provisionScimUser = defineAuthorizedScimUseCase({ scimUserId: string joinedOrganization: boolean subscriptionId: string | undefined + emailChanged: boolean resource: ReturnType } try { @@ -165,6 +170,7 @@ export const provisionScimUser = defineAuthorizedScimUseCase({ ...seatPolicy, }) if (!membership.success) throw membershipFailure(membership.failureCode) + let emailChanged = false /** * A relinked account takes the directory's current identity. A rename @@ -173,7 +179,14 @@ export const provisionScimUser = defineAuthorizedScimUseCase({ * account does not have. */ if (resolution.action === 'link') { - await syncAccountIdentityTx(tx, { userId, email, name: attributes.name.formatted }) + emailChanged = await syncAccountIdentityTx(tx, { + userId, + email, + name: attributes.name.formatted, + }) + if (emailChanged && attributes.active) { + await revokeUserSessionsTx(tx, { userId, organizationId: context.organizationId }) + } /** A relinked account may still carry the suspension a lost deprovisioning left behind. */ if (attributes.active) await unsuspendMemberTx(tx, { userId, source: 'scim' }) } @@ -216,6 +229,7 @@ export const provisionScimUser = defineAuthorizedScimUseCase({ scimUserId: inserted.id, joinedOrganization: !membership.alreadyMember, subscriptionId: seatPolicy.organizationSubscriptionId, + emailChanged, resource: toUserResource(toUserResourceRow(record, []), context.baseUrl), } }) @@ -271,7 +285,7 @@ export const provisionScimUser = defineAuthorizedScimUseCase({ */ afterSuccess: async ({ result, context }) => { /** A member provisioned already inactive had their sessions revoked inside the transaction. */ - if (!result.resource.active) { + if (!result.resource.active || result.emailChanged) { invalidateAfterSessionRevocation({ userId: result.userId, organizationId: context.organizationId, diff --git a/apps/sim/ee/scim/lib/application/users/update-user.test.ts b/apps/sim/ee/scim/lib/application/users/update-user.test.ts index 4ac5a2e5c5d..c8b846e2223 100644 --- a/apps/sim/ee/scim/lib/application/users/update-user.test.ts +++ b/apps/sim/ee/scim/lib/application/users/update-user.test.ts @@ -65,6 +65,7 @@ vi.mock('@/ee/scim/lib/application/audit', () => ({ vi.mock('@/ee/scim/lib/base-url', () => ({ scimBaseUrl: () => 'https://sim.test/api/scim/v2' })) import type { Principal } from '@sim/auth/principal' +import { OrchestrationError } from '@/lib/core/orchestration/types' import { patchScimUser, replaceScimUser } from '@/ee/scim/lib/application/users/update-user' const principal: Principal = { @@ -173,6 +174,25 @@ describe('user updates', () => { expect(mocks.invalidate).toHaveBeenCalledWith({ userId: 'u-1', organizationId: 'org-1' }) }) + it.each(['patch', 'replace'] as const)( + 'propagates owner protection through %s', + async (method) => { + stage() + mocks.suspend.mockRejectedValueOnce( + new OrchestrationError('conflict', 'Transfer ownership first') + ) + const useCase = method === 'patch' ? patchScimUser : replaceScimUser + const input = + method === 'patch' + ? { scimUserId: 'su-1', operations: [{ op: 'replace', path: 'active', value: false }] } + : { scimUserId: 'su-1', attributes: attributes({ active: false }) } + await expect(run(useCase, input)).rejects.toMatchObject({ code: 'conflict' }) + expect(mocks.updateScimUser).not.toHaveBeenCalled() + expect(mocks.reconcile).not.toHaveBeenCalled() + expect(mocks.recordAudit).not.toHaveBeenCalled() + } + ) + it('proves the organization owns the new domain before moving the address, then signs the user out', async () => { stage() await run(patchScimUser, { diff --git a/apps/sim/ee/scim/lib/entitlement.test.ts b/apps/sim/ee/scim/lib/entitlement.test.ts index c03246659ff..27cf50f5cc8 100644 --- a/apps/sim/ee/scim/lib/entitlement.test.ts +++ b/apps/sim/ee/scim/lib/entitlement.test.ts @@ -33,12 +33,25 @@ describe('isScimEntitledForOrganization', () => { expect(mockEnterprisePlan).not.toHaveBeenCalled() }) - it('ships with the enterprise plan on the hosted product, with nothing to switch on', async () => { + it('honors the deployment disable flag on the hosted product', async () => { setEnvFlags({ isScimEnabled: false, isHosted: true }) + await expect(isScimEntitledForOrganization('org-1')).resolves.toBe(false) + expect(mockEnterprisePlan).not.toHaveBeenCalled() + }) + + it('requires an enterprise plan when provisioning is enabled on the hosted product', async () => { + setEnvFlags({ isScimEnabled: true, isHosted: true }) mockEnterprisePlan.mockResolvedValue(false) await expect(isScimEntitledForOrganization('org-1')).resolves.toBe(false) mockEnterprisePlan.mockResolvedValue(true) await expect(isScimEntitledForOrganization('org-1')).resolves.toBe(true) - expect(mockEnterprisePlan).toHaveBeenCalledWith('org-1') + expect(mockEnterprisePlan).toHaveBeenCalledWith('org-1', 'throw', undefined) + }) + + it('propagates billing read failures instead of treating the organization as unentitled', async () => { + setEnvFlags({ isScimEnabled: true, isHosted: true }) + const failure = new Error('Billing database unavailable') + mockEnterprisePlan.mockRejectedValue(failure) + await expect(isScimEntitledForOrganization('org-1')).rejects.toBe(failure) }) }) diff --git a/apps/sim/ee/scim/lib/entitlement.ts b/apps/sim/ee/scim/lib/entitlement.ts index 688eec2f206..2b9398d49b9 100644 --- a/apps/sim/ee/scim/lib/entitlement.ts +++ b/apps/sim/ee/scim/lib/entitlement.ts @@ -1,25 +1,33 @@ import { isOrganizationOnEnterprisePlan } from '@/lib/billing/core/subscription' import { isHosted, isScimEnabled } from '@/lib/core/config/env-flags' +import type { DbOrTx } from '@/lib/db/types' /** * Whether this deployment serves directory provisioning at all. * * The hosted product ships it as part of the enterprise plan, the same way SSO - * ships: nothing to switch on. A self-hosted deployment turns it on with the - * enterprise switch (`ENTERPRISE_ENABLED`) or the feature's own variable - * (`SCIM_ENABLED`), which also lets an operator turn just this feature off. + * ships by default, with SCIM_ENABLED=false available to defer activation. + * A self-hosted deployment turns it on with the enterprise switch + * (`ENTERPRISE_ENABLED`) or the feature's own variable (`SCIM_ENABLED`), which + * also lets an operator turn just this feature off. */ export function isScimDeploymentEnabled(): boolean { - return isHosted || isScimEnabled + return isScimEnabled } /** * Whether directory provisioning may run for an organization: the deployment * serves it, and on the hosted product the organization holds the enterprise * plan. + * + * Billing read failures propagate because a false entitlement also releases + * managed-membership and JIT locks; an outage must not relax those policies. */ -export async function isScimEntitledForOrganization(organizationId: string): Promise { +export async function isScimEntitledForOrganization( + organizationId: string, + executor?: DbOrTx +): Promise { if (!isScimDeploymentEnabled()) return false if (!isHosted) return true - return isOrganizationOnEnterprisePlan(organizationId) + return isOrganizationOnEnterprisePlan(organizationId, 'throw', executor) } diff --git a/apps/sim/ee/scim/lib/identity/account-identity.test.ts b/apps/sim/ee/scim/lib/identity/account-identity.test.ts new file mode 100644 index 00000000000..56c4b34621f --- /dev/null +++ b/apps/sim/ee/scim/lib/identity/account-identity.test.ts @@ -0,0 +1,47 @@ +/** + * @vitest-environment node + */ +import { db } from '@sim/db' +import { user } from '@sim/db/schema' +import { dbChainMockFns, queueTableRows, resetDbChainMock } from '@sim/testing' +import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest' + +const { assertAvailable } = vi.hoisted(() => ({ assertAvailable: vi.fn() })) + +vi.mock('@/ee/scim/lib/identity/resolve-user', () => ({ + assertEmailAvailable: assertAvailable, +})) + +import { syncAccountIdentityTx } from '@/ee/scim/lib/identity/account-identity' + +afterAll(resetDbChainMock) + +describe('syncAccountIdentityTx', () => { + beforeEach(() => { + vi.clearAllMocks() + resetDbChainMock() + queueTableRows(user, [{ email: 'ada@acme.test' }]) + }) + + it('reports an address change for session revocation and clears email verification', async () => { + await expect( + syncAccountIdentityTx(db, { userId: 'u-1', email: 'new@acme.test', name: 'Ada' }) + ).resolves.toBe(true) + expect(assertAvailable).toHaveBeenCalledWith(db, 'new@acme.test', 'u-1') + expect(dbChainMockFns.set).toHaveBeenCalledWith( + expect.objectContaining({ + email: 'new@acme.test', + normalizedEmail: 'new@acme.test', + emailVerified: false, + }) + ) + }) + + it('does not report a case-only address change or clear its verification', async () => { + await expect( + syncAccountIdentityTx(db, { userId: 'u-1', email: 'Ada@acme.test', name: 'Ada' }) + ).resolves.toBe(false) + expect(assertAvailable).not.toHaveBeenCalled() + expect(dbChainMockFns.set.mock.calls[0][0]).not.toHaveProperty('emailVerified') + }) +}) diff --git a/apps/sim/ee/scim/lib/identity/account-identity.ts b/apps/sim/ee/scim/lib/identity/account-identity.ts index c41afd03fe9..d7fc539ea8c 100644 --- a/apps/sim/ee/scim/lib/identity/account-identity.ts +++ b/apps/sim/ee/scim/lib/identity/account-identity.ts @@ -11,11 +11,12 @@ import { assertEmailAvailable } from '@/ee/scim/lib/identity/resolve-user' * rename that arrives as delete-and-recreate lands the same way as one that * arrives as a PATCH. The caller has already proven the organization owns the * new address's domain; this asserts nobody else holds it and applies it. + * Returns whether the email changed so callers revoke sessions established under the old address. */ export async function syncAccountIdentityTx( tx: DbOrTx, params: { userId: string; email?: string; name: string } -): Promise { +): Promise { let emailChanged = false if (params.email !== undefined) { const [current] = await tx @@ -40,4 +41,5 @@ export async function syncAccountIdentityTx( updatedAt: new Date(), }) .where(eq(user.id, params.userId)) + return emailChanged } diff --git a/apps/sim/ee/scim/lib/managed-membership.postgres.test.ts b/apps/sim/ee/scim/lib/managed-membership.postgres.test.ts new file mode 100644 index 00000000000..de48000ec6d --- /dev/null +++ b/apps/sim/ee/scim/lib/managed-membership.postgres.test.ts @@ -0,0 +1,206 @@ +/** + * @vitest-environment node + */ +import { envFlagsMock } from '@sim/testing/mocks/env-flags.mock' +import { generateId } from '@sim/utils/id' +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' + +vi.unmock('@sim/db') +vi.unmock('@sim/db/schema') +vi.unmock('drizzle-orm') +vi.mock('@/lib/core/config/env-flags', () => ({ + ...envFlagsMock, + isHosted: true, + isScimEnabled: true, + isBillingEnabled: true, +})) + +const databaseUrl = process.env.OAUTH_TOKEN_FAMILY_TEST_DATABASE_URL + +async function loadRuntime() { + const [{ db }, schema, { eq, inArray, sql }, { alias }, membership, entitlement] = + await Promise.all([ + import('@sim/db'), + import('@sim/db/schema'), + import('drizzle-orm'), + import('drizzle-orm/pg-core'), + import('@/ee/scim/lib/managed-membership'), + import('@/ee/scim/lib/entitlement'), + ]) + return { db, schema, eq, inArray, sql, alias, ...membership, ...entitlement } +} + +describe.skipIf(!databaseUrl)('SCIM managed membership in PostgreSQL', () => { + let runtime: Awaited> + let orgId: string + let otherOrgId: string + let connectionId: string + let managedUserId: string + let unmanagedUserId: string + let managedEmail: string + + beforeAll(async () => { + process.env.DATABASE_URL = databaseUrl + runtime = await loadRuntime() + }, 30_000) + + beforeEach(async () => { + vi.stubEnv('DB_TX_TRIPWIRE', 'throw') + orgId = generateId() + otherOrgId = generateId() + connectionId = generateId() + managedUserId = generateId() + unmanagedUserId = generateId() + managedEmail = `${managedUserId}@scim-membership.test` + const { db, schema } = runtime + const now = new Date() + await db.insert(schema.organization).values( + [orgId, otherOrgId].map((id) => ({ + id, + name: 'SCIM predicate test', + slug: id, + createdAt: now, + })) + ) + await db.insert(schema.user).values( + [managedUserId, unmanagedUserId].map((id) => ({ + id, + name: 'SCIM predicate test', + email: `${id}@scim-membership.test`, + emailVerified: true, + createdAt: now, + updatedAt: now, + })) + ) + await db.insert(schema.subscription).values({ + id: generateId(), + plan: 'enterprise', + referenceId: orgId, + status: 'active', + seats: 50, + metadata: { plan: 'enterprise', referenceId: orgId, seats: 50, monthlyPrice: 100 }, + periodStart: now, + periodEnd: new Date(now.getTime() + 86_400_000), + }) + await db.insert(schema.scimConnection).values({ + id: connectionId, + organizationId: orgId, + status: 'active', + settings: { lockManualMembership: true }, + }) + await db.insert(schema.scimUser).values({ + id: generateId(), + connectionId, + userId: managedUserId, + userName: managedEmail, + orderKey: managedUserId, + attributes: { + userName: managedEmail, + active: true, + displayName: 'Managed user', + name: { formatted: 'Managed user' }, + emails: [{ value: managedEmail, primary: true, type: 'work' }], + }, + }) + }) + + afterEach(async () => { + const { db, schema, eq, inArray } = runtime + await db.delete(schema.subscription).where(eq(schema.subscription.referenceId, orgId)) + await db.delete(schema.organization).where(inArray(schema.organization.id, [orgId, otherOrgId])) + await db.delete(schema.user).where(inArray(schema.user.id, [managedUserId, unmanagedUserId])) + }) + + async function invitee(organizationId: string, email: string) { + const { db, schema, sql, scimManagedUserPredicate } = runtime + const [row] = await db + .select({ + id: schema.user.id, + managed: scimManagedUserPredicate(organizationId, schema.user.id), + }) + .from(schema.user) + .where(sql`lower(${schema.user.email}) = ${email}`) + return row + } + + it('correlates the invitation lookup to its outer user without ambiguous inner join columns', async () => { + expect(await invitee(orgId, managedEmail)).toEqual({ id: managedUserId, managed: true }) + expect(await invitee(orgId, `${unmanagedUserId}@scim-membership.test`)).toEqual({ + id: unmanagedUserId, + managed: false, + }) + expect(await invitee(otherOrgId, managedEmail)).toEqual({ id: managedUserId, managed: false }) + }) + + it.each(['invited_user', 'invited"user'])( + 'qualifies an aliased outer table named %s', + async (name) => { + const { db, schema, alias, eq, scimManagedUserPredicate } = runtime + const invited = alias(schema.user, name) + const rows = await db + .select({ id: invited.id, managed: scimManagedUserPredicate(orgId, invited.id) }) + .from(invited) + .where(eq(invited.id, managedUserId)) + expect(rows).toEqual([{ id: managedUserId, managed: true }]) + } + ) + + it.each([ + { status: 'disabled', settings: { lockManualMembership: true } }, + { status: 'active', settings: { lockManualMembership: false } }, + { status: 'active', settings: {} }, + ])('allows edits when the connection is $status with $settings', async ({ status, settings }) => { + const { db, schema, eq, assertMembershipNotScimManaged } = runtime + await db + .update(schema.scimConnection) + .set({ status, settings }) + .where(eq(schema.scimConnection.id, connectionId)) + expect(await invitee(orgId, managedEmail)).toEqual({ id: managedUserId, managed: false }) + await expect( + db.transaction((executor) => + assertMembershipNotScimManaged({ organizationId: orgId, userId: managedUserId, executor }) + ) + ).resolves.toBeUndefined() + }) + + it('runs the permission guard and hosted entitlement through the same transaction', async () => { + const { db, assertMembershipNotScimManaged } = runtime + await expect( + db.transaction((executor) => + assertMembershipNotScimManaged({ organizationId: orgId, userId: managedUserId, executor }) + ) + ).rejects.toMatchObject({ detailCode: 'SCIM_MANAGED_MEMBERSHIP' }) + for (const input of [ + { organizationId: orgId, userId: unmanagedUserId }, + { organizationId: otherOrgId, userId: managedUserId }, + { organizationId: orgId, userId: "' OR true --" }, + ]) { + await expect( + db.transaction((executor) => assertMembershipNotScimManaged({ ...input, executor })) + ).resolves.toBeUndefined() + } + }) + + it('allows a previously managed member when the real Enterprise subscription has ended', async () => { + const { db, schema, eq, assertMembershipNotScimManaged } = runtime + await db + .update(schema.subscription) + .set({ status: 'canceled' }) + .where(eq(schema.subscription.referenceId, orgId)) + await expect( + db.transaction((executor) => + assertMembershipNotScimManaged({ organizationId: orgId, userId: managedUserId, executor }) + ) + ).resolves.toBeUndefined() + }) + + it('propagates a real billing query failure without relaxing directory policy', async () => { + const { db, sql, isScimEntitledForOrganization } = runtime + await expect( + db.transaction(async (executor) => { + await executor.execute(sql`set local search_path to pg_catalog`) + await isScimEntitledForOrganization(orgId, executor) + }) + ).rejects.toMatchObject({ cause: { code: '42P01' } }) + }) +}) diff --git a/apps/sim/ee/scim/lib/managed-membership.test.ts b/apps/sim/ee/scim/lib/managed-membership.test.ts index f0e1bf274d0..bf46cb151db 100644 --- a/apps/sim/ee/scim/lib/managed-membership.test.ts +++ b/apps/sim/ee/scim/lib/managed-membership.test.ts @@ -6,6 +6,9 @@ import { dbChainMockFns, resetDbChainMock } from '@sim/testing' import { beforeEach, describe, expect, it, vi } from 'vitest' import { ForbiddenOperationError } from '@/lib/core/application' +vi.unmock('@sim/db/schema') +vi.unmock('drizzle-orm') + const { mockDeploymentEnabled, mockEntitled } = vi.hoisted(() => ({ mockDeploymentEnabled: vi.fn(), mockEntitled: vi.fn(), @@ -45,7 +48,7 @@ describe('assertMembershipNotScimManaged', () => { queueProbe(true) mockEntitled.mockResolvedValue(false) await expect(assertMembershipNotScimManaged(params)).resolves.toBeUndefined() - expect(mockEntitled).toHaveBeenCalledWith('org-1') + expect(mockEntitled).toHaveBeenCalledWith('org-1', db) }) it('never reads the plan for a member the directory does not manage', async () => { diff --git a/apps/sim/ee/scim/lib/managed-membership.ts b/apps/sim/ee/scim/lib/managed-membership.ts index ca39aa5a662..8361c1af55a 100644 --- a/apps/sim/ee/scim/lib/managed-membership.ts +++ b/apps/sim/ee/scim/lib/managed-membership.ts @@ -1,5 +1,5 @@ import { scimConnection, scimUser } from '@sim/db/schema' -import { type AnyColumn, type SQL, sql } from 'drizzle-orm' +import { type AnyColumn, Column, getTableName, is, type SQL, sql } from 'drizzle-orm' import { ForbiddenOperationError } from '@/lib/core/application' import type { DbOrTx } from '@/lib/db/types' import { isScimDeploymentEnabled, isScimEntitledForOrganization } from '@/ee/scim/lib/entitlement' @@ -36,17 +36,27 @@ export function scimManagedUserPredicate( organizationId: string, userIdColumn: SQL | AnyColumn ): SQL { + const userId = is(userIdColumn, Column) ? qualifiedColumn(userIdColumn) : userIdColumn return sql`exists ( select 1 from ${scimUser} - join ${scimConnection} on ${scimConnection.id} = ${scimUser.connectionId} - where ${scimUser.userId} = ${userIdColumn} - and ${scimConnection.organizationId} = ${organizationId} - and ${scimConnection.status} = 'active' - and coalesce((${scimConnection.settings} ->> 'lockManualMembership')::boolean, false) = true + join ${scimConnection} on ${qualifiedColumn(scimConnection.id)} = ${qualifiedColumn(scimUser.connectionId)} + where ${qualifiedColumn(scimUser.userId)} = ${userId} + and ${qualifiedColumn(scimConnection.organizationId)} = ${organizationId} + and ${qualifiedColumn(scimConnection.status)} = 'active' + and coalesce((${qualifiedColumn(scimConnection.settings)} ->> 'lockManualMembership')::boolean, false) = true )` } +/** + * Drizzle removes Column qualifiers from single-table SELECT expressions, + * including nested SQL. Explicit identifiers preserve this subquery's joins + * and outer correlation, using the column's current table name or alias. + */ +function qualifiedColumn(column: AnyColumn): SQL { + return sql`${sql.identifier(getTableName(column.table))}.${sql.identifier(column.name)}` +} + /** Refuses a change to a member the directory owns. */ export async function assertMembershipNotScimManaged(params: { organizationId: string @@ -63,7 +73,7 @@ export async function assertMembershipNotScimManaged(params: { * manual changes on behalf of a directory that can no longer sync. Read only * once a managed row is found, so the common case costs nothing. */ - if (!(await isScimEntitledForOrganization(params.organizationId))) return + if (!(await isScimEntitledForOrganization(params.organizationId, params.executor))) return throw new ForbiddenOperationError( 'SCIM_MANAGED_MEMBERSHIP', 'This member is managed by the organization’s identity provider. Make the change there, or turn off managed-membership locking in the organization’s directory settings.' diff --git a/apps/sim/ee/scim/lib/projection/grants.test.ts b/apps/sim/ee/scim/lib/projection/grants.test.ts index 2051eebf577..bcbe26925f7 100644 --- a/apps/sim/ee/scim/lib/projection/grants.test.ts +++ b/apps/sim/ee/scim/lib/projection/grants.test.ts @@ -130,10 +130,26 @@ describe('planGrantChanges', () => { it('carries the previous level when a workspace changes level in either direction', () => { expect( planGrantChanges([workspace('ws-1', 'admin')], [workspace('ws-1', 'read')]).apply - ).toEqual([{ grant: workspace('ws-1', 'admin'), previousPermission: 'read' }]) + ).toEqual([{ grant: workspace('ws-1', 'admin'), previousGrant: workspace('ws-1', 'read') }]) expect( planGrantChanges([workspace('ws-1', 'read')], [workspace('ws-1', 'admin')]).apply - ).toEqual([{ grant: workspace('ws-1', 'read'), previousPermission: 'admin' }]) + ).toEqual([{ grant: workspace('ws-1', 'read'), previousGrant: workspace('ws-1', 'admin') }]) + }) + + it('repairs missing and lowered access even when the provenance still matches', () => { + const current = workspace('ws-1', 'admin') + expect(planGrantChanges([current], [current], []).apply).toEqual([ + { grant: current, previousGrant: current }, + ]) + expect(planGrantChanges([current], [current], [workspace('ws-1', 'read')]).apply).toEqual([ + { grant: current, previousGrant: current }, + ]) + expect( + planGrantChanges([workspace('ws-1', 'read')], [workspace('ws-1', 'read')], [current]) + ).toEqual({ + apply: [], + withdraw: [], + }) }) it('never withdraws a grant that is also desired at a different level', () => { diff --git a/apps/sim/ee/scim/lib/projection/grants.ts b/apps/sim/ee/scim/lib/projection/grants.ts index 131cf23f555..36789490fea 100644 --- a/apps/sim/ee/scim/lib/projection/grants.ts +++ b/apps/sim/ee/scim/lib/projection/grants.ts @@ -22,6 +22,8 @@ export interface ProjectionGrant { permissionType?: PermissionType /** Present on grants read back from provenance; a desired grant has no origin yet. */ origin?: ProjectionGrantOrigin + /** Manual workspace permission that predates or exceeds the directory grant. */ + baselinePermission?: PermissionType | null } /** One `scim_group_mapping` row the user reaches through a group they belong to. */ @@ -78,8 +80,8 @@ export function resolveDesiredGrants(rows: readonly MappingRow[]): ProjectionGra export interface GrantApplication { grant: ProjectionGrant - /** The level a previous pass set on a workspace, present when the level changes. */ - previousPermission?: PermissionType + /** Provenance retained even when the actual access has drifted away. */ + previousGrant?: ProjectionGrant } export interface GrantPlan { @@ -92,17 +94,18 @@ export interface GrantPlan { /** * Diffs the desired set against what the directory previously granted. * - * Only differences are returned, which is what makes a reconcile pass - * idempotent: identical inputs plan nothing. A workspace already granted at a - * different level is planned as an application carrying the previous level, so - * the executor can lower as well as raise. + * The actual access, when supplied, must also satisfy the mapping. Provenance + * alone cannot detect a permission removed or lowered outside the directory. + * Unchanged mappings with intact access plan nothing. */ export function planGrantChanges( desired: readonly ProjectionGrant[], - current: readonly ProjectionGrant[] + current: readonly ProjectionGrant[], + actual: readonly ProjectionGrant[] = current ): GrantPlan { const desiredByKey = new Map(desired.map((grant) => [grantKey(grant), grant])) const currentByKey = new Map(current.map((grant) => [grantKey(grant), grant])) + const actualByKey = new Map(actual.map((grant) => [grantKey(grant), grant])) const withdraw: ProjectionGrant[] = [] for (const [key, grant] of currentByKey) { @@ -120,7 +123,13 @@ export function planGrantChanges( grant.permissionType !== undefined && existing.permissionType !== undefined && grant.permissionType !== existing.permissionType - if (levelChanged) apply.push({ grant, previousPermission: existing.permissionType }) + const observed = actualByKey.get(key) + const accessMissing = + !observed || + (grant.permissionType !== undefined && + (!observed.permissionType || + permissionRank(observed.permissionType) < permissionRank(grant.permissionType))) + if (levelChanged || accessMissing) apply.push({ grant, previousGrant: existing }) } return { withdraw, apply } diff --git a/apps/sim/ee/scim/lib/projection/reconcile-user.test.ts b/apps/sim/ee/scim/lib/projection/reconcile-user.test.ts index e378b10032e..559f8b8f61b 100644 --- a/apps/sim/ee/scim/lib/projection/reconcile-user.test.ts +++ b/apps/sim/ee/scim/lib/projection/reconcile-user.test.ts @@ -2,7 +2,15 @@ * @vitest-environment node */ import { db } from '@sim/db' -import { scimGroupMember, scimProjectionGrant, scimUser, workspace } from '@sim/db/schema' +import { + member, + permissionGroupMember, + permissions, + scimGroupMember, + scimProjectionGrant, + scimUser, + workspace, +} from '@sim/db/schema' import { dbChainMockFns, queueTableRows, resetDbChainMock } from '@sim/testing' import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest' @@ -53,10 +61,19 @@ interface Scenario { current?: Array> mappings?: Array> ownedWorkspaces?: string[] + actualWorkspaces?: Array<{ id: string; permissionType: 'read' | 'write' | 'admin' }> + actualGroups?: string[] + actualRole?: string } -/** Queues the four reads the reconciler makes, in the order it makes them. */ -function stage({ current = [], mappings = [], ownedWorkspaces = ['ws-1'] }: Scenario) { +function stage({ + current = [], + mappings = [], + ownedWorkspaces = ['ws-1'], + actualWorkspaces, + actualGroups = [], + actualRole = 'member', +}: Scenario) { queueTableRows(scimUser, [{ userId: 'u-1' }]) queueTableRows(scimProjectionGrant, current) queueTableRows(scimGroupMember, mappings) @@ -64,6 +81,18 @@ function stage({ current = [], mappings = [], ownedWorkspaces = ['ws-1'] }: Scen workspace, ownedWorkspaces.map((id) => ({ id })) ) + queueTableRows( + permissions, + actualWorkspaces ?? + current + .filter((grant) => grant.targetKind === 'workspace') + .map((grant) => ({ id: grant.targetId, permissionType: grant.permissionType })) + ) + queueTableRows( + permissionGroupMember, + actualGroups.map((id) => ({ id })) + ) + queueTableRows(member, [{ role: actualRole }]) } const workspaceMapping = (workspaceId: string, permissionType: string) => ({ @@ -118,9 +147,16 @@ describe('reconcileUserProjection', () => { it('records access the person already held by hand as adopted, and counts no change', async () => { mocks.grantWorkspace.mockResolvedValue('unchanged') - stage({ mappings: [workspaceMapping('ws-1', 'write')] }) + stage({ + mappings: [workspaceMapping('ws-1', 'write')], + actualWorkspaces: [{ id: 'ws-1', permissionType: 'write' }], + }) const delta = await reconcileUserProjection(db, params) - expect(insertedValues()[0]).toMatchObject({ targetId: 'ws-1', origin: 'adopted' }) + expect(insertedValues()[0]).toMatchObject({ + targetId: 'ws-1', + origin: 'adopted', + baselinePermission: 'write', + }) expect(delta.added).toHaveLength(0) }) @@ -137,6 +173,142 @@ describe('reconcileUserProjection', () => { expect(dbChainMockFns.delete).not.toHaveBeenCalled() }) + it.each([null, 'read'] as const)( + 'repairs recorded workspace access that is actually %s', + async (permissionType) => { + stage({ + current: [ + { + targetKind: 'workspace', + targetId: 'ws-1', + permissionType: 'admin', + origin: 'directory', + }, + ], + mappings: [workspaceMapping('ws-1', 'admin')], + actualWorkspaces: permissionType ? [{ id: 'ws-1', permissionType }] : [], + }) + const delta = await reconcileUserProjection(db, params) + expect(mocks.grantWorkspace).toHaveBeenCalledWith(db, { + workspaceId: 'ws-1', + userId: 'u-1', + permission: 'admin', + }) + expect(delta.raised).toHaveLength(1) + } + ) + + it('repairs a missing permission-group membership and a manually lowered organization role', async () => { + stage({ + current: [ + { targetKind: 'permission_group', targetId: 'pg-1', origin: 'directory' }, + { targetKind: 'org_role', targetId: 'admin', origin: 'directory' }, + ], + mappings: [ + { targetKind: 'permission_group', permissionGroupId: 'pg-1' }, + { targetKind: 'org_role', role: 'admin' }, + ], + actualGroups: [], + actualRole: 'member', + }) + await reconcileUserProjection(db, params) + expect(mocks.addMember).toHaveBeenCalledWith(db, { + organizationId: 'org-1', + groupId: 'pg-1', + userId: 'u-1', + }) + expect(mocks.changeMemberRole).toHaveBeenCalledWith(db, { + organizationId: 'org-1', + userId: 'u-1', + role: 'admin', + }) + }) + + it('restores manual Read after a directory Admin mapping is removed', async () => { + stage({ + mappings: [workspaceMapping('ws-1', 'admin')], + actualWorkspaces: [{ id: 'ws-1', permissionType: 'read' }], + }) + await reconcileUserProjection(db, params) + const saved = insertedValues()[0] + expect(saved).toMatchObject({ + permissionType: 'admin', + baselinePermission: 'read', + origin: 'directory', + }) + + vi.clearAllMocks() + resetDbChainMock() + mocks.readPermission.mockResolvedValue('admin') + stage({ current: [saved] }) + await reconcileUserProjection(db, params) + expect(mocks.lowerWorkspace).toHaveBeenCalledWith(db, { + workspaceId: 'ws-1', + userId: 'u-1', + from: 'admin', + to: 'read', + }) + expect(mocks.revokeWorkspace).not.toHaveBeenCalled() + }) + + it('preserves an adopted manual Admin when the mapping is lowered', async () => { + stage({ + current: [ + { targetKind: 'workspace', targetId: 'ws-1', permissionType: 'admin', origin: 'adopted' }, + ], + mappings: [workspaceMapping('ws-1', 'read')], + }) + mocks.grantWorkspace.mockResolvedValue('unchanged') + await reconcileUserProjection(db, params) + expect(mocks.lowerWorkspace).not.toHaveBeenCalled() + expect(mocks.grantWorkspace).toHaveBeenCalledWith(db, { + workspaceId: 'ws-1', + userId: 'u-1', + permission: 'admin', + }) + expect(insertedValues()[0]).toMatchObject({ baselinePermission: 'admin' }) + }) + + it('never lowers below the manual baseline during a directory downgrade', async () => { + stage({ + current: [ + { + targetKind: 'workspace', + targetId: 'ws-1', + permissionType: 'admin', + origin: 'directory', + baselinePermission: 'write', + }, + ], + mappings: [workspaceMapping('ws-1', 'read')], + }) + await reconcileUserProjection(db, params) + expect(mocks.lowerWorkspace).toHaveBeenCalledWith(db, { + workspaceId: 'ws-1', + userId: 'u-1', + from: 'admin', + to: 'write', + }) + }) + + it('withdraws the entire covered access when managed membership is locked', async () => { + stage({ + current: [ + { + targetKind: 'workspace', + targetId: 'ws-1', + permissionType: 'admin', + origin: 'directory', + baselinePermission: 'read', + }, + ], + }) + mocks.readPermission.mockResolvedValue('admin') + await reconcileUserProjection(db, { ...params, settings: { lockManualMembership: true } }) + expect(mocks.revokeWorkspace).toHaveBeenCalled() + expect(mocks.lowerWorkspace).not.toHaveBeenCalled() + }) + it('forgets an adopted grant without touching the access unless the directory is the source of truth', async () => { stage({ current: [ diff --git a/apps/sim/ee/scim/lib/projection/reconcile-user.ts b/apps/sim/ee/scim/lib/projection/reconcile-user.ts index 12aab864efc..69260fe34a7 100644 --- a/apps/sim/ee/scim/lib/projection/reconcile-user.ts +++ b/apps/sim/ee/scim/lib/projection/reconcile-user.ts @@ -1,5 +1,8 @@ import { db } from '@sim/db' import { + member, + permissionGroupMember, + permissions, type ScimConnectionSettings, scimGroupMapping, scimGroupMember, @@ -44,14 +47,10 @@ const logger = createLogger('ScimProjection') * Turning directory group membership into Sim access. * * A SCIM group means nothing on its own; an administrator maps it to something - * Sim understands. This module computes what a user's mappings say they should - * have, compares it to what SCIM previously granted them, and applies only the - * difference. - * - * The comparison is against SCIM's own grants, recorded in - * `scim_projection_grant`, never against the user's total access. That is the - * distinction that keeps a directory sync from revoking access a workspace - * administrator granted by hand. + * Sim understands. This module compares those desired grants with both their + * recorded provenance and the user's actual access, repairing missing grants. + * Provenance and saved manual workspace levels determine what can be withdrawn + * without removing manual access when membership locking is off. */ export interface ProjectionDelta { @@ -96,6 +95,7 @@ async function currentGrants(tx: DbOrTx, scimUserId: string): Promise { + const workspaceIds = params.desired + .filter((grant) => grant.targetKind === 'workspace') + .map((grant) => grant.targetId) + const groupIds = params.desired + .filter((grant) => grant.targetKind === 'permission_group') + .map((grant) => grant.targetId) + const [workspaceRows, groupRows, memberRows] = await Promise.all([ + workspaceIds.length > 0 + ? tx + .select({ id: permissions.entityId, permissionType: permissions.permissionType }) + .from(permissions) + .where( + and( + eq(permissions.userId, params.userId), + eq(permissions.entityType, 'workspace'), + inArray(permissions.entityId, workspaceIds) + ) + ) + : [], + groupIds.length > 0 + ? tx + .select({ id: permissionGroupMember.permissionGroupId }) + .from(permissionGroupMember) + .where( + and( + eq(permissionGroupMember.organizationId, params.organizationId), + eq(permissionGroupMember.userId, params.userId), + inArray(permissionGroupMember.permissionGroupId, groupIds) + ) + ) + : [], + params.desired.some((grant) => grant.targetKind === 'org_role') + ? tx + .select({ role: member.role }) + .from(member) + .where( + and(eq(member.organizationId, params.organizationId), eq(member.userId, params.userId)) + ) + .limit(1) + : [], + ]) + return [ + ...workspaceRows.map((row) => ({ + targetKind: 'workspace' as const, + targetId: row.id, + permissionType: row.permissionType, + })), + ...groupRows.map((row) => ({ targetKind: 'permission_group' as const, targetId: row.id })), + ...memberRows + .filter((row) => row.role === 'admin') + .map(() => ({ targetKind: 'org_role' as const, targetId: 'admin' })), + ] +} + /** * What applying a grant did. `unchanged` means the person already held it by * some other route — a manual grant — and nothing was written. @@ -140,23 +200,30 @@ async function applyGrant( organizationId: string userId: string grant: ProjectionGrant - /** The level a previous pass set on a workspace, when lowering it. */ - previousPermission?: PermissionType + previousGrant?: ProjectionGrant + baselinePermission: PermissionType | null + lockManualMembership: boolean } ): Promise { const { grant } = params switch (grant.targetKind) { case 'workspace': { if (!grant.permissionType) return 'skipped' + const minimum = + !params.lockManualMembership && + params.baselinePermission && + permissionRank(params.baselinePermission) > permissionRank(grant.permissionType) + ? params.baselinePermission + : grant.permissionType if ( - params.previousPermission && - permissionRank(params.previousPermission) > permissionRank(grant.permissionType) + params.previousGrant?.permissionType && + permissionRank(params.previousGrant.permissionType) > permissionRank(minimum) ) { const lowered = await lowerWorkspaceAccessTx(tx, { workspaceId: grant.targetId, userId: params.userId, - from: params.previousPermission, - to: grant.permissionType, + from: params.previousGrant.permissionType, + to: minimum, }) if (lowered === 'lowered') return 'applied' /** The row is no longer at the level the directory set; ensure at least the desired level. */ @@ -164,7 +231,7 @@ async function applyGrant( const outcome = await grantWorkspaceAccessTx(tx, { workspaceId: grant.targetId, userId: params.userId, - permission: grant.permissionType, + permission: minimum, }) return outcome === 'unchanged' ? 'unchanged' : 'applied' } @@ -188,7 +255,7 @@ async function applyGrant( * * The owner is out of the directory's reach: ownership carries billing and the * last-owner guarantee, and a group that happens to contain the owner must not - * fail every sync over it. Returns false, and records no grant, so the mapping + * fail every sync over it. Returns `skipped` and records no grant, so the mapping * is simply inert for that one person. */ async function setOrganizationRole( @@ -259,6 +326,17 @@ async function withdrawGrant( ) { return true } + if (!params.lockManualMembership && grant.baselinePermission) { + if (permissionRank(current) > permissionRank(grant.baselinePermission)) { + await lowerWorkspaceAccessTx(tx, { + workspaceId: grant.targetId, + userId: params.userId, + from: current, + to: grant.baselinePermission, + }) + } + return true + } const outcome = await revokeWorkspaceAccessTx(tx, { workspaceId: grant.targetId, userId: params.userId, @@ -365,7 +443,12 @@ export async function reconcileUserProjection( const desired = mapped.filter( (grant) => grant.targetKind !== 'workspace' || !foreignWorkspaceIds.has(grant.targetId) ) - const plan = planGrantChanges(desired, current) + const actual = await actualGrants(tx, { + organizationId: params.organizationId, + userId: record.userId, + desired, + }) + const plan = planGrantChanges(desired, current, actual) const delta: ProjectionDelta = { added: [], removed: [], raised: [] } const lockManualMembership = params.settings.lockManualMembership === true @@ -392,14 +475,35 @@ export async function reconcileUserProjection( delta.removed.push(grant) } - for (const { grant, previousPermission } of plan.apply) { + for (const { grant, previousGrant } of plan.apply) { + const currentPermission = + grant.targetKind === 'workspace' + ? (actual.find( + (observed) => + observed.targetKind === 'workspace' && observed.targetId === grant.targetId + )?.permissionType ?? null) + : null + let baselinePermission = previousGrant?.baselinePermission ?? null + if ( + currentPermission && + (!previousGrant || + previousGrant.origin === 'adopted' || + (previousGrant.permissionType && + permissionRank(currentPermission) > permissionRank(previousGrant.permissionType))) && + (!baselinePermission || + permissionRank(currentPermission) > permissionRank(baselinePermission)) + ) { + baselinePermission = currentPermission + } let applied: GrantOutcome try { applied = await applyGrant(tx, { organizationId: params.organizationId, userId: record.userId, grant, - ...(previousPermission ? { previousPermission } : {}), + previousGrant, + baselinePermission, + lockManualMembership, }) } catch (error) { /** @@ -443,6 +547,7 @@ export async function reconcileUserProjection( targetKind: grant.targetKind, targetId: grant.targetId, permissionType: grant.permissionType ?? null, + baselinePermission, origin: applied === 'applied' ? 'directory' : 'adopted', createdAt: new Date(), updatedAt: new Date(), @@ -455,13 +560,14 @@ export async function reconcileUserProjection( ], set: { permissionType: grant.permissionType ?? null, + baselinePermission, ...(applied === 'applied' ? { origin: 'directory' } : {}), updatedAt: new Date(), }, }) if (applied !== 'applied') continue - if (previousPermission) delta.raised.push(grant) + if (previousGrant?.permissionType) delta.raised.push(grant) else delta.added.push(grant) } diff --git a/apps/sim/ee/scim/lib/protocol/canonical.test.ts b/apps/sim/ee/scim/lib/protocol/canonical.test.ts index 5c86c21da36..f68375f8289 100644 --- a/apps/sim/ee/scim/lib/protocol/canonical.test.ts +++ b/apps/sim/ee/scim/lib/protocol/canonical.test.ts @@ -79,6 +79,14 @@ describe('toCanonicalUser', () => { expect(JSON.stringify(user)).not.toContain('hunter2') }) + it.each(['Password', 'urn:ietf:params:scim:schemas:core:2.0:User:password'])( + 'also strips the write-only password attribute %s', + (attribute) => { + const user = parseUser({ userName: 'ada@acme.test', [attribute]: 'synthetic-password' }) + expect(JSON.stringify(user)).not.toContain('synthetic-password') + } + ) + it('accepts Entra’s string boolean for active', () => { expect(parseUser({ userName: 'ada@acme.test', active: 'False' }).active).toBe(false) }) diff --git a/apps/sim/ee/scim/lib/protocol/canonical.ts b/apps/sim/ee/scim/lib/protocol/canonical.ts index d5d366e6201..a38f86a1f28 100644 --- a/apps/sim/ee/scim/lib/protocol/canonical.ts +++ b/apps/sim/ee/scim/lib/protocol/canonical.ts @@ -3,7 +3,7 @@ import { isValidEmailSyntax } from '@sim/utils/string' import type { ScimGroupWriteParsed, ScimUserWriteParsed } from '@/lib/api/contracts/scim' import { SCIM_ENTERPRISE_USER_SCHEMA } from '@/ee/scim/lib/protocol/constants' import { invalidValue } from '@/ee/scim/lib/protocol/errors' -import { isRecord } from '@/ee/scim/lib/protocol/normalize' +import { isRecord, isScimPasswordAttribute } from '@/ee/scim/lib/protocol/normalize' /** Attributes Sim models itself; everything else is preserved under `extra`. */ const MODELLED_USER_KEYS = new Set([ @@ -82,7 +82,7 @@ function formatName( function collectExtra(body: ScimUserWriteParsed): Record | undefined { const extra: Record = {} for (const [key, value] of Object.entries(body)) { - if (MODELLED_USER_KEYS.has(key.toLowerCase())) continue + if (MODELLED_USER_KEYS.has(key.toLowerCase()) || isScimPasswordAttribute(key)) continue extra[key] = value } return Object.keys(extra).length > 0 ? extra : undefined diff --git a/apps/sim/ee/scim/lib/protocol/filter.test.ts b/apps/sim/ee/scim/lib/protocol/filter.test.ts index 48736770cad..28b5224cc43 100644 --- a/apps/sim/ee/scim/lib/protocol/filter.test.ts +++ b/apps/sim/ee/scim/lib/protocol/filter.test.ts @@ -36,7 +36,16 @@ describe('parseUserFilter', () => { it('parses the work-email filtered path Entra sends', () => { expect(parseUserFilter('emails[type eq "work"].value eq "ada@acme.test"')).toEqual([ - { field: 'email', value: 'ada@acme.test' }, + { field: 'workEmail', value: 'ada@acme.test' }, + ]) + }) + + it('keeps all-email and primary-only matching distinct from work-email matching', () => { + expect(parseUserFilter('emails.value eq "ada@home.test"')).toEqual([ + { field: 'email', value: 'ada@home.test' }, + ]) + expect(parseUserFilter('emails[primary eq true].value eq "ada@home.test"')).toEqual([ + { field: 'primaryEmail', value: 'ada@home.test' }, ]) }) @@ -78,6 +87,11 @@ describe('parseUserFilter', () => { expect(parseUserFilter('active eq false')).toEqual([{ field: 'active', value: 'false' }]) }) + it('normalizes quoted boolean values and refuses other strings', () => { + expect(parseUserFilter('active eq "False"')).toEqual([{ field: 'active', value: 'false' }]) + expect(scimTypeOf(() => parseUserFilter('active eq "not-a-boolean"'))).toBe('invalidFilter') + }) + it('refuses an unquoted value', () => { expect(scimTypeOf(() => parseUserFilter('userName eq ada'))).toBe('invalidFilter') }) diff --git a/apps/sim/ee/scim/lib/protocol/filter.ts b/apps/sim/ee/scim/lib/protocol/filter.ts index 30b3c6bfbc8..e2270f7aa3b 100644 --- a/apps/sim/ee/scim/lib/protocol/filter.ts +++ b/apps/sim/ee/scim/lib/protocol/filter.ts @@ -1,6 +1,6 @@ import { SCIM_MAX_FILTER_TERMS } from '@/ee/scim/lib/protocol/constants' import { invalidFilter } from '@/ee/scim/lib/protocol/errors' -import { normalizeAttributePath } from '@/ee/scim/lib/protocol/normalize' +import { normalizeAttributePath, normalizeScimBoolean } from '@/ee/scim/lib/protocol/normalize' /** * The filter grammar this server accepts, which is the subset the provisioning @@ -19,7 +19,14 @@ import { normalizeAttributePath } from '@/ee/scim/lib/protocol/normalize' */ /** Attributes a User filter may name, mapped to the field the repository knows. */ -export type ScimUserFilterField = 'id' | 'userName' | 'externalId' | 'email' | 'active' +export type ScimUserFilterField = + | 'id' + | 'userName' + | 'externalId' + | 'email' + | 'workEmail' + | 'primaryEmail' + | 'active' /** Attributes a Group filter may name. */ export type ScimGroupFilterField = 'id' | 'displayName' | 'externalId' @@ -34,8 +41,8 @@ const USER_FILTER_FIELDS: Record = { username: 'userName', externalid: 'externalId', 'emails.value': 'email', - 'emails[type eq "work"].value': 'email', - 'emails[primary eq true].value': 'email', + 'emails[type eq "work"].value': 'workEmail', + 'emails[primary eq true].value': 'primaryEmail', active: 'active', } @@ -177,6 +184,13 @@ function parseTerm(term: string): { attribute: string; value: string } { throw invalidFilter('Filter values must be quoted strings') } + if (normalizeAttributePath(attribute).toLowerCase() === 'active') { + const active = normalizeScimBoolean(value) + if (typeof active !== 'boolean') + throw invalidFilter('active must be compared with true or false') + return { attribute, value: String(active) } + } + return { attribute, value } } diff --git a/apps/sim/ee/scim/lib/protocol/normalize.ts b/apps/sim/ee/scim/lib/protocol/normalize.ts index 7d22fc0d559..41e898aea2d 100644 --- a/apps/sim/ee/scim/lib/protocol/normalize.ts +++ b/apps/sim/ee/scim/lib/protocol/normalize.ts @@ -69,6 +69,11 @@ export function normalizeAttributePath(path: string): string { return value } +/** Passwords are write-only, including case variants and core-schema-qualified names. */ +export function isScimPasswordAttribute(path: string): boolean { + return normalizeAttributePath(path).toLowerCase() === 'password' +} + /** * Microsoft's classic schema markers, sent by older provisioning jobs alongside * the core URNs. They carry no attributes and are never stored or returned. diff --git a/apps/sim/ee/scim/lib/protocol/resources.test.ts b/apps/sim/ee/scim/lib/protocol/resources.test.ts index 42a4db8db4b..074562f49f2 100644 --- a/apps/sim/ee/scim/lib/protocol/resources.test.ts +++ b/apps/sim/ee/scim/lib/protocol/resources.test.ts @@ -2,7 +2,7 @@ * @vitest-environment node */ import { describe, expect, it } from 'vitest' -import { scimUserResourceSchema } from '@/lib/api/contracts/scim' +import { scimGroupResourceSchema, scimUserResourceSchema } from '@/lib/api/contracts/scim' import { SCIM_MAX_PAGE_SIZE } from '@/ee/scim/lib/protocol/constants' import type { ScimError } from '@/ee/scim/lib/protocol/errors' import { @@ -10,6 +10,7 @@ import { projectionWants, projectResource, resolvePage, + toGroupResource, toUserResource, } from '@/ee/scim/lib/protocol/resources' @@ -98,6 +99,28 @@ describe('toUserResource', () => { primary: true, }) }) + + it('never returns a password from legacy stored extra attributes', () => { + const base = userRow() + const resource = toUserResource( + { + ...base, + attributes: { + ...base.attributes, + extra: { + password: 'synthetic-password', + Password: 'synthetic-password', + 'urn:ietf:params:scim:schemas:core:2.0:User:password': 'synthetic-password', + title: 'Analyst', + }, + }, + }, + BASE_URL + ) + expect(resource.title).toBe('Analyst') + expect(JSON.stringify(resource)).not.toContain('synthetic-password') + expect(resource.schemas).toEqual(['urn:ietf:params:scim:schemas:core:2.0:User']) + }) }) describe('attribute projection', () => { @@ -124,6 +147,75 @@ describe('attribute projection', () => { expect(Object.keys(projected).sort()).toEqual(['id', 'meta', 'schemas', 'userName']) }) + it.each(['name.givenName', 'urn:ietf:params:scim:schemas:core:2.0:User:name.givenName'])( + 'returns the requested name sub-attribute %s', + (attributes) => { + const projected = projectResource( + toUserResource(userRow(), BASE_URL), + parseAttributeProjection({ attributes }) + ) + expect(projected.name).toEqual({ givenName: 'Ada' }) + expect(projected).not.toHaveProperty('emails') + expect(scimUserResourceSchema.safeParse(projected).success).toBe(true) + } + ) + + it('excludes a nested name attribute without dropping its siblings', () => { + const projected = projectResource( + toUserResource(userRow(), BASE_URL), + parseAttributeProjection({ excludedAttributes: 'name.formatted' }) + ) + expect(projected.name).toEqual({ givenName: 'Ada', familyName: 'Lovelace' }) + expect(scimUserResourceSchema.safeParse(projected).success).toBe(true) + }) + + it('projects each multi-valued entry and still loads requested group sub-attributes', () => { + const projection = parseAttributeProjection({ attributes: 'emails.value,groups.value' }) + const projected = projectResource(toUserResource(userRow(), BASE_URL), projection) + expect(projectionWants(projection, 'groups')).toBe(true) + expect(projected.emails).toEqual([{ value: 'ada@acme.test' }]) + expect(projected.groups).toEqual([{ value: 'g1' }]) + expect(scimUserResourceSchema.safeParse(projected).success).toBe(true) + }) + + it('projects group member sub-attributes through the response contract', () => { + const projection = parseAttributeProjection({ attributes: 'members.value' }) + const resource = toGroupResource( + { + id: 'g1', + externalId: null, + displayName: 'Engineering', + createdAt: new Date('2026-01-01T00:00:00.000Z'), + updatedAt: new Date('2026-01-01T00:00:00.000Z'), + members: [{ scimUserId: 'su1', displayName: 'Ada Lovelace' }], + }, + BASE_URL + ) + const projected = projectResource(resource, projection) + expect(projectionWants(projection, 'members')).toBe(true) + expect(projected.members).toEqual([{ value: 'su1' }]) + expect(scimGroupResourceSchema.safeParse(projected).success).toBe(true) + }) + + it('projects a schema-qualified extension attribute', () => { + const schema = 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' + const base = userRow() + const resource = toUserResource( + { + ...base, + attributes: { ...base.attributes, enterprise: { department: 'Maths', costCenter: '123' } }, + }, + BASE_URL + ) + const projected = projectResource( + resource, + parseAttributeProjection({ attributes: `${schema}:department` }) + ) + expect(projected[schema]).toEqual({ department: 'Maths' }) + expect(projected).not.toHaveProperty('name') + expect(scimUserResourceSchema.safeParse(projected).success).toBe(true) + }) + it('refuses combining an include list with an exclude list', () => { let scimType: string | undefined try { diff --git a/apps/sim/ee/scim/lib/protocol/resources.ts b/apps/sim/ee/scim/lib/protocol/resources.ts index 70a5e4a5513..28c159b63c3 100644 --- a/apps/sim/ee/scim/lib/protocol/resources.ts +++ b/apps/sim/ee/scim/lib/protocol/resources.ts @@ -7,6 +7,11 @@ import { SCIM_USER_SCHEMA, } from '@/ee/scim/lib/protocol/constants' import { invalidValue } from '@/ee/scim/lib/protocol/errors' +import { + isRecord, + isScimPasswordAttribute, + normalizeAttributePath, +} from '@/ee/scim/lib/protocol/normalize' export interface ScimResourceMeta { resourceType: 'User' | 'Group' @@ -75,6 +80,10 @@ export interface UserResourceRow { export function toUserResource(row: UserResourceRow, baseUrl: string): ScimUserResource { const stored = row.attributes const primaryType = stored.emails.find((entry) => entry.primary)?.type + const extra: Record = {} + for (const [attribute, value] of Object.entries(stored.extra ?? {})) { + if (!isScimPasswordAttribute(attribute)) extra[attribute] = value + } /** * The address comes from the Sim account rather than the stored resource. The @@ -97,9 +106,9 @@ export function toUserResource(row: UserResourceRow, baseUrl: string): ScimUserR schemas: [ SCIM_USER_SCHEMA, ...(stored.enterprise ? [SCIM_ENTERPRISE_USER_SCHEMA] : []), - ...Object.keys(stored.extra ?? {}).filter(isSchemaUrn), + ...Object.keys(extra).filter(isSchemaUrn), ], - ...(stored.extra ?? {}), + ...extra, id: row.id, ...(row.externalId ? { externalId: row.externalId } : {}), userName: row.userName, @@ -214,7 +223,14 @@ function parseAttributeList(value: string | undefined): Set | undefined if (!value) return undefined const names = value .split(',') - .map((name) => name.trim().toLowerCase()) + .map((name) => { + const normalized = normalizeAttributePath(name).toLowerCase() + if (normalized === 'enterprise') return SCIM_ENTERPRISE_USER_SCHEMA.toLowerCase() + if (normalized.startsWith('enterprise.')) { + return `${SCIM_ENTERPRISE_USER_SCHEMA.toLowerCase()}:${normalized.slice('enterprise.'.length)}` + } + return normalized + }) .filter(Boolean) return names.length > 0 ? new Set(names) : undefined } @@ -235,11 +251,15 @@ export function parseAttributeProjection(query: { export function projectionWants(projection: ScimAttributeProjection, attribute: string): boolean { const name = attribute.toLowerCase() if (projection.exclude?.has(name)) return false - if (projection.include) return projection.include.has(name) + if (projection.include) { + return [...projection.include].some( + (selected) => + selected === name || selected.startsWith(`${name}.`) || selected.startsWith(`${name}:`) + ) + } return true } -/** Attributes every resource keeps regardless of the projection requested. */ /** An `extra` key that is itself a schema URN carries a provider extension the resource must declare. */ function isSchemaUrn(key: string): boolean { return key.startsWith('urn:') @@ -247,6 +267,43 @@ function isSchemaUrn(key: string): boolean { const ALWAYS_RETURNED = new Set(['schemas', 'id', 'meta']) +/** Projects complex attributes and each entry of multi-valued attributes using RFC attribute paths. */ +function projectAttribute( + value: unknown, + path: string, + projection: ScimAttributeProjection, + inheritedInclude: boolean, + extensionRoot = false +): unknown { + if (projection.exclude?.has(path)) return undefined + const included = inheritedInclude || projection.include?.has(path) === true + const separator = extensionRoot ? ':' : '.' + if ( + !included && + projection.include && + ![...projection.include].some((selected) => selected.startsWith(`${path}${separator}`)) + ) { + return undefined + } + if (Array.isArray(value)) { + return value + .map((entry) => projectAttribute(entry, path, projection, included)) + .filter((entry) => entry !== undefined) + } + if (!isRecord(value)) return value + const projected: Record = {} + for (const [key, nested] of Object.entries(value)) { + const selected = projectAttribute( + nested, + `${path}${separator}${key.toLowerCase()}`, + projection, + included + ) + if (selected !== undefined) projected[key] = selected + } + return Object.keys(projected).length > 0 ? projected : undefined +} + /** Drops attributes the request did not ask for. */ export function projectResource( resource: Resource, @@ -260,7 +317,14 @@ export function projectResource( projected[key] = value continue } - if (projectionWants(projection, name)) projected[key] = value + const selected = projectAttribute( + value, + name, + projection, + !projection.include, + isSchemaUrn(name) + ) + if (selected !== undefined) projected[key] = selected } return projected as Resource } diff --git a/apps/sim/ee/scim/lib/protocol/user-patch.test.ts b/apps/sim/ee/scim/lib/protocol/user-patch.test.ts index a88095491b7..7e10da6c0da 100644 --- a/apps/sim/ee/scim/lib/protocol/user-patch.test.ts +++ b/apps/sim/ee/scim/lib/protocol/user-patch.test.ts @@ -8,9 +8,8 @@ import { SCIM_PATCH_OP_SCHEMA } from '@/ee/scim/lib/protocol/constants' import { applyUserPatch } from '@/ee/scim/lib/protocol/user-patch' /** - * Every fixture here is a request shape taken from Okta's or Microsoft's own - * provisioning documentation, not an invented one. The point of the test is that - * what those two products actually send is accepted. + * Covers RFC 7644 operation semantics and the request variants documented by + * Okta and Microsoft Entra. */ function baseUser(overrides: Partial = {}): ScimUserAttributes { @@ -169,6 +168,139 @@ describe('applyUserPatch', () => { expect(next.enterprise?.department).toBe('Maths') }) + it.each(['name', 'NAME', 'urn:ietf:params:scim:schemas:core:2.0:User:name'])( + 'updates the modelled name through the complex path %s', + (path) => { + const { next } = applyUserPatch( + baseUser(), + parseOperations([{ op: 'replace', path, value: { givenName: 'Augusta' } }]) + ) + expect(next.name).toEqual({ + givenName: 'Augusta', + familyName: 'Lovelace', + formatted: 'Augusta Lovelace', + }) + expect(next.extra?.name).toBeUndefined() + } + ) + + it('preserves an explicit formatted name in a complex name update', () => { + const { next } = applyUserPatch( + baseUser(), + parseOperations([ + { + op: 'add', + path: 'name', + value: { formatted: 'Countess Lovelace', givenName: 'Augusta' }, + }, + ]) + ) + expect(next.name).toEqual({ + givenName: 'Augusta', + familyName: 'Lovelace', + formatted: 'Countess Lovelace', + }) + }) + + it('updates a whole enterprise extension and preserves omitted attributes', () => { + const { next } = applyUserPatch( + baseUser({ enterprise: { department: 'Maths', employeeNumber: '123' } }), + parseOperations([ + { + op: 'replace', + path: 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User', + value: { department: 'Engineering' }, + }, + ]) + ) + expect(next.enterprise).toEqual({ department: 'Engineering', employeeNumber: '123' }) + expect(next.extra?.enterprise).toBeUndefined() + }) + + it.each([ + 'password', + 'Password', + 'urn:ietf:params:scim:schemas:core:2.0:User:password', + 'URN:IETF:PARAMS:SCIM:SCHEMAS:CORE:2.0:USER:PASSWORD', + ])('never stores the write-only password path %s', (path) => { + const original = baseUser() + const targeted = applyUserPatch( + original, + parseOperations([{ op: 'replace', path, value: 'synthetic-password' }]) + ) + const pathless = applyUserPatch( + original, + parseOperations([{ op: 'add', value: { [path]: 'synthetic-password' } }]) + ) + expect(targeted).toEqual({ next: original, changed: false }) + expect(pathless).toEqual({ next: original, changed: false }) + }) + + it('removes a previously persisted password when applying another update', () => { + const { next, changed } = applyUserPatch( + baseUser({ extra: { Password: 'synthetic-password', title: 'Analyst' } }), + parseOperations([{ op: 'replace', path: 'active', value: true }]) + ) + expect(changed).toBe(true) + expect(next.extra).toEqual({ title: 'Analyst' }) + }) + + it('updates a custom extension through Entra’s qualified attribute path', () => { + const schema = 'urn:ietf:params:scim:schemas:extension:CustomExtensionName:2.0:User' + const { next } = applyUserPatch( + baseUser({ extra: { [schema]: { tag: 'old', other: 'keep' } } }), + parseOperations([{ op: 'Replace', path: `${schema}:tag`, value: 'new' }]) + ) + expect(next.extra).toEqual({ [schema]: { tag: 'new', other: 'keep' } }) + }) + + it('adds a custom extension attribute on its first PATCH', () => { + const schema = 'urn:ietf:params:scim:schemas:extension:CustomExtensionName:2.0:User' + const { next } = applyUserPatch( + baseUser(), + parseOperations([{ op: 'add', path: `${schema}:tag`, value: 'new' }]) + ) + expect(next.extra).toEqual({ [schema]: { tag: 'new' } }) + }) + + it('merges a path-less custom extension then removes one nested attribute', () => { + const schema = 'urn:okta:sim:2.0:user:custom' + const { next } = applyUserPatch( + baseUser({ extra: { [schema]: { costCenter: 'R&D' } } }), + parseOperations([ + { op: 'replace', value: { [schema]: { department: 'Engineering' } } }, + { op: 'remove', path: `${schema}:costCenter` }, + ]) + ) + expect(next.extra?.[schema]).toEqual({ department: 'Engineering', costCenter: undefined }) + }) + + it('accepts a new extension object in a path-less PATCH', () => { + const schema = 'urn:okta:sim:2.0:user:custom' + const { next } = applyUserPatch( + baseUser(), + parseOperations([{ op: 'add', value: { [schema]: { costCenter: 'R&D' } } }]) + ) + expect(next.extra).toEqual({ [schema]: { costCenter: 'R&D' } }) + }) + + it('removes a custom extension by its exact schema path', () => { + const schema = 'urn:okta:sim:2.0:user:custom' + const { next } = applyUserPatch( + baseUser({ extra: { [schema]: { costCenter: 'R&D' }, title: 'Analyst' } }), + parseOperations([{ op: 'remove', path: schema }]) + ) + expect(next.extra).toEqual({ title: 'Analyst' }) + }) + + it('removes only the addressed sub-attribute of a typed complex attribute', () => { + const { next } = applyUserPatch( + baseUser({ extra: { addresses: [{ type: 'work', locality: 'London', country: 'GB' }] } }), + parseOperations([{ op: 'remove', path: 'addresses[type eq "work"].locality' }]) + ) + expect(next.extra?.addresses).toEqual([{ type: 'work', locality: undefined, country: 'GB' }]) + }) + it('reports no change when a patch re-sends what is already stored', () => { const { changed } = applyUserPatch( baseUser(), diff --git a/apps/sim/ee/scim/lib/protocol/user-patch.ts b/apps/sim/ee/scim/lib/protocol/user-patch.ts index ce97b1459f6..073995f69b0 100644 --- a/apps/sim/ee/scim/lib/protocol/user-patch.ts +++ b/apps/sim/ee/scim/lib/protocol/user-patch.ts @@ -3,6 +3,7 @@ import type { ScimPatchOperation } from '@/lib/api/contracts/scim' import { invalidPath, invalidValue, mutability, noTarget } from '@/ee/scim/lib/protocol/errors' import { isRecord, + isScimPasswordAttribute, normalizeAttributePath, normalizeScimBoolean, unwrapSingleElement, @@ -113,7 +114,8 @@ function applyOperation( user: ScimUserAttributes, op: 'add' | 'replace' | 'remove', rawPath: string, - value: unknown + value: unknown, + resourceAttribute = false ): void { const path = normalizeAttributePath(rawPath) const key = path.toLowerCase() @@ -135,6 +137,23 @@ function applyOperation( } switch (key) { + case 'password': + return + + case 'name': + case 'enterprise': { + if (op === 'remove') { + if (key === 'name') user.name = { formatted: user.userName } + else user.enterprise = undefined + return + } + if (!isRecord(value)) throw invalidValue(`${path} requires an object value`) + for (const [sub, nested] of sortFormattedLast(Object.entries(value))) { + applyOperation(user, op, `${path}.${sub}`, nested) + } + return + } + case 'active': user.active = op === 'remove' ? true : requireBoolean(value, 'active') return @@ -247,13 +266,41 @@ function applyOperation( default: if (key.startsWith('meta')) throw mutability(`${rawPath} is read-only`) - applyExtraOperation(user, op, path, value) + applyExtraOperation(user, op, path, value, resourceAttribute) } } /** `attr`, `attr.sub`, or `attr[type eq "x"].sub` on an attribute Sim does not model. */ const EXTRA_PATH_PATTERN = - /^(?[A-Za-z][\w-]*)(?:\[\s*type\s+eq\s+(?"|')?(?[^"'\]]+)\k?\s*\])?(?:\.(?[A-Za-z][\w-]*))?$/ + /^(?[A-Za-z][\w-]*)(?:\[\s*type\s+eq\s+(?"|')?(?[^"'\]]+)\k?\s*\])?(?:\.(?[A-Za-z][\w-]*))?$/i + +/** Uses the resource's schema keys to distinguish an extension from one of its attributes. */ +function extensionTarget( + extra: Record, + path: string, + resourceAttribute: boolean, + value: unknown +): { schema: string; attribute?: string } | undefined { + if (!path.toLowerCase().startsWith('urn:')) return undefined + const lowered = path.toLowerCase() + const existing = Object.keys(extra) + .filter( + (schema) => + schema.toLowerCase().startsWith('urn:') && + (lowered === schema.toLowerCase() || lowered.startsWith(`${schema.toLowerCase()}:`)) + ) + .sort((left, right) => right.length - left.length)[0] + if (existing) { + return { + schema: existing, + ...(path.length > existing.length ? { attribute: path.slice(existing.length + 1) } : {}), + } + } + if (resourceAttribute && isRecord(value)) return { schema: path } + const separator = path.lastIndexOf(':') + if (separator <= 'urn:'.length) throw invalidPath(`User PATCH path ${path} is not supported`) + return { schema: path.slice(0, separator), attribute: path.slice(separator + 1) } +} /** * Applies an operation to an attribute Sim does not model. @@ -268,29 +315,63 @@ function applyExtraOperation( user: ScimUserAttributes, op: 'add' | 'replace' | 'remove', path: string, + value: unknown, + resourceAttribute: boolean +): void { + user.extra ??= {} + const extension = extensionTarget(user.extra, path, resourceAttribute, value) + if (extension) { + if (!extension.attribute) { + if (op === 'remove') delete user.extra[extension.schema] + else { + if (!isRecord(value)) throw invalidValue(`${path} requires an object value`) + const current = user.extra[extension.schema] + user.extra[extension.schema] = { ...(isRecord(current) ? current : {}), ...value } + } + return + } + const current = user.extra[extension.schema] + const attributes = isRecord(current) ? { ...current } : {} + applyExtraAttribute(attributes, op, extension.attribute, value) + user.extra[extension.schema] = attributes + return + } + applyExtraAttribute(user.extra, op, path, value) +} + +/** Applies a simple or typed complex path inside either the core resource or an extension. */ +function applyExtraAttribute( + attributes: Record, + op: 'add' | 'replace' | 'remove', + path: string, value: unknown ): void { const match = path.match(EXTRA_PATH_PATTERN) if (!match?.groups) throw invalidPath(`User PATCH path ${path} is not supported`) - const { attribute, type, sub } = match.groups - user.extra ??= {} + const { type, sub } = match.groups + const attribute = + Object.keys(attributes).find( + (key) => key.toLowerCase() === match.groups?.attribute.toLowerCase() + ) ?? match.groups.attribute if (!type && !sub) { - if (op === 'remove') user.extra[attribute] = undefined - else user.extra[attribute] = value + if (op === 'remove') attributes[attribute] = undefined + else attributes[attribute] = value return } if (type) { - const list = Array.isArray(user.extra[attribute]) ? [...user.extra[attribute]] : [] + const list = Array.isArray(attributes[attribute]) ? [...attributes[attribute]] : [] const index = list.findIndex( (entry) => isRecord(entry) && String(entry.type).toLowerCase() === type.toLowerCase() ) - if (op === 'remove') { + if (op === 'remove' && !sub) { if (index !== -1) list.splice(index, 1) } else if (sub) { + if (op === 'remove' && index === -1) return const current = index !== -1 && isRecord(list[index]) ? list[index] : { type } - const next = { ...current, [sub]: value } + const key = Object.keys(current).find((key) => key.toLowerCase() === sub.toLowerCase()) ?? sub + const next = { ...current, [key]: op === 'remove' ? undefined : value } if (index === -1) list.push(next) else list[index] = next } else if (isRecord(value)) { @@ -299,14 +380,14 @@ function applyExtraOperation( } else { throw invalidValue(`${path} requires an object value`) } - user.extra[attribute] = list + attributes[attribute] = list return } - const current = isRecord(user.extra[attribute]) ? { ...user.extra[attribute] } : {} - if (op === 'remove') current[sub as string] = undefined - else current[sub as string] = value - user.extra[attribute] = current + const current = isRecord(attributes[attribute]) ? { ...attributes[attribute] } : {} + const key = Object.keys(current).find((key) => key.toLowerCase() === sub.toLowerCase()) ?? sub + current[key] = op === 'remove' ? undefined : value + attributes[attribute] = current } /** @@ -355,6 +436,11 @@ export function applyUserPatch( operations: readonly ScimPatchOperation[] ): UserPatchOutcome { const next = structuredClone(current) + if (next.extra) { + for (const attribute of Object.keys(next.extra)) { + if (isScimPasswordAttribute(attribute)) delete next.extra[attribute] + } + } for (const operation of operations) { if (operation.op === 'remove' && !operation.path) { @@ -372,19 +458,7 @@ export function applyUserPatch( * arrived as its own operation. */ for (const [attribute, nested] of sortFormattedLast(Object.entries(value))) { - /** - * RFC 7644's canonical form nests complex attributes — `{"name": {"givenName": …}}` - * and the enterprise extension keyed by its URN — so each sub-attribute is - * dispatched by its dotted path. - */ - const normalized = normalizeAttributePath(attribute).toLowerCase() - if (isRecord(nested) && (normalized === 'name' || normalized === 'enterprise')) { - for (const [sub, subValue] of sortFormattedLast(Object.entries(nested))) { - applyOperation(next, operation.op, `${normalized}.${sub}`, subValue) - } - continue - } - applyOperation(next, operation.op, attribute, nested) + applyOperation(next, operation.op, attribute, nested, true) } continue } diff --git a/apps/sim/ee/scim/lib/reconcile/job.test.ts b/apps/sim/ee/scim/lib/reconcile/job.test.ts index e06c7d24c32..4c154190c82 100644 --- a/apps/sim/ee/scim/lib/reconcile/job.test.ts +++ b/apps/sim/ee/scim/lib/reconcile/job.test.ts @@ -11,8 +11,22 @@ const mocks = vi.hoisted(() => ({ reconcileBatch: vi.fn(), listScimUserIds: vi.fn(), prune: vi.fn(), + acquireLock: vi.fn(), + listGroups: vi.fn(), + autoMap: vi.fn(), + settleGroups: vi.fn(), })) +vi.mock('@/lib/billing/organizations/membership', () => ({ + acquireOrganizationMutationLock: mocks.acquireLock, +})) +vi.mock('@/ee/scim/lib/projection/auto-map', () => ({ + autoMapPermissionGroupByName: mocks.autoMap, + settleMappedPermissionGroupsExplicit: mocks.settleGroups, +})) +vi.mock('@/ee/scim/lib/repository/groups', () => ({ + listScimGroupsForReconcile: mocks.listGroups, +})) vi.mock('@sim/utils/id', () => ({ generateId: () => 'run-1' })) vi.mock('@/ee/scim/lib/entitlement', () => ({ isScimEntitledForOrganization: mocks.isEntitled, @@ -79,6 +93,8 @@ describe('reconcileConnection', () => { mocks.prune.mockResolvedValue(undefined) mocks.reconcileBatch.mockResolvedValue(delta()) mocks.listScimUserIds.mockResolvedValue([]) + mocks.listGroups.mockResolvedValue([]) + mocks.autoMap.mockResolvedValue('mapped') }) afterEach(() => { @@ -174,6 +190,48 @@ describe('reconcileConnection', () => { }) }) + it('matches pre-existing groups before projecting users when automatic matching is enabled', async () => { + grantLease() + const settings = { autoMapPermissionGroupsByName: true } + const groups = [{ id: 'group-1', displayName: 'Engineering', orderKey: 'group-key-1' }] + mocks.listGroups.mockResolvedValueOnce(groups).mockResolvedValueOnce([]) + queueTableRows(scimConnection, [{ status: 'active', token: 'run-1', settings }]) + queueTableRows(scimConnection, [{ status: 'active', token: 'run-1', settings }]) + mocks.listScimUserIds.mockResolvedValueOnce(page(['su-1'])).mockResolvedValueOnce([]) + stageBatch('run-1', settings) + + await reconcileConnection({ ...connection, settings }) + + expect(mocks.autoMap).toHaveBeenCalledWith(db, { + organizationId: 'org-1', + scimGroupId: 'group-1', + displayName: 'Engineering', + }) + expect(mocks.listGroups).toHaveBeenNthCalledWith(2, db, { + connectionId: 'conn-1', + afterOrderKey: 'group-key-1', + limit: 25, + }) + expect(mocks.settleGroups).toHaveBeenCalledWith(db, { + organizationId: 'org-1', + scimGroupId: 'group-1', + }) + expect(mocks.autoMap.mock.invocationCallOrder[0]).toBeLessThan( + mocks.reconcileBatch.mock.invocationCallOrder[0] + ) + }) + + it('stops automatic matching when the rule was disabled after the pass was queued', async () => { + grantLease() + queueTableRows(scimConnection, [{ status: 'active', token: 'run-1', settings: {} }]) + await reconcileConnection({ + ...connection, + settings: { autoMapPermissionGroupsByName: true }, + }) + expect(mocks.listGroups).not.toHaveBeenCalled() + expect(mocks.autoMap).not.toHaveBeenCalled() + }) + it('falls back to the settings the due query returned when the row cannot be re-read', async () => { grantLease() mocks.listScimUserIds.mockResolvedValueOnce(page(['su-1'])).mockResolvedValueOnce([]) diff --git a/apps/sim/ee/scim/lib/reconcile/job.ts b/apps/sim/ee/scim/lib/reconcile/job.ts index de6973e71ce..18e44d5ba1d 100644 --- a/apps/sim/ee/scim/lib/reconcile/job.ts +++ b/apps/sim/ee/scim/lib/reconcile/job.ts @@ -3,11 +3,17 @@ import { type ScimConnectionSettings, scimConnection } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { generateId } from '@sim/utils/id' import { and, eq, isNull, lt, or, sql } from 'drizzle-orm' +import { acquireOrganizationMutationLock } from '@/lib/billing/organizations/membership' import { isScimEntitledForOrganization } from '@/ee/scim/lib/entitlement' +import { + autoMapPermissionGroupByName, + settleMappedPermissionGroupsExplicit, +} from '@/ee/scim/lib/projection/auto-map' import { PROJECTION_BATCH_SIZE, reconcileUsersProjectionInBatches, } from '@/ee/scim/lib/projection/reconcile-user' +import { listScimGroupsForReconcile } from '@/ee/scim/lib/repository/groups' import { listScimUserIds } from '@/ee/scim/lib/repository/users' import { pruneScimRequestLog } from '@/ee/scim/lib/request-log' @@ -37,11 +43,6 @@ const LEASE_TTL_MS = 15 * 60 * 1000 */ const RECONCILE_INTERVAL_MS = 50 * 60 * 1000 -/** - * Users reconciled per transaction. The organization lock is held for the whole - * batch, so it is kept small enough that a tenant's own writes never wait long. - */ - export interface ScimReconcileReport { connectionId: string reconciledUsers: number @@ -79,11 +80,58 @@ async function holdsLease(connectionId: string, runId: string): Promise const [row] = await db .select({ token: scimConnection.reconcileLockToken }) .from(scimConnection) - .where(eq(scimConnection.id, connectionId)) + .where(and(eq(scimConnection.id, connectionId), eq(scimConnection.status, 'active'))) .limit(1) return row?.token === runId } +/** Matches existing groups before projecting users, so enabling matching does not require a directory rename. */ +async function reconcileExistingGroupNames( + connection: { id: string; organizationId: string }, + runId: string +): Promise { + let cursor: string | undefined + for (;;) { + const batch = await db.transaction(async (tx) => { + await acquireOrganizationMutationLock(tx, connection.organizationId) + const [fresh] = await tx + .select({ + status: scimConnection.status, + token: scimConnection.reconcileLockToken, + settings: scimConnection.settings, + }) + .from(scimConnection) + .where(eq(scimConnection.id, connection.id)) + .limit(1) + if (fresh?.status !== 'active' || fresh.token !== runId) return { stopped: true } + if (!fresh.settings.autoMapPermissionGroupsByName) return { stopped: false } + + const groups = await listScimGroupsForReconcile(tx, { + connectionId: connection.id, + afterOrderKey: cursor, + limit: PROJECTION_BATCH_SIZE, + }) + for (const group of groups) { + const mapped = await autoMapPermissionGroupByName(tx, { + organizationId: connection.organizationId, + scimGroupId: group.id, + displayName: group.displayName, + }) + if (mapped === 'mapped') { + await settleMappedPermissionGroupsExplicit(tx, { + organizationId: connection.organizationId, + scimGroupId: group.id, + }) + } + } + return { stopped: false, cursor: groups.at(-1)?.orderKey } + }) + if (batch.stopped) return false + if (!batch.cursor) return true + cursor = batch.cursor + } +} + /** Releases the lease; the watermark advances only when the pass finished, so a failed batch is retried next hour. */ async function releaseLease( connectionId: string, @@ -151,6 +199,12 @@ export async function reconcileConnection(connection: { try { /** Pruned before the pass, so a connection whose pass keeps failing still keeps its log bounded. */ await pruneScimRequestLog(connection.id) + if ( + connection.settings.autoMapPermissionGroupsByName && + !(await reconcileExistingGroupNames(connection, runId)) + ) { + return null + } let cursor: string | undefined for (;;) { const page = await listScimUserIds(db, { diff --git a/apps/sim/ee/scim/lib/repository/groups.ts b/apps/sim/ee/scim/lib/repository/groups.ts index 5f381d071c8..a9bdc1aae84 100644 --- a/apps/sim/ee/scim/lib/repository/groups.ts +++ b/apps/sim/ee/scim/lib/repository/groups.ts @@ -1,7 +1,7 @@ import { scimGroup, scimGroupMember, scimUser } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { generateId } from '@sim/utils/id' -import { and, asc, count, eq, inArray, type SQL, sql } from 'drizzle-orm' +import { and, asc, count, eq, gt, inArray, type SQL, sql } from 'drizzle-orm' import type { DbOrTx } from '@/lib/db/types' import type { ScimFilterTerm, ScimGroupFilterField } from '@/ee/scim/lib/protocol/filter' import { buildOrderKey } from '@/ee/scim/lib/repository/users' @@ -53,6 +53,24 @@ export async function findScimGroupById( return row ?? null } +/** Stable, bounded pages for remapping groups that arrived before automatic matching was enabled. */ +export async function listScimGroupsForReconcile( + tx: DbOrTx, + params: { connectionId: string; afterOrderKey?: string; limit: number } +): Promise> { + return tx + .select({ id: scimGroup.id, displayName: scimGroup.displayName, orderKey: scimGroup.orderKey }) + .from(scimGroup) + .where( + and( + eq(scimGroup.connectionId, params.connectionId), + params.afterOrderKey ? gt(scimGroup.orderKey, params.afterOrderKey) : undefined + ) + ) + .orderBy(asc(scimGroup.orderKey)) + .limit(params.limit) +} + export async function pageScimGroups( tx: DbOrTx, params: { diff --git a/apps/sim/ee/scim/lib/repository/users.ts b/apps/sim/ee/scim/lib/repository/users.ts index 6f440b0c5ca..fc44fcc4e78 100644 --- a/apps/sim/ee/scim/lib/repository/users.ts +++ b/apps/sim/ee/scim/lib/repository/users.ts @@ -36,10 +36,31 @@ function userFilterCondition(term: ScimFilterTerm): SQL | u return eq(scimUser.userName, term.value.toLowerCase()) case 'externalId': return eq(scimUser.externalId, term.value) - case 'email': + case 'primaryEmail': return sql`lower(trim(${user.email})) = ${normalizeEmail(term.value)}` + case 'email': + case 'workEmail': { + const address = normalizeEmail(term.value) + const matchesStoredEmail = sql`exists ( + select 1 from jsonb_array_elements(${scimUser.attributes} -> 'emails') as stored_email(item) + where ${term.field === 'workEmail' ? sql`lower(stored_email.item ->> 'type') = 'work' and` : sql``} + ( + (stored_email.item ->> 'primary' = 'true' and lower(trim(${user.email})) = ${address}) + or ( + stored_email.item ->> 'primary' is distinct from 'true' + and lower(trim(stored_email.item ->> 'value')) <> lower(trim(${user.email})) + and lower(trim(stored_email.item ->> 'value')) = ${address} + ) + ) + )` + return term.field === 'email' + ? sql`(lower(trim(${user.email})) = ${address} or ${matchesStoredEmail})` + : matchesStoredEmail + } case 'active': - return eq(scimUser.active, term.value.toLowerCase() === 'true') + return term.value.toLowerCase() === 'true' + ? sql`(${scimUser.active} = true and ${user.suspendedAt} is null)` + : sql`(${scimUser.active} = false or ${user.suspendedAt} is not null)` } } diff --git a/apps/sim/ee/sso/components/sso-provider-settings.tsx b/apps/sim/ee/sso/components/sso-provider-settings.tsx new file mode 100644 index 00000000000..7b214ed77cf --- /dev/null +++ b/apps/sim/ee/sso/components/sso-provider-settings.tsx @@ -0,0 +1,1131 @@ +'use client' + +import { useState } from 'react' +import { + Button, + Chip, + ChipCombobox, + ChipCopyInput, + ChipInput, + ChipSelect, + ChipSwitch, + ChipTextarea, + Expandable, + ExpandableContent, + Switch, + toast, +} from '@sim/emcn' +import { ChevronDown, Eye, EyeOff } from '@sim/emcn/icons' +import { createLogger } from '@sim/logger' +import { getErrorMessage } from '@sim/utils/errors' +import { saveDiscardActions } from '@/components/settings/save-discard-actions' +import type { SettingsAction } from '@/components/settings/settings-header' +import type { SsoProviderView, SsoRegistrationBody } from '@/lib/api/contracts/auth' +import { REDACTED_MARKER } from '@/lib/core/security/redaction' +import { getBaseUrl } from '@/lib/core/utils/urls' +import { SettingsPanel } from '@/app/workspace/[workspaceId]/settings/components/settings-panel' +import { SettingsSection } from '@/app/workspace/[workspaceId]/settings/components/settings-section/settings-section' +import { useSettingsUnsavedGuard } from '@/app/workspace/[workspaceId]/settings/hooks/use-settings-unsaved-guard' +import { SettingRow } from '@/ee/components/setting-row' +import { SSO_TRUSTED_PROVIDERS } from '@/ee/sso/constants' +import { useConfigureSSO } from '@/ee/sso/hooks/sso' + +const logger = createLogger('SSO') + +/** Claim names each protocol uses out of the box; shown as input placeholders. */ +const OIDC_DEFAULT_MAPPING = { id: 'sub', email: 'email', name: 'name', image: 'picture' } as const +const SAML_DEFAULT_MAPPING = { + id: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier', + email: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', + name: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', +} as const + +const SAML_NAMEID_FORMATS = [ + { label: 'Provider default', value: '' }, + { + label: 'Email address', + value: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', + }, + { label: 'Persistent', value: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent' }, + { label: 'Transient', value: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient' }, + { label: 'Unspecified', value: 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified' }, +] as const + +const PROVIDER_ID_SUGGESTIONS = SSO_TRUSTED_PROVIDERS.map((id) => ({ label: id, value: id })) + +const CLIENT_SECRET_FIELD_ID = 'sso-client-secret' +/** Fixed width, so the mask never leaks how long the stored secret is. */ +const CLIENT_SECRET_MASK = '••••••••••••' + +interface ClientSecretFieldProps { + /** A secret is already saved, so the field opens as a masked fact rather than an input. */ + hasStoredSecret: boolean + /** Last four characters of the saved secret, when the API judged it safe to hint. */ + storedHint: string | null + isReplacing: boolean + onReplace: () => void + onCancelReplace: () => void + value: string + onChange: (value: string) => void + hasError: boolean +} + +/** + * A saved client secret is a fact, not an editable value — the browser never + * receives it. Rendering it as a static masked row with an explicit Replace + * action avoids the "will blank clear it?" ambiguity an empty input invites, and + * keeps a stray keystroke from arming a replacement. + */ +function ClientSecretField({ + hasStoredSecret, + storedHint, + isReplacing, + onReplace, + onCancelReplace, + value, + onChange, + hasError, +}: ClientSecretFieldProps) { + const [isRevealed, setIsRevealed] = useState(false) + + if (hasStoredSecret && !isReplacing) { + return ( +
    + + Replace +
    + ) + } + + return ( +
    + { + e.target.removeAttribute('readOnly') + setIsRevealed(true) + }} + onBlurCapture={() => setIsRevealed(false)} + onChange={(e) => onChange(e.target.value)} + inputClassName={!isRevealed ? '[-webkit-text-security:disc]' : undefined} + error={hasError} + endAdornment={ + value ? ( + + ) : undefined + } + /> + {/** Not "Cancel" — the header already owns that label for discarding the + whole edit, and these two do very different things. */} + {hasStoredSecret && Keep saved} +
    + ) +} + +/** Reads the display-only hint the API attaches beside the redacted client secret. */ +function readClientSecretHint(oidcConfig?: string | null): string | null { + if (!oidcConfig) return null + try { + const hint = JSON.parse(oidcConfig).clientSecretHint + return typeof hint === 'string' ? hint : null + } catch { + return null + } +} + +const DEFAULT_FORM_DATA = { + providerType: 'oidc' as 'oidc' | 'saml', + providerId: '', + issuerUrl: '', + domain: '', + clientId: '', + clientSecret: '', + scopes: 'openid,profile,email', + entryPoint: '', + cert: '', + callbackUrl: '', + audience: '', + wantAssertionsSigned: true, + idpMetadata: '', + mapId: '', + mapEmail: '', + mapName: '', + identifierFormat: '', + authorizationEndpoint: '', + tokenEndpoint: '', + jwksEndpoint: '', + jitProvisioningEnabled: true, +} + +interface SsoProviderSettingsProps { + organizationId: string + existingProvider?: SsoProviderView + active: boolean + onOpenDomains: () => void +} + +export function SsoProviderSettings({ + organizationId, + existingProvider, + active, + onOpenDomains, +}: SsoProviderSettingsProps) { + const existingJitProvisioningEnabled = existingProvider?.jitProvisioningEnabled ?? true + const configureSSOMutation = useConfigureSSO() + + const [isEditing, setIsEditing] = useState(false) + const [showAdvanced, setShowAdvanced] = useState(false) + const [showMapping, setShowMapping] = useState(false) + + const [formData, setFormData] = useState(DEFAULT_FORM_DATA) + const [originalFormData, setOriginalFormData] = useState(DEFAULT_FORM_DATA) + const [showErrors, setShowErrors] = useState(false) + + const [isReplacingClientSecret, setIsReplacingClientSecret] = useState(false) + + /** + * Editing an OIDC provider always means a secret is stored — the contract + * requires one to register, and the API returns only its sentinel, never the + * value. Leaving the field blank therefore means "keep it", not "clear it". + */ + const hasStoredClientSecret = isEditing && existingProvider?.providerType === 'oidc' + /** Last four characters of the saved secret, when the API judged it safe to hint. */ + const storedClientSecretHint = hasStoredClientSecret + ? readClientSecretHint(existingProvider?.oidcConfig) + : null + + const hasChanges = (Object.keys(formData) as (keyof typeof formData)[]).some( + (k) => formData[k] !== originalFormData[k] + ) + + useSettingsUnsavedGuard({ isDirty: hasChanges }) + + const validateProviderId = (value: string): string[] => { + if (!value || !value.trim()) return ['Provider ID is required.'] + if (!/^[-a-z0-9]+$/i.test(value.trim())) return ['Use letters, numbers, and dashes only.'] + return [] + } + + const validateIssuerUrl = (value: string): string[] => { + const out: string[] = [] + if (!value || !value.trim()) return ['Issuer URL is required.'] + try { + const url = new URL(value.trim()) + const isLocalhost = url.hostname === 'localhost' || url.hostname === '127.0.0.1' + if (url.protocol !== 'https:' && !isLocalhost) { + out.push('Issuer URL must use HTTPS.') + } + } catch { + out.push('Enter a valid issuer URL like https://your-identity-provider.com/oauth2/default') + } + return out + } + + const validateDomain = (value: string): string[] => { + const out: string[] = [] + if (!value || !value.trim()) return ['Domain is required.'] + if (/^https?:\/\//i.test(value.trim())) out.push('Do not include protocol (https://).') + if (!/^[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(value.trim())) + out.push('Enter a valid domain like company.com') + return out + } + + const validateRequired = (label: string, value: string): string[] => { + const out: string[] = [] + if (!value || !value.trim()) out.push(`${label} is required.`) + return out + } + + const validateAll = (data: typeof formData) => { + const newErrors: Record = { + providerType: [], + providerId: validateProviderId(data.providerId), + issuerUrl: validateIssuerUrl(data.issuerUrl), + domain: validateDomain(data.domain), + clientId: [], + clientSecret: [], + entryPoint: [], + cert: [], + scopes: [], + callbackUrl: [], + audience: [], + } + + const providerType = data.providerType || 'oidc' + + if (providerType === 'oidc') { + newErrors.clientId = validateRequired('Client ID', data.clientId) + /** Skipped only while the stored secret is being kept. Once Replace is clicked the field is a real input again, so a blank or whitespace-only value has to fail rather than quietly overwrite a working secret. */ + newErrors.clientSecret = + hasStoredClientSecret && !isReplacingClientSecret + ? [] + : validateRequired('Client Secret', data.clientSecret) + if (!data.scopes || !data.scopes.trim()) { + newErrors.scopes = ['Scopes are required for OIDC providers'] + } + } else if (providerType === 'saml') { + newErrors.entryPoint = validateIssuerUrl(data.entryPoint || '') + if (!newErrors.entryPoint.length && !data.entryPoint) { + newErrors.entryPoint = ['Entry Point URL is required for SAML providers'] + } + newErrors.cert = validateRequired('Certificate', data.cert) + } + + return newErrors + } + + const errors = validateAll(formData) + + const hasAnyErrors = (errs: Record) => + Object.values(errs).some((l) => l.length > 0) + + const handleDiscard = () => { + setIsEditing(false) + setFormData(DEFAULT_FORM_DATA) + setOriginalFormData(DEFAULT_FORM_DATA) + setShowErrors(false) + setShowAdvanced(false) + setShowMapping(false) + setIsReplacingClientSecret(false) + } + + const handleSubmit = async (e?: React.FormEvent) => { + e?.preventDefault() + + setShowErrors(true) + const validation = validateAll(formData) + if (hasAnyErrors(validation)) { + if (validation.scopes.length > 0) setShowAdvanced(true) + return + } + + try { + const providerType = formData.providerType || 'oidc' + + const requestBody: SsoRegistrationBody = + providerType === 'oidc' + ? { + providerType: 'oidc', + providerId: formData.providerId, + issuer: formData.issuerUrl, + domain: formData.domain, + orgId: organizationId, + jitProvisioningEnabled: formData.jitProvisioningEnabled, + mapping: { + id: formData.mapId.trim() || OIDC_DEFAULT_MAPPING.id, + email: formData.mapEmail.trim() || OIDC_DEFAULT_MAPPING.email, + name: formData.mapName.trim() || OIDC_DEFAULT_MAPPING.name, + image: OIDC_DEFAULT_MAPPING.image, + }, + clientId: formData.clientId, + /** Blank on an edit means the admin did not retype it: send the sentinel so the server keeps the stored secret. Trimmed because a pasted secret often carries a trailing newline, and because a whitespace-only value must never be stored as the secret. */ + clientSecret: + hasStoredClientSecret && !formData.clientSecret.trim() + ? REDACTED_MARKER + : formData.clientSecret.trim(), + scopes: formData.scopes.split(',').map((s) => s.trim()), + ...(formData.authorizationEndpoint.trim() + ? { authorizationEndpoint: formData.authorizationEndpoint.trim() } + : {}), + ...(formData.tokenEndpoint.trim() + ? { tokenEndpoint: formData.tokenEndpoint.trim() } + : {}), + ...(formData.jwksEndpoint.trim() + ? { jwksEndpoint: formData.jwksEndpoint.trim() } + : {}), + } + : { + providerType: 'saml', + providerId: formData.providerId, + issuer: formData.issuerUrl, + domain: formData.domain, + orgId: organizationId, + jitProvisioningEnabled: formData.jitProvisioningEnabled, + mapping: { + id: formData.mapId.trim() || SAML_DEFAULT_MAPPING.id, + email: formData.mapEmail.trim() || SAML_DEFAULT_MAPPING.email, + name: formData.mapName.trim() || SAML_DEFAULT_MAPPING.name, + }, + entryPoint: formData.entryPoint, + cert: formData.cert, + wantAssertionsSigned: formData.wantAssertionsSigned, + ...(formData.callbackUrl ? { callbackUrl: formData.callbackUrl } : {}), + ...(formData.audience ? { audience: formData.audience } : {}), + ...(formData.idpMetadata ? { idpMetadata: formData.idpMetadata } : {}), + identifierFormat: formData.identifierFormat, + } + + await configureSSOMutation.mutateAsync(requestBody) + + logger.info('SSO provider configured', { providerId: formData.providerId }) + toast.success(isEditing ? 'SSO provider updated' : 'SSO provider configured') + setFormData(DEFAULT_FORM_DATA) + setOriginalFormData(DEFAULT_FORM_DATA) + setShowErrors(false) + setIsEditing(false) + setShowAdvanced(false) + setIsReplacingClientSecret(false) + } catch (err) { + const message = getErrorMessage(err, 'Unknown error occurred') + toast.error(message) + logger.error('Failed to configure SSO provider', { error: err }) + } + } + + const handleInputChange = (field: keyof typeof formData, value: string | boolean) => { + const next = { ...formData, [field]: value } + /** Claim names are protocol-specific, so an override must not survive a switch. */ + if (field === 'providerType') { + next.mapId = '' + next.mapEmail = '' + next.mapName = '' + setShowErrors(false) + } + + setFormData(next) + } + + const handleKeepSavedSecret = () => { + setIsReplacingClientSecret(false) + setFormData({ ...formData, clientSecret: '' }) + } + + const isSaml = formData.providerType === 'saml' + const mappingDefaults = isSaml ? SAML_DEFAULT_MAPPING : OIDC_DEFAULT_MAPPING + const callbackUrl = `${getBaseUrl()}/api/auth/${isSaml ? 'sso/saml2/callback' : 'sso/callback'}/${formData.providerId || existingProvider?.providerId || 'provider-id'}` + + const handleEdit = () => { + if (!existingProvider) return + + try { + let clientId = '' + let clientSecret = '' + let scopes = 'openid,profile,email' + let entryPoint = '' + let cert = '' + let callbackUrl = '' + let audience = '' + let wantAssertionsSigned = true + let idpMetadata = '' + /** Blank means "use the protocol default", so only carry over a stored value that differs — otherwise editing rewrites a default as an explicit override. */ + let mapping: { id?: string; email?: string; name?: string } = {} + let identifierFormat = '' + let authorizationEndpoint = '' + let tokenEndpoint = '' + let jwksEndpoint = '' + + if (existingProvider.providerType === 'oidc' && existingProvider.oidcConfig) { + const config = JSON.parse(existingProvider.oidcConfig) + clientId = config.clientId || '' + clientSecret = config.clientSecret === REDACTED_MARKER ? '' : config.clientSecret || '' + scopes = config.scopes?.join(',') || 'openid,profile,email' + mapping = config.mapping ?? {} + authorizationEndpoint = config.authorizationEndpoint || '' + tokenEndpoint = config.tokenEndpoint || '' + jwksEndpoint = config.jwksEndpoint || '' + } else if (existingProvider.providerType === 'saml' && existingProvider.samlConfig) { + const config = JSON.parse(existingProvider.samlConfig) + entryPoint = config.entryPoint || '' + cert = config.cert || '' + callbackUrl = config.callbackUrl || '' + audience = config.audience || '' + wantAssertionsSigned = config.wantAssertionsSigned ?? true + /** Two stored shapes: `{ metadata }` from the route, a bare string from older rows. Narrow on type, not truthiness — `{ metadata: '' }` is falsy at `.metadata` but truthy as an object, putting an object in a string field. */ + idpMetadata = + typeof config.idpMetadata === 'string' + ? config.idpMetadata + : (config.idpMetadata?.metadata ?? '') + mapping = config.mapping ?? {} + identifierFormat = config.identifierFormat || '' + } + + const defaults = + existingProvider.providerType === 'saml' ? SAML_DEFAULT_MAPPING : OIDC_DEFAULT_MAPPING + const overrideOf = (value: string | undefined, fallback: string) => + value && value !== fallback ? value : '' + + const snapshot = { + providerType: existingProvider.providerType ?? 'oidc', + providerId: existingProvider.providerId ?? '', + issuerUrl: existingProvider.issuer ?? '', + domain: existingProvider.domain ?? '', + clientId, + clientSecret, + scopes, + entryPoint, + cert, + callbackUrl, + audience, + wantAssertionsSigned, + idpMetadata, + mapId: overrideOf(mapping.id, defaults.id), + mapEmail: overrideOf(mapping.email, defaults.email), + mapName: overrideOf(mapping.name, defaults.name), + identifierFormat, + authorizationEndpoint, + tokenEndpoint, + jwksEndpoint, + jitProvisioningEnabled: existingProvider.jitProvisioningEnabled ?? true, + } + setFormData(snapshot) + setOriginalFormData(snapshot) + setIsEditing(true) + setShowErrors(false) + setShowAdvanced(false) + setIsReplacingClientSecret(false) + setShowMapping(Boolean(snapshot.mapId || snapshot.mapEmail || snapshot.mapName)) + } catch (err) { + logger.error('Failed to parse provider config', { error: err }) + toast.error('Failed to load provider configuration') + } + } + + if (existingProvider && !isEditing) { + const providerCallbackUrl = `${getBaseUrl()}/api/auth/${existingProvider.providerType === 'saml' ? 'sso/saml2/callback' : 'sso/callback'}/${existingProvider.providerId}` + + return ( +
    + {active && ( + + )} + + +
    + +

    {existingProvider.providerId}

    +
    + + +

    + {(existingProvider.providerType ?? 'oidc').toUpperCase()} +

    +
    + + +

    {existingProvider.domain}

    +
    + + +

    + {existingProvider.issuer} +

    +
    + + + +

    + Configure this in your identity provider +

    +
    + + {existingProvider.providerType === 'saml' && ( + + + + )} +
    +
    + + + +

    + {existingJitProvisioningEnabled ? 'Automatic' : 'Invite only'} +

    +

    + {existingJitProvisioningEnabled + ? 'New users join as Members and use a seat. Grant workspace access separately.' + : 'Invite or provision new members before they sign in. Existing members keep their access.'} +

    +
    +
    +
    + ) + } + + return ( +
    + + + + + + {active && ( + void handleSubmit(), + onDiscard: handleDiscard, + }), + ]} + /> + )} + + {!existingProvider && ( +
    +

    + Use a verified email domain for this connection. +

    + Manage domains +
    + )} + + +
    + + + handleInputChange('providerType', value as 'oidc' | 'saml') + } + options={[ + { label: 'OIDC', value: 'oidc' }, + { label: 'SAML', value: 'saml' }, + ]} + placeholder='Select provider type' + /> + + + 0 ? errors.providerId.join(' ') : undefined + } + > + {isEditing ? ( + <> + +

    + Cannot be changed after saving. +

    + + ) : ( + <> + handleInputChange('providerId', value)} + options={PROVIDER_ID_SUGGESTIONS} + placeholder='Select or enter a provider ID' + editable + /> +

    + Unique across Sim, e.g. acme-entra. Cannot be + changed later. +

    + + )} +
    + + 0 ? errors.issuerUrl.join(' ') : undefined + } + > + e.target.removeAttribute('readOnly')} + onChange={(e) => handleInputChange('issuerUrl', e.target.value)} + error={showErrors && errors.issuerUrl.length > 0} + /> + + + 0 ? errors.domain.join(' ') : undefined} + > + e.target.removeAttribute('readOnly')} + onChange={(e) => handleInputChange('domain', e.target.value)} + error={showErrors && errors.domain.length > 0} + /> + + + {formData.providerType === 'oidc' ? ( + <> + 0 ? errors.clientId.join(' ') : undefined + } + > + e.target.removeAttribute('readOnly')} + onChange={(e) => handleInputChange('clientId', e.target.value)} + error={showErrors && errors.clientId.length > 0} + /> + + + 0 + ? errors.clientSecret.join(' ') + : undefined + } + > + setIsReplacingClientSecret(true)} + onCancelReplace={handleKeepSavedSecret} + value={formData.clientSecret} + onChange={(next) => handleInputChange('clientSecret', next)} + hasError={showErrors && errors.clientSecret.length > 0} + /> + + +
    + setShowAdvanced((value) => !value)} + rightIcon={ChevronDown} + aria-expanded={showAdvanced} + aria-controls='sso-advanced' + className='w-fit' + > + Advanced options + + + + +
    + 0 + ? errors.scopes.join(' ') + : undefined + } + > + handleInputChange('scopes', e.target.value)} + error={showErrors && errors.scopes.length > 0} + /> +

    + Comma-separated list of OIDC scopes to request +

    +
    + + + handleInputChange('authorizationEndpoint', e.target.value) + } + /> + + + + handleInputChange('tokenEndpoint', e.target.value)} + /> + + + + handleInputChange('jwksEndpoint', e.target.value)} + /> +

    + Sim reads these from the issuer's discovery document. Set them only if + your provider does not publish one. +

    +
    +
    +
    +
    +
    + + ) : ( + <> + 0 + ? errors.entryPoint.join(' ') + : undefined + } + > + handleInputChange('entryPoint', e.target.value)} + error={showErrors && errors.entryPoint.length > 0} + /> + + + 0 ? errors.cert.join(' ') : undefined} + > + handleInputChange('cert', e.target.value)} + className='min-h-20' + error={showErrors && errors.cert.length > 0} + rows={3} + /> + + +
    + setShowAdvanced((value) => !value)} + rightIcon={ChevronDown} + aria-expanded={showAdvanced} + aria-controls='sso-advanced' + className='w-fit' + > + Advanced options + + + + +
    + + handleInputChange('audience', e.target.value)} + /> + + + + handleInputChange('callbackUrl', e.target.value)} + /> + + + + + handleInputChange('wantAssertionsSigned', checked) + } + /> + + + + handleInputChange('identifierFormat', value)} + options={[...SAML_NAMEID_FORMATS]} + placeholder='Provider default' + /> + + + + handleInputChange('idpMetadata', e.target.value)} + className='min-h-15' + rows={2} + /> + +
    +
    +
    +
    + + )} + + + +

    + Configure this in your identity provider +

    +
    + + {/** Sim publishes no SP metadata document; these are the values it would carry. */} + {isSaml && ( + + +

    + Use this as Sim's entity ID in your identity provider. +

    +
    + )} + +
    + setShowMapping((value) => !value)} + rightIcon={ChevronDown} + aria-expanded={showMapping} + aria-controls='sso-mapping' + className='w-fit' + > + Attribute mapping + + + + +
    + + handleInputChange('mapEmail', e.target.value)} + /> + + + + handleInputChange('mapName', e.target.value)} + /> + + + + handleInputChange('mapId', e.target.value)} + /> +

    + Must be stable and unique per user — changing it later re-links accounts. +

    +
    +
    +
    +
    +
    +
    +
    + + + + handleInputChange('jitProvisioningEnabled', value === 'automatic')} + aria-label='SSO member provisioning mode' + options={[ + { value: 'automatic', label: 'Automatic' }, + { value: 'invite-only', label: 'Invite only' }, + ]} + /> +

    + {formData.jitProvisioningEnabled + ? 'New users join as Members and use a seat. Grant workspace access separately.' + : 'Invite or provision new members before they sign in. Existing members keep their access.'} +

    +
    +
    + + ) +} diff --git a/apps/sim/ee/sso/components/sso-settings.test.tsx b/apps/sim/ee/sso/components/sso-settings.test.tsx index 2c96b29c160..35980d2bc41 100644 --- a/apps/sim/ee/sso/components/sso-settings.test.tsx +++ b/apps/sim/ee/sso/components/sso-settings.test.tsx @@ -4,6 +4,7 @@ import { act, type ChangeEventHandler, type ReactNode } from 'react' import { resetEnvFlagsMock, setEnvFlags } from '@sim/testing' import { getErrorMessage } from '@sim/utils/errors' +import { NuqsTestingAdapter } from 'nuqs/adapters/testing' import { createRoot, type Root } from 'react-dom/client' import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' @@ -71,6 +72,7 @@ vi.mock('@sim/emcn', () => ({ }) =>