Docs

Connect your team identity provider

RepoOps accepts SAML 2.0 assertions or OpenID Connect authorization-code logins for an Enterprise team. Protocol validation proves the identity, then the hosted membership table decides whether that identity may enter the team. SCIM uses a separate one-time credential to add and deactivate members from the same directory.

For: the team owner or admin who configures the identity provider and tests access before rollout

What it does, and why it helps

The hosted SSO / SAML page gives an owner or admin the service-provider values to register with an identity provider. SAML uses ACS URL (Assertion Consumer Service) and Entity ID / Audience. OIDC uses Redirect / callback URL (give this to your IdP), discovery from the issuer, an authorization-code flow with PKCE, and a member sign-in link. Both routes recheck the Enterprise entitlement at login time and reject a verified email that has no membership in this team.

Saving the SAML card also mints the SCIM bearer token on first save. The page shows that raw token once, stores only its SHA-256 hash, and later reports only configured (write-only). A SCIM client can create, update, list and deactivate Users and Groups under that team. A Group is directory bookkeeping, not a RepoOps role or access grant. User deactivation removes an ordinary member's membership; it does not demote or remove an owner or admin.

The pain. A signed response from an identity provider proves who answered. By itself it does not prove that person belongs to this RepoOps team, and a directory change means little if the application keeps a separate roster.

The point of view. Authentication and membership are two checks. Verify the protocol first, then resolve the verified email against the team. Test the rejection path with the same care as the successful login.

What gets easier. Connecting an existing directory without creating a second membership model. SAML and OIDC resolve into the same users and memberships, SCIM updates those rows, and SSO-prefixed audit events export as one trail.

When it helps. Before an Enterprise team moves sign-in to Okta, Microsoft Entra, Google Workspace, Auth0 or another SAML 2.0 or OIDC provider, and when directory-driven onboarding or offboarding is required.

Its limits. SAML is IdP-initiated only. The Member sign-in link starts OIDC only. SSO is an available sign-in path, not a rule that disables Google, Apple or email sign-in. There is no domain discovery, forced SSO, SP-initiated SAML, SCIM bulk operation, sort control or ETag support.

Understand it in 30 seconds

30.1 s, captions on. Narration: Microsoft Zira Desktop (provisional voice; an approved narration source is pending).Transcript
Read the narration
  1. 0:00 A valid identity provider response should never create access to the wrong team.
  2. 0:06 Authentication proves an identity. Membership still decides whether that identity belongs here.
  3. 0:13 RepoOps verifies the response, blocks replay and rechecks the Enterprise tier.
  4. 0:18 Then it requires an existing team membership.
  5. 0:23 Test one member, one non-member, and the audit trail before rollout.

Synthetic example. Read the guide

Where to find it

  • Hosted: repoops.ai/team/sso, from Team & settings in the sidebar, then SSO / SAML under Account and access.
  • Desktop: hosted only.

When to use it

Configure an IdP-initiated SAML app

Situation. An Enterprise team already has its members in RepoOps and wants sign-in from the identity provider app tile.

What you do. Copy the ACS URL and Entity ID / Audience into the IdP. Paste the IdP entity id, SSO URL and PEM X.509 signing certificate into Configure identity provider, then press Enable SSO.

What you see. Current configuration shows the entity id, SSO URL, Certificate fingerprint (SHA-256), and SCIM token as configured. A valid signed assertion for an existing member redirects to the dashboard and writes sso.assertion.accepted.

What it establishes. That member receives the same hosted session used by the rest of RepoOps. A valid assertion for a non-member receives 403 and writes a redacted rejection reason instead of creating membership.

Add OIDC without hand-copying provider endpoints

Situation. The identity provider publishes OpenID Connect discovery and the team wants a sign-in link members can open from RepoOps.

What you do. Register the displayed callback URL with the IdP. Enter Issuer (https), Client id and Client secret (write-only), then press Enable OIDC. Give members the displayed Member sign-in link.

What you see. A successful save says discovery succeeded and shows the cached Authorization endpoint, Token endpoint and JWKS URI, but never the client secret. The login uses state, nonce and PKCE before ID-token verification.

What it establishes. A member can press Continue with SSO from the team-specific sign-in link. A wrong state, nonce, issuer, audience, signature, expired token or non-member email is rejected and logged with a stable reason.

Let the directory manage ordinary members

Situation. The IdP should add and deactivate members without a separate invitation cleanup pass.

