> ## 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.

# Microsoft Entra ID SAML

> Connect Modem to Microsoft Entra ID with a SAML enterprise application

This guide sets up [Enterprise SSO](/docs/enterprise/sso) with Microsoft Entra ID (formerly Azure AD) using a SAML enterprise application. Read the overview first if you haven't — it covers domain verification, roles, and the limitations that apply to every provider.

The Entra admin center changes regularly, so treat the menu paths and field labels below as a guide; the exact labels move between releases.

## Why SAML and not OIDC

Entra also speaks OIDC, but Modem recommends SAML here for one specific reason: Entra's OIDC `sub` claim is **pairwise**. It is a different value for every application registration, so it cannot be correlated with anything the directory sends — including a future SCIM `externalId`. The **object id** carried in a SAML assertion is stable and tenant-wide, which is what Modem needs.

## Prerequisites

* Enterprise SSO enabled for your Modem organization, and the **owner** role in it
* Permission to create and configure enterprise applications in your Entra tenant
* Access to DNS for the email domain you are claiming

## Setup

Setup runs in two passes, because Entra needs an Identifier (Entity ID) that Modem only issues once the provider exists.

<Steps>
  <Step title="Create the enterprise application">
    In the Microsoft Entra admin center, go to **Enterprise applications** → **New application** → **Create your own application**,
    choose **Integrate any other application you don't find in the gallery**, name it something like `Modem`, and create it.
  </Step>

  <Step title="Open single sign-on and choose SAML">
    In the new application, go to **Single sign-on** and choose **SAML**.
  </Step>

  <Step title="Fill in the Basic SAML Configuration">
    Edit **Basic SAML Configuration** and set:

    | Field                                          | Value                                                                                  |
    | ---------------------------------------------- | -------------------------------------------------------------------------------------- |
    | **Identifier (Entity ID)**                     | A placeholder for now, for example `https://app.modem.dev`. You replace this in step 7 |
    | **Reply URL (Assertion Consumer Service URL)** | The ACS URL from Modem, `https://app.modem.dev/api/auth/sso/saml2/sp/acs/org-<id>`     |
    | **Sign on URL**                                | `https://app.modem.dev/auth/login`                                                     |
  </Step>

  <Step title="Set the Unique User Identifier and claims">
    Edit **Attributes & Claims**.

    Set the **Unique User Identifier (Name ID)** to the source attribute `user.objectid`, with the format **Persistent** (or
    **Unspecified**). See [Sending the Entra object id](#sending-the-entra-object-id) below.

    Then add three claims with these exact names:

    | Claim name  | Source attribute |
    | ----------- | ---------------- |
    | `email`     | `user.mail`      |
    | `givenName` | `user.givenname` |
    | `surname`   | `user.surname`   |

    <Warning>
      Entra's *default* claim names are long URIs such as
      `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`. Modem reads the short names, so each claim's **Name**
      must be set to `email`, `givenName`, or `surname` with the **Namespace** field left **empty**.
    </Warning>
  </Step>

  <Step title="Download the signing certificate">
    Under **SAML Signing Certificate**, download **Certificate (Base64)**. Alternatively, open the **App Federation Metadata Url**
    and copy the XML document it serves — Modem accepts either the certificate or the metadata XML itself. Paste the XML, not the
    URL: Modem does not fetch it for you.
  </Step>

  <Step title="Register Entra in Modem">
    From the **Set up** panel at the bottom of the single sign-on page, copy the **Login URL** (the sign-on URL) and the **Microsoft
    Entra Identifier** (the issuer / entity id).

    In the [Modem dashboard](https://app.modem.dev), go to **Settings** → **SSO**, choose SAML 2.0, and enter the login URL, the Entra
    identifier, and the certificate (or the federation metadata XML), along with the email domain you are claiming.
  </Step>

  <Step title="Paste Modem's SP Entity ID back into Entra">
    The SSO settings page now shows Modem's **SP Entity ID (Audience URI)**. Copy it exactly, return to **Basic SAML Configuration**,
    and replace the placeholder **Identifier (Entity ID)** with it. Save.

    <Note>
      The SP Entity ID will look like your Entra tenant's own identifier URL. That is expected — copy it exactly as Modem shows it
      rather than adjusting it to look more like a Modem URL.
    </Note>
  </Step>

  <Step title="Assign users and groups">
    Under **Users and groups**, assign the people or groups who should have access to Modem. Anyone not assigned cannot sign in.
  </Step>

  <Step title="Verify your email domain">
    Publish the DNS TXT record Modem shows on the SSO settings page and click verify. Sign-in is refused until this succeeds — see
    [Domain verification](/docs/enterprise/sso#domain-verification).
  </Step>
</Steps>

## Sending the Entra object id

The **Unique User Identifier (Name ID)** must be `user.objectid` — the directory object id — and not the user's mail or UPN.

<Warning>
  The NameID is the key Modem hangs the account off, and it must be a stable, immutable id. [Directory
  Sync](/docs/enterprise/scim) matches directory users to Modem users by **`externalId`**, which has to be the **same value** — the object
  id. Entra's provisioning default sends `mailNickname` instead, so if you turn provisioning on you must change that mapping to
  `objectId`; see [Microsoft Entra ID provisioning](/docs/enterprise/scim-entra#matching-the-sso-identity).

  Email addresses and UPNs change. Matching on either is how an account ends up handed to the wrong person.
</Warning>

## Attribute mapping

| What Modem wants | Entra value                                        | Notes                                                                          |
| ---------------- | -------------------------------------------------- | ------------------------------------------------------------------------------ |
| Account identity | Unique User Identifier (Name ID) = `user.objectid` | Format `Persistent` or `Unspecified`                                           |
| Email            | Claim `email` = `user.mail`                        | Short name, empty namespace. Modem falls back to the NameID if this is missing |
| First name       | Claim `givenName` = `user.givenname`               | Short name, empty namespace                                                    |
| Last name        | Claim `surname` = `user.surname`                   | Short name, empty namespace                                                    |

## Testing the sign-in

Sign out of Modem, or use a private window, then:

1. Go to `https://app.modem.dev`
2. Click **Continue with SSO**
3. Enter your work email address, or your Modem organization slug
4. Complete the Microsoft prompt

You should land back in Modem signed in. A user who has never used Modem before gets an account and joins as a **member**, unless they had a pending invitation carrying a different role.

<Warning>
  Do not test from the **My Apps** tile. Modem accepts **SP-initiated** sign-in only, so an IdP-initiated launch is rejected with "Start
  single sign-on from Modem". This is the single most common support question — it is worth telling your team up front to start from the
  Modem sign-in page.
</Warning>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Start single sign-on from Modem">
    The sign-in started from the Entra **My Apps** tile rather than from Modem. Go to `https://app.modem.dev` and click **Continue with
    SSO**. Setting the app's **Sign on URL** to `https://app.modem.dev/auth/login` makes the tile send people to the right place.
  </Accordion>

  <Accordion title="Single sign-on is not finished being set up">
    The domain has not been verified yet. Publish the DNS TXT record from the SSO settings page and click verify. DNS can take minutes
    to hours to propagate; retrying is safe.
  </Accordion>

  <Accordion title="Entra reports an identifier or reply URL mismatch">
    The **Identifier (Entity ID)** in Entra does not match the SP Entity ID Modem shows, or the **Reply URL** is not the ACS URL from
    Modem. Copy both again from the SSO settings page, character for character.
  </Accordion>

  <Accordion title="Users sign in but have no name or email">
    The claims are almost certainly still using Entra's default URI names. Edit each claim so its **Name** is the short `email`,
    `givenName`, or `surname` and its **Namespace** is empty.
  </Accordion>

  <Accordion title="The signing certificate expired">
    Entra SAML signing certificates have an expiry, and can be rolled early. After a roll, download the new **Certificate (Base64)** and
    update it on the Modem SSO settings page, otherwise assertions stop validating.
  </Accordion>

  <Accordion title="A user is not assigned">
    Entra refuses the sign-in before it ever reaches Modem if the person is not assigned to the application. Check **Users and groups**.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="Enterprise SSO" icon="https://mintcdn.com/modem-844d7a4a/Wr2r4IRr97lNQiQb/icons/shield.svg?fit=max&auto=format&n=Wr2r4IRr97lNQiQb&q=85&s=ee1ca3093fcbdf45ec5dc1a74652bed6" href="/docs/enterprise/sso" width="24" height="24" data-path="icons/shield.svg">
    Requirements, domain verification, and sign-in behaviour.
  </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>
