feat(sso): SAML/OIDC single sign-on by 0ski · Pull Request #3911 · triggerdotdev/trigger.dev
marked this pull request as ready for review
0ski added a commit that referenced this pull request
- vercel.onboarding: already-authenticated users whose domain requires SSO were redirected to /login/sso, which bounces authed users home and dropped the single-use Vercel code. Destroy the session first via authenticator.logout so /login/sso accepts them and the resume URL survives the round-trip (addresses PR #3911 review). - auth.sso.callback: sanitize redirectTo at the exit point (IdP-initiated values come from relay-state and never passed the host sanitizer) and attribute the referral source, matching the other auth callbacks. - ssoAuth: extract private early-return helpers (resolveSsoUserId, attachSsoIdentityBestEffort, provisionJitMembershipBestEffort, runPostAuthentication) and fail closed if the user can't be confirmed post-resolution instead of minting a session.
0ski
enabled auto-merge (squash)
Vendor-neutral plugin contract plus the host wiring that consumes it. With no SSO plugin installed, everything degrades to a no-op fallback, so OSS deployments are unaffected. - Plugin contract (@trigger.dev/plugins) + lazy loader/fallback in internal-packages/sso: status, portal-link, enforce/JIT config, route-decision, begin/complete authorization, identity resolution, JIT evaluation, and periodic session validation. All methods return neverthrow Results; the fallback is fail-open. - Login: 'Sign in with SSO' entry + dedicated /login/sso flow and /auth/sso(.callback) routes, plus auto-discovery from magic-link/OAuth. - Org settings -> SSO page: plan-tier upsell, connection status, verified-domain list, enforcement + JIT provisioning + default-role configuration, and an admin-portal link dialog. - AuthUser carries an optional signed 'sso' marker; SSO-established sessions are periodically re-validated against the identity provider on a single-flight, throttled, fail-open basis and logged out only on an explicit invalid result. - SSO_ENABLED gate (default off) so the feature ships dark until its backing plugin is available; SSO_SESSION_REVALIDATION_INTERVAL_SECONDS controls the cadence.
0ski
enabled auto-merge (squash)
ensureOrgMember's create + rbac.setUserRole + compensating delete are not transactional (the RBAC plugin writes on its own connection). The common single-failure case already recovers — a failed setUserRole deletes the row, so the next login retries cleanly. But if the compensating delete ALSO fails, the placeholder MEMBER row is orphaned and the findFirst no-op short-circuits every future login, stranding the user on the wrong role. When an existing membership is found and a JIT role is requested, complete the assignment if (and only if) the RBAC layer shows no role assigned. Gated on 'no role assigned' so it can never demote a deliberately-set role; best-effort so it never throws or rolls back a valid pre-existing membership. Addresses PR #3911 review.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters