> ## Documentation Index
> Fetch the complete documentation index at: https://modem.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Enterprise SSO

> Let your team sign in to Modem through your company identity provider with SAML 2.0 or OIDC

Enterprise SSO lets the members of your organization sign in to Modem through your company identity provider instead of GitHub or Google. Modem supports **SAML 2.0** and **OIDC**, and has step-by-step guides for [Okta](/docs/enterprise/sso-okta), [Microsoft Entra ID](/docs/enterprise/sso-entra), and [Google Workspace](/docs/enterprise/sso-google-workspace).

To also create and remove Modem accounts automatically from the same directory, see [Directory Sync](/docs/enterprise/scim).

<Info>
  Enterprise SSO requires the **Enterprise plan** and is turned on per organization by Modem. Contact
  [support@modem.dev](mailto:support@modem.dev) to have it enabled before you start.
</Info>

## Requirements

* The **Enterprise plan**, with SSO enabled for your organization by Modem
* The **owner** role in the Modem organization. Admins and members can open the SSO settings page but cannot change anything
* One identity provider per organization: either SAML 2.0 or OIDC, not both
* Access to DNS for the email domain you want to claim, so the domain can be verified

## How it works

Setting up SSO is a round trip between your identity provider and Modem, because each side needs a value the other one generates.

