For the complete documentation index, see llms.txt. This page is also available as Markdown.

SCIM through Entra

This guide covers the core SCIM setup: enabling SCIM in Stack AI, creating the Entra enterprise app, configuring attribute mappings for users, assigning users, and verifying that provisioning works.


Prerequisites

  • Stack AI organization admin access

  • Microsoft Entra tenant with privileges to create Enterprise applications and edit App Registrations

  • A modern browser tab open to each side


Step 1 — Enable SCIM in Stack AI

  1. Sign in to Stack AI as an org admin.

  2. Open Settings → SCIM Provisioning.

  3. Click Enable SCIM and confirm. This creates a scim_provisioning_configs row for your org and unlocks the SCIM endpoints.

  4. From the Overview card, copy two values — you'll need them on the Entra side:

    • Base URL — looks like https://api.stack-ai.com/scim/v2

    • SCIM token — click Generate token, give it a name (e.g. "Entra Production"), and copy the token immediately. You only see it once; if you lose it, regenerate.

Leave this page open — you'll come back to verify provisioned users.


Step 2 — Create the Enterprise application in Entra

  1. Identity → Applications → Enterprise applications+ New application.

  2. Click + Create your own application.

  3. Name it (e.g. Stack AI).

  4. Choose "Integrate any other application you don't find in the gallery (Non-gallery)"Create.

Entra will build the app from its generic SCIM template — that's why provisioning logs and job names will reference customappsso. It's cosmetic and expected.


