SCIM provisioning
How Entra ID or Okta pushes people and groups into the portal over SCIM, which credential it uses, how each write lands, and how changes are grouped into sync runs.
Your identity provider pushes SCIMSCIM provisioningCấp tài khoản qua SCIMThe standard your identity provider uses to create, update and remove portal accounts automatically, so people who leave lose access.Open in glossary changes straight to the portal, which is the SCIM server. Joiners, changes and leavers reach the directory without anyone retyping them.
Key rules
- The provider pushes; the portal never pulls. The portal cannot request a sync.
- An existing email is claimed, not duplicated. A claim leaves the portal’s own fields alone.
- Leavers lose access first. Deprovisioning writes the portal before Keycloak.
- Changes are grouped into sync runs. Changes within ten minutes of each other count as one run.
- Every SCIM write is audited with a system actor.
How a person is provisioned
-
The provider gets an access token
The provider presents its client identifier and secret at the portal’s token endpoint and receives an access token that lasts one hour.
-
The provider creates a user
It calls the portal’s SCIM routes with the token as a bearer token.
-
The portal claims or creates
- The email is already in the directory: the portal claims the existing row.
- A new person: the portal creates the Keycloak account first, then writes the user row keyed by the Keycloak id.
-
The portal records an admin event
Every SCIM write records an admin event with a system actor in the audit logAudit logNhật ký kiểm toánThe record of who did what: every model call with its cost and department, plus admin changes and approvals.Open in glossary.
-
The portal answers the provider
The provider receives a standard SCIM response.
Connector credential
Your organisation holds one provisioning credential. Choosing a method replaces it.
| Method | Detail |
|---|---|
| OAuth (default) | The portal mints a client identifier and secret, used only at a token endpoint that names your organisation. Directory requests carry an access token that dies an hour after issue; the connector renews it itself. Microsoft marks the long-lived bearer token unsupported for applications created from now on |
| Long-lived secret | Presented directly. For a connector already running on one, or a provider that offers nothing else |
- The secret is shown once and kept only as a digest. A lost secret is replaced, and replacing it stops the connector holding the old one.
- Replacing a credential revokes every access token issued under it at once.
- Editing the provider afterwards leaves the credential alone. The provider form is how a domain is corrected.
- A rejected secret answers 401. It is the one status the sync history does not record.
- Every refusal, at the token endpoint as at the directory routes, is the same answer with no detail.
- A registered provider always carries a credential, because a provider-owned directory (
IDPmode) has the seven directory writes frozen, invitations among them.
Write rules
| Write | Rule |
|---|---|
| Order | Creation calls Keycloak first. Deprovisioning writes the portal first, so a Keycloak failure leaves access already denied |
| Create, existing email | Claims the row and leaves department, organisation role and invitation state alone |
Create with active: false | The account is created disabled, never created and then disabled |
| Delete on Users | Deactivates. Audit rows reference the row, and a refusal would leave the provider retrying until it quarantines the job |
PATCH and PUT | Both exist, because Entra ID patches and Okta replaces. Both reduce to one membership diff and one rename |
PUT | Replaces the provider’s own fields only. A fully compliant replace would wipe department, organisation role and suspension on every Okta cycle |
| Membership | A diff. A re-push that changes nothing writes nothing. An unknown or nested-group member is skipped and counted |
| Group slug | Derived. A rename upstream never moves it, because portal URLs are built on it |
| Group delete | Cascades to memberships, role grants and visibility rules. The event says how many of each went |
| Rename | Carried through to the Keycloak account, because Keycloak links a brokered sign-in by the presented address |
| Disable | Sets the Keycloak account flag from whether the seat still allows access |
| Groups | Provisioning reaches the groups it provisioned and no others |
Sync runs and audit
A push-based provider never says a cycle began, so the portal treats a sync run as a time window.
| Rule | Detail |
|---|---|
| Window | The first change opens a run. Every change within ten minutes of the last one counts into it. A later change opens the next run |
| Refused push | Gets its own failed row carrying the status and reason. Bookkeeping never fails a write |
| Cadence | Entra ID pushes twenty to forty minutes apart. A connector configured a minute ago holds nobody yet, and the screens say so |
| On demand | The provider’s on-demand push sends one named person or group. The portal cannot request a sync |
| Audit | Every SCIM write records an admin event with a system actor. An unauthenticated request records nothing |
Directory mode
The directory mode is chosen when the organisation is created and defaults to PORTAL, where admins manage people in the portal. In IDP mode your provider is the system of record: the directory arrives over SCIM and the portal refuses the directory writes the provider owns. No screen changes the mode afterwards; changing it is a data migration, because a PORTAL directory holds hand-made users, groups and departments the provider has never heard of.
What IDP mode freezes, and which fields each side owns, is on Departments → Directory mode.
Why it works this way
Why the provider pushes instead of the portal pulling
Keycloak ships no SCIM server. Pulling from Keycloak’s Admin API cannot see a leaver either: a brokered account stays enabled in Keycloak after Entra ID disables it. So Entra ID pushes SCIM directly to the portal.
Why Delete deactivates instead of deleting
Audit rows reference the person, so the row must stay. Refusing the delete instead would leave the provider retrying until it quarantines the provisioning job.
Why PUT is deliberately not fully compliant
Okta replaces whole records on every cycle. A fully compliant replace would wipe the portal-owned fields (department, organisation role, suspension) each time. Both deviations from the standard have a test that fails if the endpoint is made compliant.
Under the hood
Routes and identifiers
- Twelve SCIM routes cover Users and Groups. Each names the organisation in its path, and a credential opens only the organisation it was minted for.
- The portal user id is the Keycloak id. The external id holds Entra ID’s object id.
- An access token is a database row, which is why replacing a credential revokes every token under it at once.
- The token endpoint reads the client pair from the form body, a basic authorization header, or both, because Microsoft sends both. If the two disagree, the request is refused.