What you do. On the first SAML save, copy SCIM bearer token (shown once) and the SCIM endpoint into the IdP. Configure its Users and Groups provisioning against that endpoint.

What you see. SCIM Users map onto the existing users and memberships tables. Active user creation checks the paid seat count. Deactivation removes ordinary membership and revokes that user's bound devices and fleet secrets. Group changes stay directory metadata only.

What it establishes. The roster follows supported SCIM user operations, with redacted SCIM audit rows in the SSO export. Owners and admins remain protected from SCIM removal and must be changed through a manager-controlled path.

Before you start

Supported versions
RepoOps hosted v0.3.1, the release this guide was read against. The desktop row only opens the hosted page.
Where it runs
Hosted at repoops.ai/team/sso, SSO / SAML under Team & settings. There is no public/sso.html because the feature is hosted only. The SAML ACS, OIDC start and callback, and SCIM endpoints run on the website server.
Permissions
A signed-in owner or admin may read, create, update and remove the team configuration. Server actions and config APIs repeat authentication, membership, manager role and tier checks. Members see an ask-an-admin message. Login itself requires an existing membership after protocol verification, unless SCIM created that ordinary membership first.
Connections
A SAML 2.0 IdP with an entity id, SSO URL and PEM signing certificate, or an OIDC provider with a public HTTPS issuer, client id and client secret. SCIM needs the one-time bearer token. The configured public origin must exactly match the URLs registered at the IdP.
Plan
Enterprise with an active, trialing or past-due subscription. The current gate requires Enterprise for configuration, SAML, OIDC and SCIM. Lower tiers see Enterprise plan and View plans; unauthenticated login routes answer as unconfigured rather than exposing billing state.

Configure it

  1. Choose SAML or OIDC as the member entry path.

    SAML starts at the IdP app tile because RepoOps has no SAML start route. OIDC starts from the displayed Login start URL or Member sign-in link and returns to the registered callback URL.

  2. Register the exact RepoOps values at the IdP.

    Copy the SAML ACS and audience, or the OIDC callback URL, exactly as shown. The page and routes derive them from the same configured public origin so a host redirect does not change the registered string.

  3. Save the provider metadata and protect the one-time secret.

    SAML needs entity id, SSO URL and the full signing certificate on every update. OIDC needs issuer, client id and client secret on every update. Copy the first or rotated SCIM token before leaving the result URL; it cannot be read later.

  4. Provision membership before testing login.

    Invite the member or let SCIM create the ordinary membership. A valid SAML assertion or OIDC token never creates membership by itself.

  5. Test success, rejection and evidence.

    Sign in once as a member and once with a verified non-member address. Then export CSV or JSON and confirm the accepted and rejected events carry no assertion, token, certificate or secret.

SettingWhereA sensible choiceWhy it matters
ACS URL (Assertion Consumer Service), Entity ID / AudienceService provider details (give these to your IdP)Copy both exact values into the SAML applicationThe ACS receives the IdP POST. The assertion audience must equal the displayed repoops:org team value.
IdP entity id (issuer)Configure identity providerThe exact entity id from the IdP metadataRepoOps passes it as the SAML IdP issuer expected by the assertion validator.
IdP SSO URL (single sign-on endpoint)Configure identity providerThe IdP's valid SAML POST endpoint URLShape validation requires a URL. SAML starts at the IdP because RepoOps does not provide an SP-initiated start route.
IdP signing certificate (PEM X.509)Configure identity providerThe current IdP signing certificate with BEGIN and END markersThe certificate body is stored server-side and never shown again. Current configuration shows only its SHA-256 fingerprint.
Rotate the SCIM provisioning tokenConfigure identity providerOff for a metadata-only update; on when replacing the IdP credentialFirst save mints a token automatically. Rotation replaces the stored hash and reveals the new raw token once, so the old token stops authenticating.
SCIM endpoint (provisioning)Service provider details (give these to your IdP)Use the displayed team endpoint with the one-time bearer tokenThe token is bound to this team. Users change membership; Groups do not change roles or access.
Redirect / callback URL (give this to your IdP)OpenID Connect (OIDC)Register the exact displayed callback URLThe OIDC code exchange uses this same redirect URI. A different host or path fails the provider's exact match.
Issuer (https)OpenID Connect (OIDC)The provider's public HTTPS issuerSave fetches its well-known discovery document. Private, loopback, link-local and internal hosts are refused, and the document issuer must match.
Client idOpenID Connect (OIDC)The OAuth client registered for the displayed callbackRepoOps sends it in the authorization and token requests and verifies it as the ID-token audience.
Client secret (write-only)OpenID Connect (OIDC)The current OAuth client secretIt is encrypted at rest and omitted from reads. Re-enter it whenever you update OIDC configuration.
Remove SSO configurationCurrent configurationUse to disable SAML and the SCIM bearer gate for this teamIt deletes the SAML config row immediately. It does not remove OIDC configuration, memberships, SCIM bookkeeping rows or existing sessions.
Remove OIDC configurationCurrent OIDC configurationUse to disable OIDC start and callback for this teamIt deletes the OIDC config row. It does not remove SAML, memberships or existing sessions.
Export CSV, Export JSONSSO audit exportChoose the format your reviewer needs and narrow a large trail on Audit logThe export includes sso.-prefixed events. More than 10,000 matching rows is refused rather than truncated.
ⓘ
To stop or undo
Remove SSO configuration deletes the SAML descriptor and SCIM token hash, disabling those entry points. Remove OIDC configuration disables OIDC separately. Removing either config does not revoke sessions already minted or force members out of other sign-in methods. To stop a person, remove or deactivate their membership; SCIM refuses to remove an owner or admin.

