Skip to main content

Provision Users and Groups from Microsoft Entra ID

Gravitino acts as a SCIM 2.0 service provider. Microsoft Entra ID acts as the client, pushing users, groups, and memberships into a Gravitino metalake so that access control can be expressed against identities your organization already manages.

Provisioning is one directional. Entra is the source of truth, and Gravitino accepts what Entra sends. Nothing flows back.

Quick Start

1. Mint a SCIM token. Call the token endpoint on the Gravitino server for the metalake you want Entra to populate. The response carries the token value and its expiry.

curl -X POST \
-H "Content-Type: application/json" \
-d '{"tokenName": "entra"}' \
https://{gravitino_host}/api/metalakes/{metalake_name}/scim/tokens

2. Note the tenant URL. Entra needs the metalake scoped SCIM base path with the compatibility parameter appended.

https://{scim_host}/scim/v2/metalakes/{metalake_name}?aadOptscim062020

3. Create a non-gallery application in Entra. Use the option for integrating an application that is not in the Entra gallery, then enable automatic provisioning on it.

4. Supply the tenant URL and token, and test the connection. A successful test means Entra reached the endpoint and authenticated. It does not mean the attribute mappings are correct.

5. Assign a group to the application. Entra provisions only the users and groups assigned to the application. An application with nothing assigned syncs nothing.

6. Run on demand provisioning for a single user. Confirm the user appears in the metalake before enabling the scheduled cycle.

Prerequisites

Entra requires a Premium license for provisioning to applications that are not in its gallery. Entra ID P1 is sufficient, and it is included in Microsoft 365 E3 and E5, so most organizations already hold it.

The Gravitino SCIM endpoint must be reachable from Microsoft's cloud over HTTPS on port 443, with a certificate from a publicly trusted authority. Entra rejects self signed certificates. Because the provisioning service cannot complete an interactive sign in, no proxy that issues a login redirect can sit in front of the endpoint. The SCIM bearer token is the only authentication layer.

Any load balancer in the path must pass PATCH and DELETE through, deliver the Authorization header unmodified, leave the request path unrewritten, and ignore unrecognized query parameters.

SCIM Service Configuration

The SCIM service runs as an auxiliary service alongside the Gravitino server and listens on its own port. Its configuration is validated at startup, and a mismatch terminates the server rather than leaving the service unregistered. Confirm that scim appears in the auxiliary service names, that the principal mapper and custom filter match the authentication mode you intend to use, and that the groups fields setting is empty.

Gravitino supports two authentication modes on the SCIM endpoints. Static bearer tokens are the mode Entra uses, since the provisioning service has no way to complete an OAuth flow. OAuth is available for clients that can present a token from your identity provider, which is the mode Keycloak based deployments use.

Token Management

Tokens are minted per metalake and persist across restarts. Each token carries an expiry, so plan for rotation before it lapses. Rotating a token issues a new value under the same name, which lets you update Entra without deleting and recreating the application.

OperationRequest
CreatePOST /api/metalakes/{metalake_name}/scim/tokens
RotatePOST /api/metalakes/{metalake_name}/scim/tokens/{token_name}/rotate
DeleteDELETE /api/metalakes/{metalake_name}/scim/tokens/{token_name}

Configure the Application in Entra

Microsoft documents the generic mechanics of setting up provisioning for a non-gallery application. The steps below cover only what is specific to Gravitino.

Use the compatibility parameter. Entra runs two generations of provisioning job. The older one sends requests that do not conform to SCIM 2.0, including PATCH bodies with malformed value structures. Appending aadOptscim062020 to the tenant URL opts the application into the conformant behavior. Gravitino implements the specification as written, so without this parameter you will see PATCH operations fail even though the endpoint is correct.

If you configured an application before adding the parameter and it continues to fail on disabling users, on adding single valued attributes, or on removing group members, the application is still bound to the older job. Adding the parameter to an existing configuration does not always rebind it. Delete the provisioning configuration and create a new one.

Assign groups rather than individual users. Assigning a group provisions the group object itself along with its members, which exercises both the user and group paths. Assigning users individually leaves group membership untested.

Use on demand provisioning while you iterate. The scheduled cycle runs on an interval measured in tens of minutes. On demand provisioning applies to a single user immediately and reports the result of each attribute mapping, which makes it the only practical way to debug a configuration.

Attribute Mappings

Entra ships a default mapping set aimed at a generic SCIM target. Most of its entries reference attributes Gravitino does not implement, and Entra treats a mapping to an unsupported attribute as a provisioning failure rather than skipping it. Remove every mapping not listed below.

Entra AttributeSCIM AttributeNotes
userPrincipalNameuserNameMatching attribute, must be marked as such
displayNamedisplayName
givenNamename.givenName
surnamename.familyName
mailemails[type eq "work"].value
Switch([IsSoftDeleted], ...)activeControls enable and disable, keep the default expression
objectIdexternalIdOptional, see below

Set the matching attribute to userName. Gravitino assigns its own immutable id to every resource it creates and does not accept a client supplied value for it, so matching on objectId or on externalId will cause Entra to create duplicates rather than recognize existing records.

externalId is optional. Mapping Entra's objectId to it gives you a stable link back to the directory object, which is useful when auditing, but provisioning works without it.

For groups, keep the mappings for displayName and members, and remove the rest.

How Deletes Behave

Entra distinguishes two operations, and they reach Gravitino differently.

Disabling a user, removing their application assignment, or removing them from an assigned group causes Entra to send a PATCH setting active to false. The record remains in the metalake and stops being treated as an active identity.

Deleting a user from the directory causes Entra to send a DELETE after a delay. Entra soft deletes directory objects first and retains them for thirty days, so the DELETE does not arrive immediately after the user disappears from your directory view.

The practical consequence is that most removals you perform in Entra arrive as a deactivation rather than a deletion. Plan any downstream cleanup around active rather than around the presence of the record.

Group Provisioning

Gravitino provisions groups as SCIM group resources with their memberships. Membership changes arrive as PATCH operations that add or remove individual members rather than replacing the whole list.

Nested groups are not provisioned. Entra flattens nothing on your behalf, so a group whose members are other groups arrives with those groups as members and their users do not appear. Assign leaf groups.

Filter matching on group displayName is case sensitive.

Troubleshooting

The connection test fails with an authentication error. Confirm the token has not expired and that the load balancer is passing the Authorization header through. A proxy that strips or rewrites the header produces the same symptom as a bad token.

The connection test fails with a certificate error. Entra requires a publicly trusted certificate. Certificates that browsers accept because of a local trust store addition will still fail.

Users provision but attributes are empty. The source attributes are unset on the directory objects. Entra sends what it has, and a user with no given name provisions with no given name.

PATCH operations fail while creates succeed. The application is bound to the older provisioning job. Recreate the provisioning configuration with aadOptscim062020 in the tenant URL.

Duplicate records appear on every cycle. The matching attribute is not set to userName. Entra is failing to recognize existing records and creating new ones.

Nothing provisions at all. Confirm that users or groups are assigned to the application. Provisioning scope covers assigned principals only.

Entra records every provisioning attempt with the request it sent and the response it received. The provisioning logs are the fastest way to distinguish a mapping problem from an endpoint problem, and they should be the first place you look before inspecting the Gravitino server logs.