# Single sign-on (SAML)

Connect your identity provider so people sign in to CodeHerder through your own SAML setup, on the Enterprise plan.

Source: https://codeherder.com/docs/sso/

Connect your identity provider so people sign in to CodeHerder through your own SAML setup, on the Enterprise plan.

**Single sign-on (SSO)** lets your identity provider (IdP) authenticate people signing in to CodeHerder, in place of the usual email sign-in. It’s available on the **Enterprise** plan — see [Plans and limits](https://codeherder.com/docs/plans-and-limits/#what-your-plan-unlocks). On any other plan, the SSO page shows an upgrade banner with a **Contact sales** link instead of the setup form.

This connection also carries automatic user provisioning, a separate Enterprise entitlement that lets your identity provider create and deactivate accounts for you instead of you inviting people by hand — see [Automatic user provisioning (SCIM)](https://codeherder.com/docs/scim/).

## Where it lives

Open **Settings → SSO**. There is no `ch` command for SSO — set it up and manage it from the web app only.

## Who can set it up

Only an **owner** or **admin** of your account’s top-level workspace can set this up. If you open **Settings → SSO** from a workspace nested under a group, you’re still looking at that top-level workspace’s connection — an account holds a single connection, shared by every workspace inside it, not one per nested workspace. A **member** sees a read-only view with a notice that only an owner or admin can manage it.

An account can hold only **one non-disabled** connection at a time — that includes one still pending, not yet enabled. If creating a new connection is refused because one already exists, disabling the existing connection frees the slot; you don’t need to delete it first.

## Creating the connection

Click **New connection** and fill in three fields:

- **Provider name** — a label for the connection, 3–32 characters. The first character must be a letter or digit; the rest can also include hyphens and underscores. It must be unique across all of CodeHerder, not just your own account — if a name you expected to be free is refused, someone else has already taken it. It also can’t be one of a handful of reserved identity-provider names (Google, Microsoft, GitHub, and similar) exactly, or start with one of those names followed by a hyphen or underscore — `google-corp` is refused, but `googlecorp` is accepted.
- **IdP metadata** — either a **Metadata URL** your identity provider publishes, or a **Metadata XML document** you upload directly. Provide exactly one; you can’t set both.
- **Email verified attribute** (optional) — the name of the SAML attribute your identity provider asserts to say an email address is verified: up to 128 characters, printable ASCII only, with no spaces, quotes, or backslashes. Leave it blank if your IdP doesn’t send one. See [Matching sign-ins to an existing member](https://codeherder.com/docs/sso/#matching-sign-ins-to-an-existing-member) below for what this field is for and what else has to be true for it to work.

Saving creates the connection in **pending** status — it doesn’t accept sign-ins yet.

## Handing values to your identity provider

Once the connection exists, its page shows three values for your IdP admin to configure:

- **ACS URL** — where your IdP sends its SAML response after authenticating someone.
- **Entity ID** — the identifier your IdP uses for this connection.
- **Sign-in URL** — a ready-to-use link for testing. It isn’t required by your IdP configuration, but see [How people sign in](https://codeherder.com/docs/sso/#how-people-sign-in) below — you’ll likely want to distribute this link yourself.

Each value is copyable straight from the page. If your deployment has no single-sign-on hosting configured, all three show “Not available” instead — ask whoever runs your deployment to enable it.

With your IdP configured against those values, click **Enable** to move the connection from pending to **active** and start accepting sign-ins. **Disable** reverses this at any time — it stops routing sign-ins through the connection immediately.

A separate **Provisioning** indicator on the page (unprovisioned / provisioned / error) reports whether the underlying sign-in service currently has a working provider set up — it’s not the same thing as the connection’s Status above, and an error there is shown with its own banner.

## Claiming and verifying a domain

Claiming a domain proves you control it — and verifying it is one of two conditions (see [Matching sign-ins to an existing member](https://codeherder.com/docs/sso/#matching-sign-ins-to-an-existing-member) below) that let someone signing in through your connection be matched to their existing CodeHerder membership by email address. To claim one:

1. Add the domain on the connection’s page. CodeHerder shows a DNS TXT record to publish: name `_codeherder-sso.<your-domain>`, value `ch-verify=<a token>`.
2. Publish that record with your DNS provider.
3. Click **Verify**.

A few things worth knowing:

- Public email domains (gmail.com, outlook.com, and similar free or disposable providers) can never be claimed, no matter what DNS says.
- Verification is first-come: whichever account verifies a domain first keeps it, and no other connection — on any account — can claim it afterward, even if another account typed it in first.
- **Leave the TXT record published after verifying.** CodeHerder rechecks verified domains periodically, and if a check genuinely finds the record missing three times in a row, the domain drops back to unverified. A DNS lookup that simply fails to complete doesn’t count against you — only a confirmed missing or wrong record does.

## Matching sign-ins to an existing member

When someone signs in through your connection, CodeHerder can automatically match them to their existing membership by email address — but only when **both** of these are true:

1. Your connection’s **email verified attribute** field (above) is set, and your identity provider actually asserts that attribute as true for that person.
2. The person’s email domain is **verified** on this connection (above), and the connection is **active**.

If either condition isn’t met, CodeHerder treats the email as unverified no matter what your identity provider asserted, and the sign-in **fails outright** — it does not fall back to any other match. Inviting the person again doesn’t fix this: an invitation creates a separate, ordinary email sign-in for them, and doesn’t change how their SAML sign-in gets matched. Set the email-verified attribute and verify your domain before you send anyone the Sign-in URL — see [When it goes wrong](https://codeherder.com/docs/sso/#when-it-goes-wrong) below if someone hits this after you already have.

## How people sign in

Distribute your connection’s **Sign-in URL** to the people who should use it — link it from your company intranet, your IdP’s own app dashboard, or a bookmark you send around. Following that link takes someone straight to your identity provider to authenticate, then back into CodeHerder.

CodeHerder’s own sign-in page does not detect your organization from someone’s email address and redirect them automatically — there’s no “Sign in with SSO” button there tied to your connection. The Sign-in URL is the way in.

## Changing, disabling, and removing a connection

**Renaming.** The provider name can’t be changed while the connection is active. Disable it, give it a moment to finish deprovisioning, then rename it and re-enable.

**Disabling.** Disable stops routing sign-ins immediately, whether or not the underlying deprovisioning finishes right away.

**Removing.** Deleting a connection is permanent, and the web app asks you to confirm before it proceeds. If tearing down the connection’s live configuration fails partway through, the removal itself is refused and reported rather than leaving things half-cleaned-up — wait a moment and try again.

## When it goes wrong

- **Creating a second connection is refused.** An account holds one non-disabled connection at a time. Disable the existing one to free the slot.
- **Someone reaches your identity provider through the Sign-in URL but can’t get into your workspace.** This is almost always the two conditions in [Matching sign-ins to an existing member](https://codeherder.com/docs/sso/#matching-sign-ins-to-an-existing-member) above — check that your email verified attribute is set and actually asserted by your IdP for that person, and that their email domain is verified on this connection while it’s active. Re-inviting them does not fix this.
- **A domain won’t verify.** Double check the exact TXT record name and value shown on the connection’s page — a small typo, or a record published under the wrong subdomain, is the usual cause. Public email domains never verify, by design.
- **Renaming is refused.** The connection is still active, or still finishing a disable — wait for it to settle, then try again.
- **All three configuration values read “Not available.”** Single-sign-on hosting isn’t configured on your deployment; ask whoever runs it to enable it.
- **The Provisioning indicator shows an error.** The connection’s Status can still be active while Provisioning shows a problem — re-check your IdP configuration against the ACS URL and Entity ID, then disable and re-enable the connection to retry provisioning.

## Related guides

- [Automatic user provisioning (SCIM)](https://codeherder.com/docs/scim/) — let your identity provider create and deactivate accounts for you
- [Plans and limits](https://codeherder.com/docs/plans-and-limits/) — the Enterprise plan and what else it unlocks
- [Members, teams, and roles](https://codeherder.com/docs/members-and-teams/) — workspace roles, and inviting people who don’t sign in through SSO
- [Credentials and profiles](https://codeherder.com/docs/credentials/) — how the `ch` CLI authenticates, separate from web sign-in