What you should see

A valid SAML assertion for a member

Configuration. Enterprise entitlement, configured SAML metadata, signed assertion with the displayed audience, and a NameID email matching a team member.

Expect. RepoOps validates the signature and timing, claims the assertion id in the database replay cache, resolves membership, writes accepted audit rows and redirects to the dashboard with the shared session cookies.

Verify. The SSO audit trail contains sso.assertion.accepted with the member's user id and lowercased principal. Reusing the same assertion is rejected by the database-backed replay claim.

A valid OIDC token for a non-member

Configuration. Configured OIDC discovery and a correctly signed token whose email is not in the team's membership table.

Expect. Signature, issuer, audience, time, state and nonce may all pass, but the callback returns forbidden at the membership gate and creates no session.

Verify. The SSO audit trail records sso.oidc.login.rejected with the stable not-a-member reason and no ID token, code, client secret or exception message.

SCIM deactivates an ordinary member

Configuration. A valid team SCIM bearer and an existing active SCIM User whose team role is member.

Expect. PATCH active false or DELETE marks the SCIM user inactive, removes membership, and revokes that user's device bindings and fleet secrets. Repeating deactivation is safe.

Verify. The member no longer resolves through membershipByEmail. The redacted scim.user.deactivated audit row records whether membership and credentials were removed.

Data and cost

What is captured
One SAML config row per team stores the IdP entity id, SSO URL, PEM signing certificate and SCIM token hash. One OIDC config row stores issuer, client id, encrypted client secret plus its hash, and cached discovery endpoints. SCIM stores user and group mappings beside the existing users and memberships. SSO and SCIM mutations and login outcomes write redacted audit events.
Who can see it
Owners and admins can read masked configuration. The certificate body, SCIM hash and OIDC secret never return on a read. The raw SCIM token appears once after mint or rotation. The IdP sees the protocol request values, and an SSO export is manager-only and Enterprise-gated. A SCIM token can access only the team named in its endpoint.
How long it is kept
Not provided for SSO configuration or audit rows on this surface. Config persists until its matching remove action. A consumed SAML assertion id stays in the replay cache for one hour. The OIDC transaction cookie expires after ten minutes and is cleared on callback. A successful SSO Auth.js session lasts up to thirty days unless another access check blocks it.
What leaves the machine
SAML posts the assertion from the IdP through the member's browser to the RepoOps ACS. OIDC save fetches the public discovery document; login redirects the browser to the authorization endpoint, posts the code and client credential to the token endpoint, and reads the public JWKS. SCIM clients send directory records to RepoOps. No model is called.
What it costs
No model cost. The hosted service performs protocol validation, database reads and writes, provider discovery, token exchange and audit export. Provider licensing and the RepoOps Enterprise subscription are outside the measured AI-spend ledger.

When the result differs