Step 3 — Configure SCIM credentials and test the connection

  1. In the new app, open the Provisioning blade → Get started.

  2. Set Provisioning Mode = Automatic.

  3. Expand Admin Credentials:

    • Tenant URL: paste the Stack AI Base URL from Step 1 (https://api.stack-ai.com/scim/v2)

    • Secret Token: paste the SCIM token from Step 1

  4. Click Test Connection. Entra calls /ServiceProviderConfig and /Users?count=1. Both should return 200.

    • 401: token is wrong or expired — regenerate in Stack AI and re-paste.

    • 404: Tenant URL is wrong — double-check the trailing /scim/v2.

    • 5xx: Stack AI side issue; check Stack AI status before continuing.

  5. Click Save.


Step 4 — Configure user attribute mappings

After saving credentials, the Mappings section appears with two object types: Users and Groups. Start with users — groups are covered in the optional section at the end.

  1. Click Provision Microsoft Entra ID Users.

  2. Enabled: Yes.

  3. Target Object Actions: leave Create / Update / Delete all checked.

  4. Verify (and trim) the attribute mappings. The minimum useful set:

    Microsoft Entra attribute
    Target SCIM attribute
    Notes

    userPrincipalName

    userName

    Identity key

    Switch([IsSoftDeleted], , "False", "True", "True", "False")

    active

    Disables suspended users

    objectId

    externalId

    Stable lookup; survives renames

    mail

    emails[type eq "work"].value

    Required for invites/SSO match

    givenName

    name.givenName

    surname

    name.familyName

    displayName

    displayName

    You can delete the rest of Entra's defaults (manager, addresses, phone numbers, etc.) — Stack AI ignores them and removing them reduces sync errors.

  5. Save the mappings.


Step 5 — Assign users to the app

Provisioning scope defaults to "Sync only assigned users and groups". Leave this — broader scopes provision your entire tenant, which you almost never want.

  1. In the same Enterprise application, open the Users and groups blade.

  2. + Add user/group → pick users (or, later, groups — see the optional group section).

  3. Save.

Only assigned users are eligible for provisioning. Adding more users later is non-destructive — they get picked up on the next sync cycle.


Step 6 — Start provisioning and verify

  1. Back to the Provisioning blade.

  2. Click Start provisioning at the top. Status should switch to Provisioning (green).

  3. To skip the wait, use Provision on demand:

    • Click Provision on demand

    • Search for one of the assigned users → Provision

    • Inspect the result. The "Modify user" or "Create user" step shows the exact SCIM payload sent and the response received.

  4. In Stack AI → Settings → Members, confirm the user appears with the expected name, email, and active state.

Going forward, Entra runs a sync cycle every ~40 minutes. This interval is set by Microsoft and cannot be lowered.


What to expect operationally

  • Adding a user to the app → next cycle they appear in Stack AI.

  • Removing a user from the app (or soft-deleting them in Entra) → active=false is sent, Stack AI deactivates them. The user record is preserved.

  • Hard-deleting a user in Entra after 30 days → SCIM DELETE /Users/{id} is sent and the user is removed from Stack AI.

  • Renaming a user → Stack AI updates the existing record, identified via externalId. No duplicate is created.

  • Quarantine (red banner on the Provisioning blade) → too many failures or auth errors. Fix the underlying issue, then Restart provisioning to clear it.


Troubleshooting checklist

If provisioning isn't behaving:

  1. Provisioning logs (Provisioning blade → "View provisioning logs"). Filter by Status = Failure. Each row shows the request, response, and exact error.

  2. 401 Unauthorized on every call → token expired or revoked in Stack AI. Regenerate and update Entra credentials.

  3. 403 Forbidden on /Users → SCIM was disabled on the Stack AI side. Re-enable from the SCIM Provisioning page.

  4. 400 invalidValue on userName → almost always a missing userPrincipalName for that user. Check the user's profile in Entra.

  5. No log rows at all for a user you expected → they're not assigned to the app, or they're in an unassigned group.

  6. Provision on demand is the fastest debug tool. Use it after every config change to validate without waiting for the cycle.


Optional: Group sync

By default, Stack AI mirrors Entra groups one-to-one — same name, same membership. There's no group → role / group → permission translation; the synced group is just a Stack AI group. Skip this section if you only need user provisioning.

Enable group sync in Stack AI

  1. Stack AI → Settings → SCIM Provisioning.

  2. Toggle Sync groups to ON.

If this toggle is off, every Entra /Groups call returns 403 Forbidden and Entra logs will be flooded with group-create failures.

Confirm the Group mapping is enabled in Entra

  1. Provisioning blade → Mappings.

  2. Click Provision Microsoft Entra ID GroupsEnabled = Yes.

  3. Verify the minimum mapping set:

    Entra attribute
    SCIM attribute

    displayName

    displayName

    objectId

    externalId

    members

    members

    The Entra group's displayName becomes the Stack AI group name verbatim. Pick clean, human-readable group names in Entra; they show up directly in Stack AI's UI.

Assign the group to the app

In Users and groups, + Add user/group → pick the group itself (not just its members). Assigning a member's parent group does not implicitly provision the group; the group must be assigned explicitly.

Note: Entra does not expand nested or dynamic groups for SCIM. If you have a group of groups, assign each leaf group separately.

Verify

After the next sync (or via Provision on demand on the group):

  • The group appears in Stack AI → Settings → Groups.

  • Members are populated. Adding/removing a user from the Entra group propagates as a SCIM PATCH (add/remove members) on the next cycle.

  • Renaming the Entra group updates the Stack AI group's name (it's matched by externalId).

  • Deleting the Entra group removes the Stack AI group; member users are kept.


Optional: Role mapping

By default, provisioned users have no role. To grant roles automatically, you create a translation table in Stack AI ("when Entra sends role X, set Stack AI role Y") and configure Entra to send a role value per user.

How role resolution works

When Stack AI receives a SCIM user payload with a roles array, it:

  1. Picks the role marked primary: true (or the first if none flagged).

  2. Lowercases and trims the value.

  3. Looks for an exact match in your role mappings.

  4. If no match → assigns the configured default role.

  5. If there's no default role → user is provisioned with no role.

Matching is case-insensitive, but whitespace and unicode quirks count. Use plain lowercase tokens (admin, member, viewer).

