MountainGoat · Single Sign-On & Provisioning

Microsoft Entra ID SSO & Provisioning: MountainGoat Configuration Guide

For Microsoft Entra administrators connecting a Microsoft 365 tenant to a MountainGoat instance for sign-in, and optionally for automatic user provisioning.

This guide walks you through enabling Sign in with Microsoft for your MountainGoat instance using OpenID Connect (OIDC), and optionally SCIM provisioning so Entra creates, updates, and deactivates MountainGoat users automatically. At a glance:

Looking for email sync instead? This guide covers signing in to MountainGoat. To let MountainGoat read purchase-order email from a Microsoft 365 mailbox, see the Outlook Email Sync (Microsoft Entra) guide. The sign-in registration in this guide is a separate app from the mailbox one; if you already registered an app for email sync, leave it as it is and create a new registration here.

1.Overview and security model

MountainGoat supports Microsoft Entra ID as an OIDC single sign-on provider, a peer of Sign in with Okta. When SSO is enabled, your users see a Sign in with Microsoft button on the MountainGoat login page and can also launch MountainGoat from their My Apps portal.

Supported: SP-initiated SSO, the My Apps tile, Just-In-Time account creation, app-role mapping, and optional SCIM 2.0 provisioning. Not supported: Single Logout (SLO), multi-tenant app registrations, and force authentication.

2.Decide first: SSO only, or SSO + provisioning?

SSO alone is a complete setup. Steps 1–9 give your users Sign in with Microsoft, app-role-driven MountainGoat roles, and Require SSO if you want it. You create one Entra app, you need no Entra ID license tier, and you are done. Most instances stop here; accounts are created by invitation from the Users tab, exactly as they are without SSO.

SCIM provisioning is optional, and it is what makes offboarding a push from Entra rather than a refusal at next login. Add it when you want Entra to create, update, and deactivate MountainGoat accounts for you. It requires Entra ID P1 and a second Entra app.

PathEntra appsLicenseSteps
SSO only 1: App registrations → New registration (single tenant) Any tenant, no P1 1–9, then stop
SSO + provisioning That one, plus an Enterprise applications → New application → Create your own applicationIntegrate any other application you don't find in the gallery (Non-gallery) Entra ID P1 1–9, then 10–23

If you are adding provisioning, know this before you start, because it is the single most common surprise here: Entra offers Provisioning → Automatic only on a non-gallery enterprise application you create yourself. The enterprise application Entra generates automatically behind your sign-in App registration does not offer it; its Provisioning blade is empty or offers manual only. There is no setting that turns this on. The second app is the supported path.

The two apps are tied together by the user's directory object id, which is identical in both. That is why the externalId mapping in step 16a is mandatory. Assignments are per app: app roles on the sign-in app drive MountainGoat roles, and users and groups on the provisioning app decide who gets provisioned. Assign the same people to both.

3.Prerequisites