<Steps>
  <Step title="Create the application in your identity provider">
    Create a SAML app (Okta, Entra) or an OIDC client (Google Workspace) and point it at Modem's ACS URL or redirect URI. A SAML app
    also wants an audience or entity id, which Modem hasn't issued yet, so put a placeholder there on this first pass. An OIDC client
    needs nothing back from Modem, so its setup is a single pass.
  </Step>

  <Step title="Register the provider in Modem">
    Go to **Settings** → **SSO** in the [Modem dashboard](https://app.modem.dev) and enter the values your identity provider gave you:
    the issuer, the sign-on URL, and the signing certificate for SAML, or the issuer, client id, and client secret for OIDC.
  </Step>

  <Step title="Paste Modem's values back into the application">
    Once the provider is registered, the SSO settings page shows the values Modem generates — the SP entity ID, the ACS URL, the SP
    metadata URL, and the OIDC redirect URI. Copy the ones your provider needs back into the app you created in step 1.
  </Step>

  <Step title="Verify your email domain">
    Publish the DNS record Modem shows you and click verify. See [Domain verification](#domain-verification) below. Sign-in is refused
    until this succeeds.
  </Step>

  <Step title="Test the sign-in">
    Sign out, go to `https://app.modem.dev`, and click **Continue with SSO**. See [Signing in](#signing-in) below.
  </Step>
</Steps>

## The values you exchange

Modem generates the values in this table from your organization's numeric id. Copy them from the SSO settings page rather than building them by hand — the page shows the exact strings for your organization.

| Value                                                                                   | Shape                                                                      |
| --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Provider id                                                                             | `org-<id>`                                                                 |
| SAML ACS URL (also called Assertion Consumer Service, Reply URL, or Single sign-on URL) | `https://app.modem.dev/api/auth/sso/saml2/sp/acs/org-<id>`                 |
| SAML SP metadata URL                                                                    | `https://app.modem.dev/api/auth/sso/saml2/sp/metadata?providerId=org-<id>` |
| OIDC redirect URI (callback URL)                                                        | `https://app.modem.dev/api/auth/sso/callback/org-<id>`                     |
| Domain-verification DNS TXT host                                                        | `_modem-verification-org-<id>.<domain>`                                    |

In each of these, `<id>` is your Modem organization's numeric id and `org-` is literal.

Going the other way, Modem needs these from your identity provider:

| Flow     | What Modem needs                                                                                                                                     |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| SAML 2.0 | The IdP **Entity ID / Issuer**, the **Single Sign-On URL**, and the **X.509 signing certificate** — or the IdP metadata XML, which carries all three |
| OIDC     | The **Issuer** URL, the **Client ID**, and the **Client secret**                                                                                     |

<Note>
  Modem's **SP Entity ID (Audience URI)** is the same value you entered as your identity provider's Entity ID / Issuer, so it will look
  like your IdP's own issuer URL. That is expected. Copy it exactly as Modem shows it, and replace the placeholder audience in your IdP
  app with it.
</Note>

## Domain verification

Before anyone can sign in, your organization has to prove it controls the email domain it is claiming, for example `acme.com`.

<Steps>
  <Step title="Get the token">
    Modem issues a verification token on the SSO settings page. The token is stable — requesting it again returns the same value rather
    than rotating it — and it expires after **7 days** if it is never used.
  </Step>

  <Step title="Publish a DNS TXT record">
    Create a **TXT** record at `_modem-verification-org-<id>.<domain>`, where `<domain>` is the domain you are claiming. The value is the
    bare token, with no prefix and no quoting beyond whatever your DNS provider adds itself.
  </Step>

  <Step title="Verify in Modem">
    Click verify on the SSO settings page. DNS propagation can take anywhere from a few minutes to a few hours, so if verification fails
    the first time, wait and retry — there is no penalty for retrying.
  </Step>
</Steps>

<Warning>
  Until the domain is verified, **Continue with SSO** refuses the sign-in with "Single sign-on is not finished being set up", even though
  the provider is fully configured on both sides.
</Warning>

## Signing in

Users go to `https://app.modem.dev` and click **Continue with SSO**, then type either their work email address or your Modem organization slug. Modem resolves the provider from the email domain (or from the slug) and sends them to your identity provider. When they come back, they are signed in.

What happens on the Modem side depends on the person:

| Who is signing in                       | What happens                                                                                                                  |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Someone with no Modem account           | An account is created for them and they join your organization as a **member**                                                |
| Someone with a pending Modem invitation | The invitation's role is honoured instead — an `admin` invitation makes them an admin — and the invitation is marked accepted |
| An existing Modem user                  | They keep the same account. SSO is matched to it on the email address your identity provider asserts                          |

The **owner** role is never granted automatically. Promote someone from **Settings** → **Team**; see [Team Management](/docs/features/team-management) for what each role can do.

<Note>
  SSO is an additional way in, not yet a required one. GitHub and Google sign-in still work for the same users. Enforcing SSO is planned
  for a later release.
</Note>

## Identity attributes

Modem stores one stable identifier per user, taken from your identity provider. Choosing the right one matters more than it looks, because [Directory Sync](/docs/enterprise/scim) matches directory users to Modem users by **`externalId`** — and `externalId` has to be the **same value** as the SSO identifier.

<Warning>
  Never use email as the identifier. People change email addresses, and matching on email is how one person's account ends up handed to
  someone else. Use the immutable directory id below for your provider.
</Warning>

| Provider           | Flow | Identifier to send                                 | The matching SCIM `externalId`                                  |
| ------------------ | ---- | -------------------------------------------------- | --------------------------------------------------------------- |
| Okta               | SAML | NameID = `user.id`, the Okta user id               | Okta sends the Okta user id as `externalId` by default          |
| Microsoft Entra ID | SAML | Unique User Identifier (Name ID) = `user.objectid` | Entra's default is `mailNickname` — **change it** to `objectId` |
| Google Workspace   | OIDC | The `sub` claim, Google's stable global user id    | Nothing to configure — `sub` is what Modem stores               |

For SAML, Modem reads the rest of the profile from the assertion like this:

| What Modem wants | Where it reads it                                                                             |
| ---------------- | --------------------------------------------------------------------------------------------- |
| Account identity | The assertion's **NameID**                                                                    |
| Email            | An attribute named exactly `email`; if it is absent, Modem falls back to the NameID           |
| Name             | The attributes `givenName` and `surname`; failing that `displayName`; failing that the NameID |

So every SAML app should send a NameID set to the stable immutable id, plus an attribute statement carrying `email`, `givenName`, and `surname`.

## Limitations

* **SP-initiated sign-in only.** Users must start from the Modem sign-in page. IdP-initiated sign-in — the Okta dashboard tile, the Entra "My Apps" tile — is not supported and is rejected.
* **Assertions must be signed.** Modem rejects unsigned SAML assertions. Signing the whole response as well is fine but not required.
* **Encrypted assertions are not supported.**
* **Assertions are single-use.** Each one may be consumed once, and must be consumed within a few minutes of being issued.
* **One provider per organization**, either SAML 2.0 or OIDC.
* **SSO is not yet required** — GitHub and Google sign-in remain available.
* **No single logout (SLO).** Signing out of Modem does not sign the user out of your identity provider, or the reverse.

## Troubleshooting

<AccordionGroup>
  <Accordion title="No single sign-on provider for that address">
    The email domain typed at **Continue with SSO** has no provider registered against it. Check that the domain on the SSO settings
    page matches the domain in the address, and that the person is using their work address rather than a personal one.
  </Accordion>

  <Accordion title="Single sign-on is not finished being set up">
    The provider exists but the domain has not been verified. Publish the DNS TXT record and verify, as described in [Domain
    verification](#domain-verification).
  </Accordion>

  <Accordion title="Start single sign-on from Modem">
    Someone launched Modem from a tile in your identity provider's dashboard. Modem only accepts SP-initiated sign-in, so send them to
    `https://app.modem.dev` and have them click **Continue with SSO** instead.
  </Accordion>

  <Accordion title="The assertion is rejected">
    Check that your identity provider is signing the assertion, that the certificate registered in Modem is the current one, and that
    the Audience URI in the app matches the SP Entity ID Modem shows. A certificate rolled in the IdP has to be re-entered in Modem.
  </Accordion>

  <Accordion title="Signed in, but with the wrong role">
    Roles come from Modem, not from your identity provider. A first-time user joins as a member unless they had a pending invitation
    carrying a different role. Change roles in **Settings** → **Team**.
  </Accordion>
</AccordionGroup>

## Set up your provider

<CardGroup cols={2}>
  <Card title="Okta" icon="https://mintcdn.com/modem-844d7a4a/Wr2r4IRr97lNQiQb/icons/shield.svg?fit=max&auto=format&n=Wr2r4IRr97lNQiQb&q=85&s=ee1ca3093fcbdf45ec5dc1a74652bed6" href="/docs/enterprise/sso-okta" width="24" height="24" data-path="icons/shield.svg">
    SAML 2.0 app integration, with the Okta user id as the NameID.
  </Card>

  <Card title="Microsoft Entra ID" icon="https://mintcdn.com/modem-844d7a4a/Wr2r4IRr97lNQiQb/icons/shield.svg?fit=max&auto=format&n=Wr2r4IRr97lNQiQb&q=85&s=ee1ca3093fcbdf45ec5dc1a74652bed6" href="/docs/enterprise/sso-entra" width="24" height="24" data-path="icons/shield.svg">
    SAML enterprise application, with the directory object id as the NameID.
  </Card>

  <Card title="Google Workspace" icon="https://mintcdn.com/modem-844d7a4a/Wr2r4IRr97lNQiQb/icons/shield.svg?fit=max&auto=format&n=Wr2r4IRr97lNQiQb&q=85&s=ee1ca3093fcbdf45ec5dc1a74652bed6" href="/docs/enterprise/sso-google-workspace" width="24" height="24" data-path="icons/shield.svg">
    OIDC client, using Google's stable `sub` claim.
  </Card>

  <Card title="Team Management" icon="https://mintcdn.com/modem-844d7a4a/Wr2r4IRr97lNQiQb/icons/users.svg?fit=max&auto=format&n=Wr2r4IRr97lNQiQb&q=85&s=32a2de5620a3659206db1c3d1aff5a06" href="/docs/features/team-management" width="24" height="24" data-path="icons/users.svg">
    Roles, invitations, and auto-join.
  </Card>
</CardGroup>
