Skip to main content

Configure single sign-on with Microsoft Entra ID

Connect your Microsoft Entra ID tenant (formerly Azure AD) to Measured Cloud so your team signs in with their work accounts. OpenID Connect (OIDC) is the recommended setup; SAML 2.0 is covered at the end.

Goal​

People in your Entra tenant sign in to Measured Cloud through Microsoft. Someone signing in for the first time gets an account automatically (if you turn that on), and you can then require Entra for everyone in your org.

Prereqs​

  • The super admin role in Measured Cloud. Only a super admin can add or change an identity provider.
  • An Entra role that can register applications (Application Developer or Cloud Application Administrator) and grant consent.
  • A Measured Cloud deployment with PUBLIC_BASE_URL set (see Configuration). Every URL you paste into Entra is built from it. If it isn't set, the Add provider form says so and SSO can't work.

One tenant only​

A Measured Cloud provider trusts one Entra tenant. Microsoft's multi-tenant endpoints (common, organizations, consumers) accept a sign-in from any Microsoft tenant, so Measured Cloud refuses them:

  • the form only accepts a Directory (tenant) ID, a GUID;
  • the issuer is https://login.microsoftonline.com/<tenant-id>/v2.0, and the issuer in Microsoft's discovery document and in every ID token must match it exactly;
  • every ID token's tid (tenant ID) claim must equal the configured tenant.

A sign-in from any other tenant fails with sso_error=idp_error.

1. Start the provider in Measured Cloud​

  1. Open Settings → Single sign-on → Add provider.
  2. Set Provider to Microsoft Entra ID.
  3. Leave the form open. The Copy these into Microsoft Entra box shows the Sign-in redirect URI, for example https://dq.example.com/auth/sso/<your-org-slug>/callback.

2. Register the app in Entra​

In the Microsoft Entra admin center:

  1. Identity → Applications → App registrations → New registration.

    Entra fieldValue
    NameMeasured Cloud
    Supported account typesAccounts in this organizational directory only (single tenant)
    Redirect URIPlatform Web, and the Sign-in redirect URI from Measured Cloud, exactly as shown
  2. Register. On the app's Overview, copy the Application (client) ID and the Directory (tenant) ID.

  3. Certificates & secrets → Client secrets → New client secret. Copy the secret's Value (not its Secret ID). Note when it expires; see Rotate the client secret.

  4. Token configuration → Add optional claim → ID, and tick email and xms_edov. Accept the prompt to turn on the Microsoft Graph email permission. See Why xms_edov below.

  5. API permissions: the app needs the delegated Microsoft Graph permissions openid, email and profile. Click Grant admin consent for <your tenant> so people aren't asked to consent one by one.

  6. Optional, to limit who can sign in: in Enterprise applications, open the app, set Properties → Assignment required? to Yes, and add people or groups under Users and groups. Otherwise anyone in the tenant can reach the sign-in (whether they get in still depends on the auto-provisioning setting below).

3. Finish the provider in Measured Cloud​

Back in the Add provider form:

Measured Cloud fieldValue
Display nameWhat your team sees on the sign-in page, e.g. Microsoft.
Directory (tenant) IDFrom the app's Overview.
Client IDThe Application (client) ID.
Client secretThe secret's Value. It's encrypted at rest under your org's data-encryption key.
Default role for new usersThe role a person gets the first time they sign in. Viewer is the safest start.

The Issuer URL fills itself in: https://login.microsoftonline.com/<tenant-id>/v2.0. Click Discover to fetch the endpoints from <issuer>/.well-known/openid-configuration.

Tick Auto-provision new users on first sign-in if people who don't have a Measured Cloud account yet should get one. Leave Enforce unticked for now. Click Save.

4. Test it​

  1. In a private browser window, open https://dq.example.com/login, choose Sign in with SSO and enter your org slug.
  2. Sign in with a work account from the tenant.
  3. You land in Measured Cloud, signed in.

If you're a super admin or technical admin with an existing password account, link it first: see Link a super admin or technical admin account. Admin accounts are never linked automatically.

When everything works, edit the provider and tick Enforce to turn off password sign-in for your org. Do this only after a super admin has signed in through Entra at least once.

What Measured Cloud reads from Entra​

Measured Cloud asks for the scopes openid email profile (no offline_access: it doesn't use Microsoft's refresh tokens) and reads these ID token claims:

ClaimUsed for
iss, aud, exp, nonceChecked on every sign-in. iss must equal the configured issuer, aud the client ID, and nonce the value Measured Cloud sent. The signature is checked against Microsoft's published keys.
tidMust equal the configured Directory (tenant) ID.
subThe person's permanent link to this provider.
emailThe account's email address.
xms_edovWhen true, the email counts as verified (see below).
preferred_username, then upnUsed as the email address when Entra sends no email (an account without a mailbox, for example). Never treated as verified.
nameThe display name of a new account.
groups or rolesOptional team mapping (below).

Why xms_edov​

Entra never sends the standard email_verified claim, and preferred_username / upn can be changed and aren't verified. Measured Cloud only matches a sign-in to an existing account by email when the email is verified, so the person who already has a Measured Cloud account (invited by email, or signing in with a password today) needs a verified email to sign in through Entra the first time.

xms_edov ("email domain owner verified") is Microsoft's signal that the email claim's domain is verified in your tenant. With it on, those people's existing accounts are linked on their first Entra sign-in. Without it, they get sso_error=email_unverified. People without an account are not affected: with auto-provisioning on, a new account is created keyed on sub.

Map Entra groups to teams​