Test instance. The shared instance for review and testing is demo.mountaingoat.ai (for example, start SSO at https://demo.mountaingoat.ai/auth/entra/login). Production clients each use their own {app.subdomain}.mountaingoat.ai host.

4.Set up the sign-in app in Entra

Sign in to the Microsoft Entra admin center at https://entra.microsoft.com (or https://portal.azure.com → Microsoft Entra ID), then:

  1. App registrations → New registration, single tenant (Accounts in this organizational directory only). From the app's Overview page, note the Directory (tenant) ID and Application (client) ID.
  2. Redirect URI (Web): paste the value shown in the MountainGoat SSO panel; the panel pre-fills it and offers a Copy button. It has this shape:
    • Redirect URI (Web) https://{app.subdomain}.mountaingoat.ai/auth/entra/callback
    • SP-initiated login URL (open this to start SSO) https://{app.subdomain}.mountaingoat.ai/auth/entra/login
  3. Certificates & secrets → New client secret. Copy the secret value now; it is entered once in MountainGoat and never shown again. Note the expiry date too.
  4. App roles: create roles named for MountainGoat (for example MG-Admin, MG-Manager, MG-Editor, MG-Viewer), then assign users or groups to those roles on the app's Enterprise application entry. App-role names arrive in the token's roles claim, the recommended source, readable in the mappings JSON (see section 6).
    • Fallback for organizations that do not use app roles: Token configuration → add the groups claim, set MountainGoat's Group Claim to groups, and map group GUIDs instead of names.
    • On a free tenant, assign users to app roles; assigning groups to app roles needs Entra ID P1.
  5. Optional (My Apps tile): set the Enterprise application's Home page URL to https://{app.subdomain}.mountaingoat.ai/auth/entra/login. The tile launch is plain SP-initiated sign-in; no separate initiate-login URI exists for Entra.

Already have a MountainGoat app registration for Outlook email sync? That app grants read-only mailbox access and stays as it is. Sign-in uses this new, separate registration; the two are never combined. See the Outlook Email Sync guide for the mailbox side.

5.Enter the credentials in MountainGoat

Sign in to your MountainGoat instance as an administrator, click Settings under the user profile, then select the Admin tab → API & CredentialsSSO CredentialsEntra ID Credentials.

  1. Paste the Tenant ID, Client ID, and Client Secret; confirm the pre-filled Redirect URI; choose the Group Claim (roles is the default); map roles under Group/Role Mappings; set the Default Role; set the JIT Mode: strict if you are doing SSO only, mapped if you are going on to set up provisioning (see section 7 for why); set Enabled to Yes; Save.
  2. Test connection. Green means your tenant's discovery document and signing keys are reachable and the issuer resolved. The result is kept as a last-tested chip in the panel.
  3. Sign out and verify Sign in with Microsoft appears on the login page. Sign in with a test user, then confirm the mapped role and the sign-in entry in the SSO Status panel's audit trail.
  4. Only after a successful Entra sign-in by a second full admin: optionally switch Require SSO on (the shared switch in the SSO Policy block; it is saved with either provider's Save button). The panel refuses the switch while no SSO provider is available, and a startup self-check protects against locking the instance out either way.

About the Client Secret. The secret is write-only in the Admin UI: you can enter or replace it, but MountainGoat never displays it back and stores it encrypted. On a later edit, leave the Client Secret blank to keep the existing secret. Only type in the field when you intend to replace it.

Doing SSO only? You are done. Accounts stay invitation-managed from the Users tab, and nothing in section 9 applies to you.

6.User roles and access

MountainGoat has five access roles: No access, View only, PO edit, Manager, and Full admin.

RoleWhat it grants
Full admin full_adminFull administrator. All Admin tabs, PO Dashboard edit, and PO assignment rights.
Manager managerPO Dashboard edit plus PO assignment management. No Admin access.
PO edit po_editPO Dashboard edit and can be assigned POs. No Admin or manager access.
View only view_onlyPO Dashboard view-only access. Cannot be assigned POs.
No access noneNo default application access.

Recommended: app roles

App roles (step 4) are the recommended way to carry role information from Entra: they are assigned per application, their names arrive in the roles claim, and the Group/Role Mappings stay readable (MG-Adminfull_admin, and so on). Keep MountainGoat's Group Claim on roles.

Fallback: the groups claim

If your organization does not use app roles, add the groups claim under the app registration's Token configuration, set MountainGoat's Group Claim to groups, and map group GUIDs instead of names.

Very large directories. When a user belongs to 200 or more groups, Entra can omit the group claim from the token. MountainGoat degrades safely: the sign-in still succeeds, new users receive the Default Role, existing users keep their current role (never a demotion), and a group_overage_default_role entry is written to the audit trail. App roles avoid this limit entirely, which is another reason to prefer them.

No mappings at all

Mappings are optional. Without them, users receive the Default Role and your MountainGoat administrator assigns roles by hand under Settings → Admin → Users. Entra confirms who the person is, and MountainGoat controls what they can do.

7.Provisioning modes (JIT)

The JIT Mode field decides what happens when someone signs in through Entra who has no MountainGoat account yet:

JIT ModeBehavior
strict
recommended steady state
Only existing active MountainGoat users can sign in; on first successful login the account links by verified email. Unknown users are refused with unknown_user_strict_mode.
view_only Unknown users are created with PO Dashboard view-only access.
mapped Unknown users are created using the Group/Role Mappings, falling back to the Default Role.

strict is the recommended steady state either way; it keeps account creation a deliberate act. Which value you start on depends on which path you are taking:

Changing the mode is a Save on the same form and takes effect on the next sign-in.

8.Sign-in email and allowed domains

The sign-in email is resolved from the token by precedence: email, then preferred_username (when it contains @), then upn (when it contains @). Which claim was used is recorded in the audit trail per login, so a tenant whose UPNs are not real mailboxes is diagnosable. A token with no resolvable email is refused, never linked to a guessed identity.

This precedence is also why the SCIM userName mapping in step 16 matters: provisioning must write the same address sign-in will resolve, or the same person arrives twice.

Allowed Email Domains (optional): enter one or more domains separated by commas, for example acme.com, partner.com, to limit sign-in to those domains. Everyone else is denied with email_domain_not_allowed. The restriction applies to the resolved email value. Leave the field blank to allow any domain your Entra assignment permits.

9.SCIM provisioning (optional)

Everything in this section is optional. If SSO alone is what you wanted, you finished at step 9: accounts stay invitation-managed from the Users tab, and nothing here applies to you.

Add this section when you want Entra's provisioning service to create, update, and deactivate MountainGoat users automatically over SCIM 2.0, chiefly so that offboarding is a push from Entra rather than a refusal at next login. It is a platform capability on every MountainGoat instance, no extra module required, but it requires Entra ID P1 (or above) on your tenant: Microsoft gates automatic provisioning behind it.

Before you start, re-read section 2. Steps 12–13 create the second Entra app it describes.

In MountainGoat: generate the token

  1. In the SCIM Provisioning section of the same SSO Credentials pane, switch Provisioning Enabled to Yes and click Save SCIM Config. This switch is also the kill switch: turning it off refuses every SCIM request immediately, even with a valid token.
  2. Enter a token label (for example Entra prod) and click Generate Token. The token is shown exactly once; copy it now. It is stored hashed and can never be displayed again. Copy the read-only Tenant URL too:
    • Tenant URL https://{app.subdomain}.mountaingoat.ai/scim/v2?aadOptscim062020
    A blank label is refused. Refusals show in the message line at the top of the SCIM Provisioning section, above the Provisioning Enabled switch; if a click seems to do nothing, look up there rather than at the button.

In Entra: create the provisioning app

  1. Enterprise applications → New application → Create your own application. Name it something you will recognize beside the sign-in app (for example MountainGoat Provisioning), choose Integrate any other application you don't find in the gallery (Non-gallery), and Create. This second app is required: automatic provisioning is not offered on the enterprise application behind your sign-in registration (see section 2).
  2. Open the new app → ProvisioningGet started → set Provisioning Mode to Automatic.

In Entra: connect it

  1. Under Admin Credentials, paste the MountainGoat Tenant URL into Tenant URL and the generated token into Secret Token, then click Test Connection. Green means Entra reached your instance and the token was accepted. A red result here is almost always the token (copied with trailing whitespace, already rotated, or revoked) or the Provisioning Enabled switch being off; either refusal is recorded in the panel's Provisioning Activity readout.
  2. Save the Admin Credentials. The Mappings section appears only after a successful save.

In Entra: fix the mappings (do not skip this)

  1. Open Mappings → Provision Microsoft Entra ID Users. Entra ships this app with a default mapping set MountainGoat does not accept as-is. Two edits are required.

    16a: Change externalId to objectId. This is mandatory. The default source for externalId on a non-gallery app is mailNickname. Click that row and change the source attribute to objectId.

    If you leave externalId on mailNickname, identity correlation breaks. MountainGoat stores each Entra user's directory object id as the account's identity when they sign in. Provisioning looks a user up by externalId before deciding whether to create them. With mailNickname there, that lookup never matches an account that has already signed in, so Entra tries to create someone who already exists, MountainGoat refuses the duplicate email with a 409 uniqueness error, and the cycle reports errors on exactly the people who were working fine. mailNickname is also editable in the directory, so it can change out from under the link; objectId never does.

    16b: Delete every mapping row that is not on this list. MountainGoat implements the attribute subset it actually stores. Entra sends changed attributes as explicit SCIM paths, and a path outside this list is refused with 400 invalidPath; one such row makes every update fail even though the initial create succeeded. Keep exactly these seven rows:

    Keep this SCIM attributeSource it to
    userNameuserPrincipalName (the default), but see the note below
    activeNot([IsSoftDeleted]) (the default)
    displayNamedisplayName (the default)
    name.givenNamegivenName (the default)
    name.familyNamesurname (the default)
    externalIdobjectId (changed in 16a)
    emails[type eq "work"].valuemail (the default)

    Delete all the rest. The rows Entra adds by default that MountainGoat refuses include name.formatted, preferredLanguage, title, every addresses[...] row (streetAddress, locality, region, postalCode, country, formatted) and every phoneNumbers[...] row (work, mobile, fax). Anything under the enterprise-user extension schema (department, manager, employeeNumber) goes too. None of them map to a MountainGoat field, so deleting them loses nothing; job title in particular is a MountainGoat field you set in MountainGoat, not one provisioning fills in.

    On userName: MountainGoat resolves the sign-in email as emailpreferred_usernameupn, and for most tenants the email claim comes from the user's mail attribute. If your users' UPNs are their real mailboxes, Entra's userPrincipalName default is fine; leave it. If they are not, change the source to the expression Coalesce([mail], [userPrincipalName]) so provisioning writes the address sign-in will resolve. Getting this wrong makes the same person arrive as two accounts.

  2. Leave Match users based on as it ships (userName, matching precedence 1). Save the mappings.

In Entra: assign, test, and start

  1. Users and groups → Add user/group. Assign the same people you assigned to app roles on the sign-in app. Assignment on this app controls who gets provisioned; assignment on the sign-in app controls what role they get.
  2. Provision on demand for one test user. Read the result screen: it names each attribute it sent and the response it got. A green create means MountainGoat accepted it.
  3. In MountainGoat's Users tab, confirm the test user appears with the Entra badge, the Provisioned chip, and the Default Role from the Entra credentials form. Check the panel's Provisioning Activity readout too.

    First and Last name blank? That is not a MountainGoat fault. Entra sends whatever givenName and surname hold, and plenty of directories leave those empty even when the display name looks fine, so such a person reads as nameless in the Users table. Populate First name and Last name on the user in Entra and provision on demand again. A name typed into MountainGoat instead can be overwritten the next time Entra syncs that user.

  4. Start provisioning. The first cycle takes up to about 40 minutes. Afterwards, verify the create, update, and deactivate counts in the Provisioning Activity readout.
  5. Now tighten JIT to strict on the Entra ID Credentials form, per section 7.
  6. Deprovision test: disable the test user in Entra, provision on demand, and confirm the MountainGoat account deactivates and any open session ends on its next request.

Behavior to know

10.Troubleshooting

Every failed Entra sign-in shows a short error code on a clear error page and writes the same code to the audit trail. The SSO Status panel shows the last error reason with its time; it never shows secrets, tokens, raw claims, or signing keys.

Sign-in errors

Error codeCauseFix
entra_not_configured The provider is disabled or a required field is missing. Finish the Entra ID Credentials form and set Enabled to Yes.
entra_discovery_unavailable login.microsoftonline.com discovery is unreachable and no cached document exists. Check the instance's egress to login.microsoftonline.com (firewall or proxy) and Microsoft service health. The Test connection button isolates this without a sign-in.
invalid_tenant The token's tenant does not match the configured Tenant ID. The app registration lives in a different tenant than configured, or a multi-tenant app is being reused. Register a single-tenant app in the right directory.
missing_email_claim No usable email in email, preferred_username, or upn. Add an email claim in Token configuration, or populate the user's mail attributes.
missing_object_id The token carries no oid claim. Almost always a token configuration problem; MountainGoat refuses rather than link an unstable identity. Review the app registration's token configuration.
email_conflict_inactive_user A deactivated MountainGoat account already owns this email. Reactivate (or rename) that account deliberately; sign-in is refused rather than silently resurrecting or duplicating it.
unknown_user_strict_mode JIT Mode is strict and this person has no MountainGoat account yet. Invite them, provision them, or switch JIT Mode deliberately. During a first setup this usually means JIT was tightened to strict before provisioning had run; see section 7.
email_domain_not_allowed The resolved email's domain is outside Allowed Email Domains. Add the domain to Allowed Email Domains, or clear the restriction.
group_overage_default_role Not a failure. The user belongs to 200+ groups, so the group claim was omitted; the sign-in succeeded on the Default Role or the user's existing role. Prefer app roles (the roles claim), which do not hit the overage limit.
invalid_state, invalid_nonce The sign-in session did not match, often from an old or reused callback link. Start sign-in again from the MountainGoat login page.
expired_token The ID token had already expired when it reached MountainGoat. Start sign-in again. If it keeps happening, confirm the system clocks are accurate.

Provisioning errors

Entra reports these on the provisioning app's Provisioning logs; the matching refusal also lands in MountainGoat's Provisioning Activity readout.

SymptomCauseFix
invalidPath / "Unsupported PATCH path" A mapping row outside the seven-row keep-list. This typically shows up only after the first successful create, on the first update. Redo step 16b.
uniqueness / 409 on create The email already belongs to another MountainGoat account. Either externalId is not sourced from objectId (step 16a), or userName is writing a different address than sign-in resolves (the userName note in step 16).
401 on every request The token is wrong, was rotated, or was revoked. Generate a new token and paste it into Admin Credentials.
403 on every request, including a token that used to work Provisioning Enabled is off in MountainGoat. It is the kill switch, and it is checked before the token. Switch Provisioning Enabled back on and save.
Quarantined Entra quarantines an endpoint after repeated failures. Fix the cause, then use Restart provisioning; a corrected mapping alone does not clear quarantine.

11.Requirements

12.Support

For help configuring Microsoft Entra SSO or SCIM provisioning for MountainGoat, contact:

help@mountaingoat.ai