Skip to content

Workforce SSO vs Connector OAuth

These two auth domains look similar on the surface, but they solve different problems and use different provider identities inside the repo.

Topic Workforce SSO Connector / Social OAuth
Purpose Sign a person into the platform Authorize access to an external provider account
Main app owner apps/auth apps/api, apps/cms-customer, and connector runtime code
Example IDs google-sso, microsoft-sso google, microsoft, slack, atlassian, or another configured connector/social provider id
User result Platform session Provider tokens or connector access
Policy scope Deployment sign-in policy Connector capability and provider scope policy

Workforce SSO provider IDs are intentionally isolated from connector and social OAuth provider IDs. That prevents platform login configuration from colliding with connector token and provider-runtime behavior.

Better Auth 1.6.16 now rejects SSO provider ids that collide with configured social/trusted provider ids, and SSO callback trust no longer comes from a provider-name match. Workforce SSO uses Better Auth SSO domainVerification; deployment-managed setup marks configured provider rows domain-verified, and SSO provider ids stay out of Better Auth accountLinking.trustedProviders. Treat that as upstream defense in depth. Repo-level startup, sign-in-policy, and focus validation still enforce the boundary before a connector-linked account can be mistaken for workforce SSO.

This separation applies to every provider family that can appear in both workforce SSO and connector/social OAuth. Current configured examples include:

  • google-sso and microsoft-sso are Better Auth SSO provider ids for web sign-in.
  • google and microsoft are connector/social OAuth provider ids used for linked provider accounts.
  • GOOGLE_SSO_* and MICROSOFT_SSO_* env vars control workforce sign-in registration and policy.
  • Connector OAuth credentials and scopes use the connector/social provider ids and connector runtime policy, not the *_SSO_* provider ids.
  • google-sso and microsoft-sso mean workforce sign-in.
  • Connector/social provider ids such as google, microsoft, slack, and atlassian refer to connector-facing provider integrations.
  • Matching labels in the UI do not mean they are the same provider registration inside the system.
  • A connector-linked OAuth account must not be accepted by the workforce SSO sign-in entrypoint.
  • A workforce SSO account must not be offered as a connector/social account unless the user explicitly links the corresponding connector provider account.
  • Chat focus follows the same boundary: connector-account focus choices come from connector OAuth bindings and owned connector rows. Workforce SSO accounts such as google-sso and microsoft-sso must not appear as focus account choices or pass focus validation.
  • Workforce SSO can auto-link onto an existing local email/password user only when that local user already has verified inbox ownership.
  • In this repo, approved web access completion is the canonical path that creates a local user and then marks that user emailVerified = true.
  • If a local credential user is still unverified, same-email workforce SSO must fail closed instead of silently linking into that account.

Better Auth treats a linked external account as the pair providerId + accountId. The same external connector/social account cannot belong to two Better Auth web users at the same time.

That means:

  • any connector/social provider account identified by a specific providerId + accountId pair cannot be linked by two different app users,
  • unlinking a connector/social account frees that external account for a future user link,
  • sharing one external provider account across multiple app users would require a separate app-level sharing model above Better Auth linked accounts.
File What it helps you answer
apps/auth/.env.example Workforce SSO env groups and provider ids
apps/api/.env.example Connector runtime env groups and provider setup
packages/domain/src/connectors/connectorRegistry.ts Connector keys, OAuth bindings, and scopes
packages/contracts/src/auth/signInPolicy.ts How workforce providers are exposed on sign-in surfaces
docs/features/authentication/spec.md Why workforce ids must stay separate from connector ids
docs/features/connectors/spec.md Connector account ownership and OAuth runtime rules