Outbound provisioning keeps an application’s own user list in step with your directory, over the application’s SCIM 2.0 API. EZGH SSO creates the people assigned to the application there, updates them when they change, and deactivates them when they’re unassigned or suspended. It can push the application’s assigned groups too.
Provisioning works for oidc and saml applications. ezgh applications are EZGH products and
aren’t provisioned (409 provisioning_not_supported). You need sso.provisioning.update to
change the settings (in SsoFullAccess), and sso.provisioning.get to see them and their status.
Turn on provisioning
You need the application’s SCIM base URL and a bearer token from the application. The catalog has the base URL and mappings for the applications that support SCIM, with the vendor’s steps for getting a token.
- Open EZGH SSO > Applications, the application, and its Provisioning tab.
- Enter the SCIM base URL and Bearer token, or select Start from a catalog app to fill in the base URL and mappings.
- Check the Attribute mappings, and choose whether to Push groups and Delete users at the application.
- Select Save and turn on.
ezgh sso applications provisioning set Slack --catalog slack --bearer-token-stdin < slack-token.txt
ezgh sso applications provisioning set Wiki --base-url https://wiki.acme.com/scim/v2 --bearer-token-file token.txt \
--attribute-mapping 'userName=${user.email}' --attribute-mapping 'displayName=${user.name}' --push-groupsThe token is read from standard input or a file, never from an argument. provisioning set
changes only the settings you give.
Call UpdateProvisioning (PUT):
curl -X PUT https://sso.ezghcloud.com/v1/organizations/$ORG_ID/sso/applications/$APP_ID/provisioning \
-H "Authorization: Bearer $EZGH_API_KEY" -H "Content-Type: application/json" \
-d '{ "baseUrl": "https://wiki.acme.com/scim/v2", "bearerToken": "…", "pushGroups": true }'PUT replaces the settings whole: a field you leave out takes its default, except the bearer
token, which is kept. Send If-Match with the ETag from
GetProvisioning; if the settings changed since you read them,
the request is 412 precondition_failed.
Settings
| Field | Description | Default |
|---|---|---|
baseUrl |
The application’s SCIM 2.0 base URL: https, a public host on port 443, no query. A trailing / is dropped. |
Required |
bearerToken |
Write-only: stored encrypted, never shown or recorded. bearerTokenSet says whether one is stored. Required the first time, and whenever baseUrl changes, so the stored token is never sent to a new URL. |
|
attributeMappings |
1 to 50 mappings. See Attribute mappings. | The defaults |
enabled |
Push changes. Turning it off stops pushes and drops the queued ones; nobody is deactivated at the application. | true |
pushGroups |
Push the groups assigned to the application, with their members. See Groups. | false |
hardDelete |
Delete users at the application when they’re deleted from the directory. See Deprovisioning. | false |
The answer also shows configured (false until the first PUT), status, and when the settings
were created and last changed.
- Changing
baseUrlstarts over: what was pushed to the old URL is forgotten, everyone is pushed to the new one, and nothing is deprovisioned at the old one. - Turning it on, or changing anything while it’s on, pushes everyone assigned and everyone pushed before again. Users whose pushed values haven’t changed aren’t sent anything.
Attribute mappings
A mapping is { "target", "source" }. The mappings must include userName, and each target
appears once.
target is a SCIM attribute path, up to 320 characters:
- a core attribute or sub-attribute:
userName,displayName,title,name.givenName; - one typed value of a multi-valued attribute:
emails[type eq "work"].value; - an extension’s attribute:
urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department.
id, externalId, active, meta, schemas, groups, members and password can’t be
mapped. EZGH SSO sets externalId to the directory user’s ID on users it creates, and active
from their status and assignment.
source is up to 512 characters of text with these variables:
| Variable | Value |
|---|---|
${user.email} |
The email address |
${user.name} |
The display name |
${user.givenName}, ${user.familyName} |
The given and family names |
${user.department} |
The department: set on the user, or sent by inbound SCIM |
${user.id}, ${user.slug} |
The user’s ID and slug (usr_…) |
${user.tags.<key>} |
The value of one of the user’s tags |
A value that comes out empty isn’t sent.
The default mappings:
[
{ "target": "userName", "source": "${user.email}" },
{ "target": "emails[type eq \"work\"].value", "source": "${user.email}" },
{ "target": "name.givenName", "source": "${user.givenName}" },
{ "target": "name.familyName", "source": "${user.familyName}" },
{ "target": "displayName", "source": "${user.name}" }
]ezgh sso applications provisioning set --default-mappings goes back to them. The catalog’s
scim.attributeMappings use the same format.
What’s pushed
| A user who is | Is pushed as |
|---|---|
| Assigned (directly or through a group) and not suspended, including a user pending activation | active: true |
Unassigned, suspended, or deleted without hardDelete |
active: false |
Deleted, with hardDelete |
DELETE |
A push is queued, in the same transaction as the change, whenever something may change what an application should have:
- assignments added, removed or replaced, directly or for a group;
- a user’s profile changed, or the user suspended, reactivated or deleted, by you or by inbound SCIM;
- group membership changed: by you, by inbound SCIM, by an identity provider’s group mappings at sign-in, or by deleting an identity provider;
- a group renamed or deleted.
Each push reads the directory as it is when it runs, so the order of changes doesn’t matter.
How a user is pushed: a user EZGH SSO already knows at the application is updated with
PATCH. Otherwise EZGH SSO looks for them by externalId (a user it created), then by userName,
and only then creates them with POST. A user found by userName is adopted: EZGH SSO
updates them, but didn’t create them, so reconcile doesn’t repair them. Updates replace the mapped
attributes (a mapped multi-valued attribute is replaced whole) and active; attributes you don’t
map are never touched. A change that doesn’t alter anything pushed sends nothing.
Groups
With pushGroups, the groups assigned to the application are pushed with displayName (the
group’s name), externalId (the group’s ID) and their members who are active at the application.
A group is looked up by externalId, then displayName, before it’s created. Members are added
and removed with PATCH, and only users EZGH SSO pushed are ever removed.
A group that’s no longer pushed (unassigned, deleted, or pushGroups turned off) is deleted at the
application if EZGH SSO created it, and left alone otherwise.
Deprovisioning
- Unassigning or suspending a user always sends
active: false, which most applications treat as deactivation. The user stays at the application. - Deleting a directory user sends
active: false, or withhardDelete,DELETE. - Deleting the application, or the directory, stops provisioning without deprovisioning anyone at the application. To deactivate everyone first, unassign them and wait for the pushes.
Retries and status
| The application answers | EZGH SSO |
|---|---|
429 |
Pauses every push to the application until Retry-After (a minute without one, an hour at most). Not counted as a failed attempt. |
A timeout, a connection error, 408 or 5xx |
Retries from 10 seconds, doubling up to an hour, and gives up after 15 attempts. |
Any other 4xx |
Stops that user’s or group’s push at once. |
A failure is kept as the user’s (or group’s) lastError: the status, and the application’s SCIM
detail and scimType, up to 300 characters. A user whose push stopped stays flagged until a
later change, a reconcile or a settings change pushes them successfully. Requests time out after
30 seconds, and answers over 1 MiB are refused.
GetProvisioning (ezgh sso applications provisioning get)
shows status:
state |
Meaning |
|---|---|
notConfigured |
No settings yet. |
disabled |
Turned off. |
paused |
The application answered 429; pushes resume at pausedUntil. |
syncing |
Pushes are queued. |
error |
Some user’s or group’s last push failed. |
idle |
Everything is pushed. |
status also counts the queued pushes, users (active, inactive, errors) and pushed groups,
and shows the last success, the last error, and the last and next reconcile. To see each user or
group:
ezgh sso applications provisioning users Wiki --status error
ezgh sso applications provisioning groups WikiListProvisionedUsers (status: active, inactive,
none or error) and ListProvisionedGroups (status:
error) list each record newest first: the application’s ID for it, whether EZGH SSO created it
there (createdByEzgh), whether a push is pending, and the last push and error.
Reconcile
A reconcile compares the application’s users with the directory and repairs drift. It runs every week, counted from when provisioning was turned on, and within seconds when you ask:
On the application’s Provisioning tab, select Reconcile now.
ezgh sso applications provisioning reconcile WikiCall ReconcileProvisioning. It answers 202, or 409 provisioning_not_enabled when provisioning is off.
A reconcile lists the application’s users (GET /Users, at most 10,000), then pushes again:
- each user EZGH SSO created there that’s missing, has a mapped value or
activethat differs, or should be gone; - each flagged user;
- each assigned user who isn’t there yet;
- each pushed group.
Users EZGH SSO adopted, or never touched, aren’t repaired. If listing fails with a 429, the
reconcile pauses and retries; another failure retries in 15 minutes, except a 4xx, after which
every user EZGH SSO created is pushed again instead (shown in lastReconcileError).
Activity in Trails
Each push that changes something at the application is recorded in Trails as a
service event by sso.ezghcloud.com, naming the application and the user or group:
ProvisionUser (create, update or adopt), DeprovisionUser (deactivate or delete) and
ProvisionGroup (create, update with the members added and removed, or delete). A push that
stops is recorded once, with errorCode provisioning_failed. Retries and pauses aren’t recorded,
and neither the bearer token nor attribute values ever are.