Measured Cloud can put people into teams from the groups (or roles) claim on every sign-in.

In Entra: Token configuration → Add groups claim. Pick Groups assigned to the application (recommended: it keeps the claim short) or Security groups. For the ID token, keep Group ID. Entra then sends each group's Object ID.

In Measured Cloud, a team whose external group id equals a group's Object ID gets that group's members. Set it with PATCH /api/v1/organizations/{org_id}/teams/{team_id} and {"external_group_id": "<object id>"}. A team pushed by SCIM from Entra carries the group's Object ID already.

Only memberships added this way are removed when someone leaves the group. If someone is in more than 200 groups, Entra leaves the groups claim out of the token; Measured Cloud then changes nothing for that sign-in rather than removing them from every team. Groups assigned to the application avoids this.

Map Entra groups to roles​

The same groups claim can also set a person's org role. Edit the provider and add rows under Role mappings: a group's Object ID (Entra sends IDs, not names) and the role it grants (viewer, editor, technical admin, or super admin).

Mappings are checked when someone is provisioned and again each time a person linked to this provider signs in:

  • The highest matching role wins. Someone in a viewer group and an editor group becomes an editor.
  • A match sets the role. A technical admin who is now only in a group mapped to viewer becomes a viewer at their next sign-in.
  • No match, no change. Someone in none of the mapped groups keeps the provider's Default role for new users the first time, and their current role after that. Mappings never demote a person who matches nothing, and a sign-in whose token leaves the groups claim out (the 200-group limit above) changes nothing.
  • Super admin needs an opt-in. A group can grant super admin only after you tick Allow a group to grant super admin. Without it, the provider can't create super admins, and it never changes the role of an existing super admin.
  • The last super admin stays. A mapping never demotes the org's last super admin.

Every role a mapping changes is written to the audit log as org_membership.role_mapped_by_sso, with the actor sso, the old and new role, and the groups that matched. The change applies from the person's next session.

Use groups that only your Entra administrators can change. Whoever can add people to a mapped group can grant that role.

Rotate the client secret​

Entra client secrets expire. Before yours does, create a new secret in Certificates & secrets, then in Measured Cloud open Settings → Single sign-on, click the provider's Edit icon, paste the new value into Client secret and click Save. Saving asks you to confirm your sign-in if it's more than five minutes old.

The form never shows the stored secret: the field reads Unchanged, and leaving it blank keeps the secret on file. If you change the Directory (tenant) ID, enter the secret again: Measured Cloud never sends a stored secret to a different issuer, and it re-checks the new issuer's discovery document before saving.

To do the same with the API:

curl -X PATCH "https://dq.example.com/api/v1/organizations/$ORG_ID/identity-providers/$IDP_ID" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"config": {"provider": "entra", "tenant_id": "<tenant-id>", "client_id": "<client-id>", "client_secret": "<new secret value>"}}'

$TOKEN must be a super admin's session access token less than five minutes old (from POST /auth/login, or re-confirmed with POST /auth/elevate): changing an identity provider needs a recent sign-in, so a personal API key can't do it. Send the whole config: a plain field you leave out is cleared, while a secret you leave out is kept. Don't delete and re-add the provider instead; that breaks every person's link to it.

Use SAML instead​

Pick Microsoft Entra ID (SAML) as the provider. The form shows the ACS URL and the SP entity ID.

In the Entra admin center:

  1. Identity → Applications → Enterprise applications → New application → Create your own application, and choose Integrate any other application you don't find in the gallery (Non-gallery).

  2. Single sign-on → SAML. Under Basic SAML Configuration:

    Entra fieldValue
    Identifier (Entity ID)The SP entity ID from Measured Cloud (your PUBLIC_BASE_URL)
    Reply URL (Assertion Consumer Service URL)The ACS URL from Measured Cloud
  3. Under Attributes & Claims, set Unique User Identifier (Name ID) to user.objectid with format Persistent. The default, user.userprincipalname, changes when someone's sign-in name changes, which would break their link. Keep the default emailaddress claim (user.mail).

  4. Assign people or groups under Users and groups.

  5. Under SAML Certificates, copy the App Federation Metadata Url, paste it into IdP metadata URL in Measured Cloud and click Fetch. That fills in the entity ID, SSO URL and certificate.

SAML assertions carry no "email verified" signal, so over SAML an existing Measured Cloud account can't be matched by email. SAML signs in people who don't have an account yet (with auto-provisioning on) and people already linked to the provider. If your users already have accounts, use OIDC.

SAML needs the optional dq-cloud-api[saml] install on a self-hosted deployment; see Configure SSO.

Troubleshooting​

SymptomLikely cause
The form says the tenant is a multi-tenant endpointYou entered common, organizations or consumers. Use the Directory (tenant) ID from the app's Overview.
Discover says issuer mismatchThe tenant ID is wrong, or you entered a domain name. Use the GUID.
Microsoft shows AADSTS50011 (redirect URI mismatch)The redirect URI in the app registration doesn't match the one Measured Cloud shows, character for character, or it's under a platform other than Web.
Microsoft shows AADSTS7000215 (invalid client secret)You copied the secret's ID instead of its Value, or it expired.
sso_error=idp_errorThe token's tenant didn't match, the secret is wrong, or Microsoft returned an error. The server log line sso_callback_failed has the detail.
sso_error=email_unverifiedAn existing account was matched without a verified email. Add the email and xms_edov optional claims (step 2.4).
sso_error=not_provisionedThe person has no Measured Cloud account and auto-provisioning is off. Invite them, or turn auto-provisioning on.

More codes are listed in Configure SSO.