SymptomLikely causeNext action
The page shows Enterprise plan instead of configuration.The team is not both entitled and on the Enterprise tier. Active, trialing and past-due count as entitled; lower plans do not pass the tier rung.Use View plans or contact sales, then confirm the billing webhook set the team's plan and subscription status.
The SAML assertion returns bad assertion.The signed response is missing, invalid, too old, outside its time window, has the wrong audience or issuer, carries no NameID, or repeats a consumed assertion id.Compare the IdP application with the displayed ACS and Entity ID / Audience, then inspect the stable rejection reason in the SSO audit trail.
OIDC discovery failed.The issuer is not public HTTPS, cannot be resolved safely, returns a failing discovery response, reports a different issuer, or points a required endpoint at another origin.Use the exact public issuer from the provider and confirm its well-known document exposes authorization, token and JWKS endpoints on that origin.
Continue with SSO returns not configured.The team id is wrong, OIDC is absent, or the Enterprise entitlement was lost. SAML does not use this link.Copy the Member sign-in link again from the configured team. For SAML, start at the IdP app tile.
A verified identity receives forbidden.Its normalized email does not match an existing membership in this team.Invite that exact address or provision it through SCIM, then retry. Do not weaken the membership gate.
The SCIM client receives unauthorized or forbidden.The bearer is absent, wrong or rotated, or the authenticated team no longer meets Enterprise entitlement.Rotate the token if its value is lost, update the IdP immediately, and check the team plan. The old raw token cannot be recovered.
An SSO export is refused as too large.The selected SSO event set exceeds 10,000 rows.Open Audit log, choose SSO / SAML, set a narrower since and until window, and export that view.
Disable
Use Remove SSO configuration for SAML and SCIM, and Remove OIDC configuration for OIDC. They are independent. A plan downgrade also blocks new SAML, OIDC and SCIM requests at their server-side tier checks.
Roll back
Not provided. The page keeps no prior certificate, endpoint, issuer or client-secret version to restore. Paste the former values again if you retained them at the IdP. Rotating SCIM has no route to recover the old raw token, and the old bearer stops working.
Revoke access
Remove or SCIM-deactivate the member to stop team membership; deactivation also revokes that ordinary member's bound devices and fleet secrets. Removing provider configuration does not revoke sessions already minted. No page control revokes all SSO sessions for the team.
Delete
Remove SSO configuration deletes the SAML descriptor and SCIM token hash. Remove OIDC configuration deletes its provider config. Not provided for SCIM user and group bookkeeping, SSO audit rows or session rows from this page. SCIM user DELETE deactivates and retains the user mapping; SCIM group DELETE removes only directory group bookkeeping.

Maintenance evidence

Feature id
sso (spine leaf sso)
Owner
Team hosted mode TH.4 and K5.F.4 identity production, with AI Security Phase 2 SCIM Groups. Guide: LDG-0717.
Supported product version
RepoOps v0.3.1
Last verified
2026-09-15, read against origin/main at 52366bb6d; labels read from the served tab source in website/app/team/(home)/sso/page.tsx, the hosted-only desktop pointer in lib/canonical-tabs.mjs, and the SAML, OIDC, SCIM and audit route implementations.
Example fixtures
No fixture file. website/lib/saml-config.test.ts covers masking, token rotation and persistence; website/app/api/team/sso/sso-route.test.ts covers auth, role, tier and secret projection; saml-acs.test.ts, saml-hardening.test.ts, saml-rate-limit.test.ts and saml-replay-cache.integration.test.ts cover SAML; oidc-config.test.ts, oidc-login.test.ts, team-oidc.test.ts, oidc-start.test.ts, oidc-callback.test.ts and oidc-rate-limit.test.ts cover OIDC; scim-users.test.ts, scim-groups.test.ts and scim-email-normalization.db.test.ts cover SCIM; export-route.test.ts covers the SSO audit filter.
Source references
lib/canonical-spine.json, lib/canonical-tabs.mjs, website/app/team/(home)/sso/page.tsx, website/lib/tier.ts, website/lib/saml-config.ts, website/lib/saml-replay-cache.ts, website/app/api/auth/saml/[orgId]/route.ts, website/lib/oidc-config.ts, website/lib/oidc-login.ts, website/app/api/auth/oidc/[orgId]/start/route.ts, website/app/api/auth/oidc/[orgId]/callback/route.ts, website/lib/sso-session.ts, website/lib/sso-signin.ts, website/lib/scim/scim-core.ts, website/lib/scim/scim-provisioning.ts, website/app/api/team/audit/export/route.ts
Documentation review
Independent review requested on the slice pull request; not yet recorded.
Video review
Narrated story rendered and published 2026-09-26 (render 797a6a9c791a, LDG-1012) with the breadcrumb Team & settings, checked against main at b0bb02812. Six frames, the captions and the transcript were reviewed by the authoring agent, not an independent reviewer; the audio was not listened to by a person. Narration is the provisional Windows voice until LDG-0721.

Last updated