Rensei docs

SCIM Directory Sync

SCIM directory sync.

SCIM (System for Cross-domain Identity Management) directory sync keeps your Rensei workspace automatically in sync with your identity provider. When a group is created, renamed, or deleted in Okta, Azure AD, or any WorkOS-connected directory, the corresponding Rensei teams update in real time. When a user is deprovisioned in your IdP, their Rensei access is revoked.

How directory sync works

The platform receives SCIM events via a dedicated webhook at POST /api/scim/webhook. Signature verification uses HMAC-SHA256 over the request body; the signing secret is configured by your Rensei deployment operator.

Supported events

EventAction
dsync.group.createdCreates (or maps) a Rensei team for the new directory group
dsync.group.updatedRenames the team; syncs member list if members array is provided
dsync.group.deletedSoft-deletes the Rensei team
dsync.user.deletedCalls deprovisionUser() - revokes org memberships, scrubs active sessions

Only the events listed above trigger platform actions. Unknown event types return 200 { ok: true, detail: "Event type not handled" } so your IdP's delivery retry logic does not stall.

Setup

Enable Directory Sync in WorkOS

In the WorkOS Dashboard, navigate to Organizations → <your-org> → Directory Sync and create a new directory. Select your IdP (Okta, Azure AD, Google Workspace, etc.) and follow the WorkOS setup guide for that provider.

Configure the webhook

WorkOS needs to know where to send directory events. In the WorkOS Dashboard under Webhooks, add a new endpoint:

https://app.rensei.ai/api/scim/webhook

The signing secret configuration is handled by your Rensei deployment operator. Deployment-level setup is covered in the operator docs.

Map groups to roles

Once directory sync is live, open Settings → Members → Directory Groups. For each synchronized group, assign a platform role:

RoleCapabilities
adminFull org admin - settings, billing, key management
memberStandard access to projects they are a member of
auditorRead-only across all projects; can query audit trail

Role resolution is highest-privilege-wins: if a user belongs to both an admin-mapped group and a member-mapped group, they get admin. The resolution order is: adminauditormember.

Group-to-role mapping

The platform stores group mappings in Redis under the key workspace:{id}:scim:group-map. Each entry maps an IdP group ID to a GroupRoleMapping:

interface GroupRoleMapping {
  groupId: string      // IdP group ID from SCIM
  groupName: string    // Human-readable name from IdP
  role: 'admin' | 'member' | 'auditor'
  provider?: string    // e.g. "workos", "okta", "azure-ad"
}

Mapping changes emit scim.group_mapped or scim.group_unmapped audit events.

User deprovisioning

When dsync.user.deleted fires, the platform looks up the user by their externalId (the IdP user ID stored at sign-in) and calls deprovisionUser(). Deprovisioning:

  • Soft-deletes all org memberships for the user
  • Invalidates any active sessions
  • Emits an audit event for the compliance trail

The user's history (audit events, session records) is preserved for audit purposes - only active access is revoked.

SCIM user state in Redis

The platform tracks each SCIM-managed user in Redis under workspace:{id}:scim:user:{userId}:

interface ScimUser {
  id: string
  email: string
  firstName: string
  lastName: string
  active: boolean        // false after deprovision
  scimManaged: boolean   // true for SCIM-provisioned users
  groups: string[]       // current group memberships
}

This state is the authoritative source of truth for whether a user is actively managed by the directory - used by the role resolver to enforce real-time group changes.

Troubleshooting

On this page