Skip to content

feat(sso): let an organization keep several identity providers on one domain and choose the primary - #7836

Merged
waleedlatif1 merged 4 commits into
stagingfrom
fix/sso-same-domain-providers
Sep 15, 2026
Merged

waleedlatif1 merged 4 commits into
stagingfrom
fix/sso-same-domain-providers

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • An organization can add a second identity provider on a domain it already signs in through, instead of getting "already signs in through the provider…". This is how teams move from one IdP to another (e.g. Entra ID → Okta) without downtime
  • New nullable sso_domain.primary_provider_id names the provider sign-in uses. When it's null, behavior is unchanged: the first verified provider by id, so existing orgs see no difference
  • The name is only honored while that provider still belongs to the org, is verified, and serves the domain. Deleting a provider (settings or deregister script) clears it
  • A provider joining a domain can't take over by sorting first. Unless the domain's named primary still signs it in, the provider already signing people in is named. This applies to new providers, providers moved onto the domain, and untrusted providers saved again, in both the register route and the self-host script
  • A caller's own personal (org-less) provider on the domain still blocks adding an org provider there, same as before
  • Make primary goes through an organization.sso.set_primary_provider application use case (org admin, session) and writes an organization.sso.primary_provider_changed audit entry
  • Settings: a Primary tag shows when a domain has more than one provider, plus Make primary with a confirmation, and a Test sign-in link (/sso?provider=<id>) for a verified provider waiting beside the primary. Grouping uses the normalized domain
  • Resolve honors the test link only for a verified provider that serves the email's domain. A failed test sign-in returns to the same link
  • Delete confirmation names who signs in afterward. Otherwise it keeps the existing "can no longer sign in through it" copy
  • Shared rules (domain key, join, keep-sign-in, clear) live in @sim/db/sso-primary-provider, so the app and scripts can't drift
  • Migration 0347 adds the column and drops sso_provider_org_domain_unique concurrently. The deployed release still refuses same-domain providers before writing, so it's safe during cutover. After a rollback, a domain whose chosen primary doesn't sort first falls back to the first provider by id
  • Docs: new "Switching identity providers" section

Type of Change

  • New feature

Testing

  • PostgreSQL integration suite covers:
    • resolve, the list route, make primary (roles, cross-org, audit) and delete
    • domain moves, test links, registration pinning, stale names and personal-provider refusal
    • it runs in the CI Postgres job
  • Key cases fail with their fix reverted
  • All 347 migrations applied to an empty database
  • Ran both self-host scripts end to end against a local database, and checked the settings UI in a browser against a running app (two providers, single provider, unverified provider)
  • Unit tests updated. The full vitest suite passes except the pre-existing cleanup-table-row-ttl integration test, which needs a DB
  • lint, check:audits, check:api-validation:strict, docs-manifest:check, repo-wide type-check and check:migrations origin/staging pass

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@waleedlatif1
waleedlatif1 requested a review from a team as a code owner September 15, 2026 01:11
@vercel

vercel Bot commented Sep 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs Ready Ready Preview Sep 15, 2026 1:44am UTC

Request Review

@greptile-apps

greptile-apps Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge; no outstanding correctness, security, or repository-rule violation remains in the scoring set.

Summary

The PR enables multiple SSO identity providers to serve one verified organization domain while preserving an explicit, safely validated primary provider.

  • Adds a nullable domain-level primary-provider pointer and removes the former same-domain uniqueness restriction.
  • Routes normal sign-in through the valid named primary with deterministic fallback, while supporting provider-specific test links.
  • Preserves existing routing when providers are added or moved and clears stale primary pointers when providers are deleted.
  • Moves primary-provider selection behind an authorized organization operation with semantic audit recording.
  • Adds settings UI, migration/script support, documentation, and PostgreSQL integration coverage.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  Admin[Organization admin] --> Add[Add provider to verified domain]
  Add --> Pin[Preserve incumbent sign-in provider]
  Pin --> Test[Test provider-specific sign-in link]
  Test --> Set[Make tested provider primary]
  Set --> Auth[Authorized organization operation]
  Auth --> Domain[(sso_domain.primary_provider_id)]
  User[User submits email] --> Resolve[Resolve verified provider]
  Domain --> Resolve
  Resolve --> Named{Valid named primary?}
  Named -- Yes --> Primary[Use named provider]
  Named -- No --> Fallback[Use first verified provider by ID]
  Primary --> IdP[Identity provider]
  Fallback --> IdP
  Delete[Delete provider] --> Clear[Clear matching primary pointer]
  Clear --> Domain
Loading

Reviews (2) · Last reviewed commit: "fix(sso): regenerate the primary provide..."

Comment thread apps/sim/app/api/auth/sso/providers/[providerId]/route.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@waleedlatif1
waleedlatif1 merged commit c3f8140 into staging Sep 15, 2026
34 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/sso-same-domain-providers branch September 15, 2026 01:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant