- Provision Auth0 users into a SCIM-compliant application as they are created.
- Keep profile attributes in the downstream application current as users change in Auth0.
- Deactivate or remove users in the downstream application when they are blocked or deleted in Auth0.
- Provision to a SCIM server without running your own webhook listener.
Implementation overview
This implementation uses an event stream with our outbound SCIM 2.0 user provisioning Action template. Auth0 publishes an event each time a user profile is created, updated, or deleted. The event stream delivers that event to the Action, and the Action sends a matching SCIM 2.0 request to the server you configure. The Action correlates each Auth0 user with its SCIM resource using the SCIMexternalId attribute (RFC 7643), which lets a client store its own identifier on a SCIM resource. The Action sets externalId to the Auth0 user_id, which is stable across profile changes. This allows the Action to find the right SCIM resource even after a name or email update.
| Auth0 event | SCIM request |
|---|---|
user.created | POST /Users to create the SCIM resource. |
user.updated | GET /Users?filter=externalId eq "..." to find the resource, then PUT /Users/{id} to replace it (or PATCH /Users/{id}, if configured). |
user.deleted | DELETE /Users?filter=externalId eq "..." to find the resource, then DELETE /Users/{id} to delete it. The SCIM server decides whether a DELETE means a hard delete, a tombstone, or a deactivation. |
Error handling
When the Action throws an error, the delivery is marked failed and Auth0 automatically retries the failed event. After the retries are exhausted, the event becomes available in the dead-letter queue for inspection and redelivery. Because this Action throws errors on invalid responses and terminal SCIM errors, those failed syncs are visible through retries and the dead-letter queue. A change that never produces a delivered event is not visible this way.Limits
- This Action synchronizes user profiles and does not include group provisioning.
- One event stream binds to one Action destination. To target several SCIM servers, create several event streams and Actions.
Instructions
Prerequisites
Before you begin, you need:
- An Auth0 tenant with Events and Actions enabled.
-
A downstream SCIM 2.0 endpoint that accepts
POST,GET,PUT, andDELETEon/Users. -
A SCIM server.
-
The SCIM server must return responses compliant with the SCIM 2.0 protocol (RFC 7644), and specifically:
-
A create (
POST /Users) must return a User resource with a stringid. -
A filter query (
GET /Users?filter=...) must return aListResponsewith aResourcesarray, and each returned resource must include a stringid. An emptyResourcesarray is valid and means no match.
-
A create (
-
The SCIM server must support an
externalId eqfilter. If the server rejects theexternalId eqfilter, the Action falls back to auserNamefilter, which matches on name and therefore cannot track an email change.
-
The SCIM server must return responses compliant with the SCIM 2.0 protocol (RFC 7644), and specifically:
- A bearer token issued by the SCIM server with permission to read, create, replace, and delete users.
- Network access from Auth0 to the SCIM server. If the SCIM server restricts inbound traffic, allow calls from the Auth0 IP addresses for your region.
Start creating the event stream
From Auth0 Dashboard > Event Streams, select + Create Event Stream to go to the New Event Stream page.In the Destinations section, select Auth0 Actions, then:
- In the Configurations section, for Stream Name, enter a descriptive name (like “Outbound SCIM provisioning”).
-
In the Select Events section, select
user.created,user.deleted, anduser.updated.
Configure Action secrets
In the Actions Editor, select Secrets (the key icon) and add the secrets for your SCIM server:The transport defaults fit the event stream execution budget. Event Relay enforces an effective execution budget of about 10 seconds, which is tighter than the 20-second Actions ceiling. The default of a 1500-millisecond timeout with one retry keeps the lookup-and-write flow within that budget. Raising either value risks exceeding it.
Base URL of the SCIM 2.0 endpoint. For example,
https://api.example.com/scim/v2.Bearer token issued by the SCIM server.
Per-request timeout in milliseconds.
Retry count on HTTP 429, HTTP 5xx, and network errors.
Comma-separated connection names. When set, the Action processes events only from these connections.
Add the Action template and customize the attribute mapping
In the Actions Editor, copy and paste the outbound SCIM 2.0 user provisioning Action template.The template’s
You can modify the
buildScimUser() function maps the Auth0 user profile to the SCIM User resource. The default mapping produces a core SCIM 2.0 User with the following fields:| SCIM attribute | Auth0 source |
|---|---|
externalId | user_id |
active | Inverse of blocked |
userName | email |
| Primary work email | email |
name.givenName | given_name |
name.familyName | family_name |
name.formatted | name |
displayName | name |
nickName | nickname |
| Work phone (optional) | user_metadata.phone |
buildScimUser() function to the mapping your SCIM server expects.Additionally, the buildScimUser() function contains a commented block for the SCIM Enterprise User extension. You can uncomment the fields that your server supports and adjust the Auth0 metadata paths for your tenant.Customize user update behavior (optional)
The Action template’s
onUserUpdated() function includes commented blocks with opt-in behaviors for user profile updates. Enable them only when your SCIM server requires them:-
Configure
PATCHinstead ofPUTif your SCIM server does not acceptPUTrequests. For example, Microsoft Entra ID inbound SCIM omits theput:userspermission from its default token and accepts onlyPATCH. - Enable upserts (creates for missing users on updates) if you do not provision existing Auth0 users in your SCIM server before enabling the event stream, or if your SCIM server may otherwise legitimately miss user creation events.
Configure PATCH instead of PUT
Configure PATCH instead of PUT
By default, on user profile updates, the Action replaces the full SCIM resource with
PUT /Users/{id}. A user.updated event carries the complete user profile and no list of changed fields, so a full replace is the most accurate update.To configure PATCH instead of PUT for user updates, in onUserUpdated(), follow the OPTIONAL: PATCH instead of PUT comment and set the update method and body:PATCH converges the attribute present in the mapped SCIM body, but unlike PUT, attributes you omit from the body can keep their current downstream values. If you want a removed Auth0 field to clear the downstream value, add explicit remove or null handling that your SCIM server supports.Additionally, this request omits the path attribute because path is optional for replace operations. However, some SCIM servers require a path on every operation. For those servers, send one operation per attribute, and use the schema-qualified path for any extension attribute.Enable upserts
Enable upserts
By default, when a This way, the Action sends a single
user.updated event fires for a user that does not exist in the SCIM server, the Action skips the update and logs a warning. This default assumes that SCIM server should have already processed the earlier user.created event, so a missing user signals an issue.To enable upserts, in onUserUpdated(), follow the OPTIONAL UPSERT comment and replace the skip-and-log with the following line:POST /Users to create the user instead of skipping. The mapped SCIM body already holds the full profile, so the Action needs no follow-up request.Test mapping locally
Before you deploy, you can unit test the Action with a mock event and a stubbed SCIM call. Auth0 documents Jest for this purpose, though you can use any test library.The following Jest test confirms that a For development outside the Auth0 Dashboard, you can add type hints with the Reference the Event Stream trigger types from JSDoc so the file stays plain JavaScript and adds no runtime dependencies.
user.created event sends a POST /Users request with a bearer token:@auth0/actions package:Synchronize existing users (recommended)
Before enabling the event stream, we recommend a one-time synchronization of existing Auth0 users with your SCIM server. The event stream can only react to user events delivered after you enable it, so this one-time synchronization keeps your downstream SCIM server up to date and prevents correlation failures when existing users are updated or deleted.To synchronize existing Auth0 users with your SCIM server:
- Get all existing Auth0 users. Use your normal user export or Management API workflow, and include every connection you want to sync.
-
Reconcile existing SCIM users with Auth0 users. If the SCIM server already has users, match them to Auth0 users by a trusted identifier (such as email), then update each resource so its
externalIdis the Auth0user_id. Do not create duplicates. - Backfill missing SCIM users. For each unmatched Auth0 user, send a SCIM create using the same body and attribute mapping defined in the Action.
- Verify the baseline. Check sample users, total counts, blocked users, and email changes in the SCIM server.
Event considerations
-
Account linking: When you link two Auth0 users, Auth0 sends a
user.deletedevent for the secondary account and auser.updatedevent for the primary account. The Action therefore deletes the secondary user in the SCIM server and updates the primary user. Unlinking restores the secondary user. To keep linked accounts in the SCIM server, restrict the synced connections withSCIM_CONNECTION_ALLOWLIST. -
Reactivation after brute-force block: Unlike tenant administrator blocks, which send a
user.updatedevent, brute-force protection blocks expire automatically without firing an event. The Action therefore does not update the SCIM server until the next profile change.