Directory Sync
Build frictionless onboarding for entire organizations with real-time provisioning and deprovisioning of users based on changes to your customers’ directories.
Organizations use directories from providers such as Okta or Workday to easily manage users and enforce their access to organization resources. Directories enable IT admins to activate and deactivate user accounts, create groups that inform access rules, accelerate adoption of new tools, and more. Get seamless user lifecycle management for both you and your customers by keeping your app in sync with the user directory - Directory Sync enables automatic updates for your app whenever there are changes to users, groups, or access rules in the connected directory.
The WorkOS Directory Sync API exclusively uses read-only operations. We will never mutate end-user directories.
Request a Directory Provider
Don't see a Directory Provider you need? Contact us to request a Directory Provider!
WorkOS makes use of Cloudflare to ensure security and reliability of all operations. If you are looking to create a list of allowed IP addresses for incoming requests, you can use the IP Ranges listed in the Cloudflare documentation.
In this guide, we’ll take you from learning about Directory Sync and POC-ing all the way through to building production-ready features fully integrated with the WorkOS Directory Sync API.
Sign in to your WorkOS account to see code examples pre-filled with your API keys and resource IDs.
This guide will show you how to:
To get the most out of this guide, you’ll need:
- A WorkOS account.
- A directory from a Directory Provider that WorkOS supports.
Object
Definition
Directory
A Directory stores information about an Organization’s user management system (i.e. Directory Provider).
Directory User
A Directory User represents an Organization user that is active in an Organization’s Directory Provider.
Directory Group
A Directory Group is a collection of Organization users, e.g. IT admins, HR, Database admins, etc. within a Directory.
The first step to connecting with a directory is creating an Organization in the WorkOS Dashboard. You will then be able to create a new Connection to your organization's directory. Let’s start by creating one for development in your Sandbox Project - get provider specific instructions by selecting the Identity Provider you're planning to use from the list below.
You can view and copy the unique identifier for the Directory Connection on the Directory page, once it has been set up. The id takes the form
directory_*
.
Directory Provider
Instructions
You can create a Connection with Azure AD SCIM by reading through our integration guide below. It provides end-to-end instructions for creating your Connection in the WorkOS Dashboard.
Connect to Azure AD SCIM
Our guide to creating a new Connection with Azure AD SCIM.
WorkOS offers native SDKs in several popular programming languages. Choose a language below to see instructions in your application’s language.
Node.js
Ruby
Go
Python
PHP
Laravel
.NET
Java
Request an SDK
Don't see an SDK you need? Contact us to request an SDK!
Directory Sync Example Application
Install the SDK using the command below.
Install the WorkOS SDK
npm install @workos-inc/node
As a best practice, your WorkOS API key should be kept secret and set as an environment variable on process start. The SDK is able to read the key automatically if you store it in an environment variable named WORKOS_API_KEY
; otherwise, you will need to set it manually. The Client ID should also be set dynamically based on the release environment.
Environment Variables
WORKOS_API_KEY='sk_example_123456789'WORKOS_CLIENT_ID='client_123456789'
Get the details of an existing Directory User.
Get User
1const WorkOS = require('@workos-inc/node');23const workos = new WorkOS(process.env.WORKOS_API_KEY);45const directoryUserID = // ... The ID of the Directory User to fetch6const user = await workos.directorySync.getUser(directoryUserID);
Webhooks should use HTTPS and expect to receive POST requests with the following headers:
${issued_timestamp}
, v1=${signature_hash}
NOTE: WorkOS sends the header as
WorkOS-Signature
, but many web servers will normalize all HTTP request headers to their lowercase variants. In this case, you'll extract theworkos-signature
header.
See example approaches for implementing a webhook endpoint below.
Webhook endpoint
1const express = require('express')23const app = express();45app.use(express.json());67app.post('/webhook', (req, res) => {8 const payload = req.body;9 const sigHeader = req.headers['workos-signature'];1011 // Verify the signature and process the event1213 res.status(200);14});
Set and save the webhook URL in the WorkOS Dashboard, so WorkOS knows where to deliver events.
The Webhook Secret is used to verify webhook requests from WorkOS. Be sure to keep the value secure.
Before processing the request payload, verify the request was sent by WorkOS and not an unknown party.
WorkOS includes a unique signature in each webhook request that it sends, allowing you to verify the authenticity of the request. In order to verify this signature, you must obtain the secret that is generated for you when you set up your webhook endpoint in the WorkOS dashboard. Ensure that this secret is stored securely on your webhook endpoint server as an environment variable.
The WorkOS SDKs have methods for validating the timestamp and signature of a webhook. Examples using these methods are included below. The parameters are the payload (raw request body), the WorkOS-Signature
header, and the Webhook Secret. There is an optional parameter, tolerance, that sets the time validation for the webhook in seconds. The SDK methods have default values for tolerance, usually 3-5 minutes.
Webhook validation
1import WorkOS from '@workos-inc/node';23const workos = new WorkOS(process.env.WORKOS_API_KEY);45const webhook = workos.webhooks.constructEvent({6 payload: payload,7 sigHeader: sigHeader,8 secret: process.env.WEBHOOK_SECRET,9});
If implementing webhook validation yourself, you'll need to use the following steps:
First, extract the timestamp and signature from the header. There are two values to parse from the WorkOS-Signature
, delimited by a ,
character.
issued_timestamp
: The number of milliseconds since the epoch time at which the event was issued, prefixed byt=
.signature_hash
: The HMAC SHA256 hashed signature for the request, prefixed byv1=
.
To avoid replay attacks, we suggest validating that the issued_timestamp
does not differ too much from the current time.
Next, construct the expected signature. The expected signature is computed from the concatenation of:
issued_timestamp
- The
.
character - The request’s body as a utf-8 decoded string
Hash the string using HMAC SHA256, using the Webhook Secret as the key. The expected signature will be the hex digest of the hash. Finally, compare signatures to make sure the webhook request is valid.
Once you’ve determined the event request is validly signed, it’s safe to use the event, i.e. the request body, in your application’s business logic. You do not need to signal to WorkOS whether or not the event was processed successfully.
Make sure you're ready to go live to production by going through this checklist.
- Handle edge cases
You may occasionally receive duplicate webhook events. To prevent duplicate processing of events, we suggest caching received events and implementing logic to skip processing seen events.
Since webhook events may be delivered out of order, i.e. not in the order in which they were generated, be sure to handle accordingly. The
issued_timestamp
extracted from theWorkOS-Signature
header can be used to determine order. - Register a production webhook URL in your Production Project.
- Set and secure your Production Project's Webhook Secret.
- Set and secure your Production Project's API key.
- Ensure that your application can receive webhooks from WorkOS.
Depending on your network architecture, you may need to allow incoming traffic from
api.workos.com
.WorkOS currently cannot guarantee that webhook traffic will originate from a static set of IP addresses.