Step A — Create role mappings in Stack AI

  1. Stack AI → Settings → SCIM ProvisioningRole mappings card.

  2. Set a default role in the SCIM config (highly recommended). This is the safety net for users without a matching role.

  3. + Add mapping for each label you intend to send from Entra:

    IdP role value
    Stack AI role

    admin

    Admin

    member

    Member

    viewer

    Viewer

Step B — Define App Roles on the App Registration

App Roles live on the App Registration, not the Enterprise application.

  1. Entra admin → App registrations → open the registration that backs your Stack AI enterprise app (same name).

  2. App roles+ Create app role for each Stack AI role:

    • Display name: e.g. Stack AI Admin

    • Allowed member types: Users/Groups

    • Value: admin ← this is the string sent in roles[].value. Must match the idp_role_value from Step A.

    • Description: anything

    • Enable this app role?: Yes

  3. Repeat for member, viewer, etc.

Step C — Assign users (or groups) to App Roles

  1. Back to the Enterprise applicationUsers and groups.

  2. + Add user/group → pick a user or group → Select a role → choose the app role → Assign.

  3. Each user can hold one app-role assignment per app. Re-assigning replaces the previous role.

  4. If you assign a group, every member inherits the role for SCIM purposes.

Step D — Map App Roles into the SCIM roles attribute

Provisioning blade → MappingsProvision Microsoft Entra ID Users:

  1. Scroll to the bottom and tick Show advanced options.

  2. Click Edit attribute list for customappsso.

  3. Ensure roles exists with Type = String and Multi-Valued = True. Add it if missing. Save.

  4. Back in the user mappings list, + Add New Mapping:

    • Mapping type: Expression

    • Expression: SingleAppRoleAssignment([appRoleAssignments])

    • Target attribute: roles[primary eq "True"].value

    • Match objects using this attribute: No

    • Apply this mapping: Always

  5. Save.

The SingleAppRoleAssignment function emits the user's current app-role Value (e.g. "admin"), placed into roles[0].value with primary=true — exactly what Stack AI's resolver looks for.

Step E — Verify

  1. Provision on demand for a user with an assigned app role.

  2. Inspect the outbound SCIM payload — roles should be present with the right value.

  3. In Stack AI → Settings → Members, the user's role should reflect the mapping.

Troubleshooting role mapping

  • roles missing from payload → Step D-3 (schema) wasn't saved, or the user has no app role assigned (Step C).

  • roles present but Stack AI uses the default → label mismatch. The Value on the App Role and the idp_role_value in Stack AI must match (case-insensitive, no extra whitespace).

  • Existing users not updating → they don't re-resolve until something on their record changes. Either trigger a Provision on demand for each, or wait for the next sync cycle and ensure their app-role assignment was set/changed (which forces an update).

  • Multiple app-role assignments → not supported by SingleAppRoleAssignment. Use only one app role per user.

Lightweight alternative

If you don't want to manage App Roles, set a single constant role for everyone:

  • In Mappings → Provision Microsoft Entra ID Users, + Add New Mapping:

    • Mapping type: Constant

    • Constant value: member

    • Target attribute: roles[primary eq "True"].value

  • Add one matching role mapping in Stack AI: member → Member.

Everyone gets the same role on provisioning; admins are promoted manually inside Stack AI. Simpler, less Entra to manage, but no role differentiation from the IdP.


Quick reference

Question
Where it's configured

Who can SSO into Stack AI?

Entra app → Users and groups (assignment), SSO blade (provider config)

Who gets provisioned?

Entra app → Users and groups (must be assigned and in Provisioning scope)

What attributes flow over?

Entra app → Provisioning → Mappings

Where is my SCIM token?

Stack AI → SCIM Provisioning page (regenerate if lost)

Why isn't my group syncing?

(1) Sync groups toggle in Stack AI, (2) group itself assigned to the app, (3) Group mapping enabled in Entra

Why is everyone getting the wrong role?

Role mapping label mismatch, or no roles claim in SCIM payload

How fast does a change propagate?

Every ~40 minutes, or instantly via Provision on demand

Last updated

Was this helpful?