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_URLset (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
- Open Settings → Single sign-on → Add provider.
- Set Provider to Microsoft Entra ID.
- 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:
-
Identity → Applications → App registrations → New registration.
Entra field Value Name Measured Cloud Supported account types Accounts in this organizational directory only (single tenant) Redirect URI Platform Web, and the Sign-in redirect URI from Measured Cloud, exactly as shown -
Register. On the app's Overview, copy the Application (client) ID and the Directory (tenant) ID.
-
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.
-
Token configuration → Add optional claim → ID, and tick email and xms_edov. Accept the prompt to turn on the Microsoft Graph
emailpermission. See Whyxms_edovbelow. -
API permissions: the app needs the delegated Microsoft Graph permissions
openid,emailandprofile. Click Grant admin consent for <your tenant> so people aren't asked to consent one by one. -
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 field | Value |
|---|---|
| Display name | What your team sees on the sign-in page, e.g. Microsoft. |
| Directory (tenant) ID | From the app's Overview. |
| Client ID | The Application (client) ID. |
| Client secret | The secret's Value. It's encrypted at rest under your org's data-encryption key. |
| Default role for new users | The 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
- In a private browser window, open
https://dq.example.com/login, choose Sign in with SSO and enter your org slug. - Sign in with a work account from the tenant.
- 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:
| Claim | Used for |
|---|---|
iss, aud, exp, nonce | Checked 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. |
tid | Must equal the configured Directory (tenant) ID. |
sub | The person's permanent link to this provider. |
email | The account's email address. |
xms_edov | When true, the email counts as verified (see below). |
preferred_username, then upn | Used as the email address when Entra sends no email (an account without a mailbox, for example). Never treated as verified. |
name | The display name of a new account. |
groups or roles | Optional 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
groupsclaim 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:
-
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).
-
Single sign-on → SAML. Under Basic SAML Configuration:
Entra field Value 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 -
Under Attributes & Claims, set Unique User Identifier (Name ID) to
user.objectidwith format Persistent. The default,user.userprincipalname, changes when someone's sign-in name changes, which would break their link. Keep the defaultemailaddressclaim (user.mail). -
Assign people or groups under Users and groups.
-
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
| Symptom | Likely cause |
|---|---|
| The form says the tenant is a multi-tenant endpoint | You entered common, organizations or consumers. Use the Directory (tenant) ID from the app's Overview. |
Discover says issuer mismatch | The 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_error | The 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_unverified | An existing account was matched without a verified email. Add the email and xms_edov optional claims (step 2.4). |
sso_error=not_provisioned | The 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.
Related
- Configure SSO: the general SSO guide, enforcement and step-up.
- Provision users from Microsoft Entra ID via SCIM: keep accounts and groups in sync automatically.
- Configure single sign-on with Okta