
SCIM vs JIT provisioning: when to use each
SCIM vs JIT provisioning: when should I use each?
Use JIT (just-in-time) provisioning for low-friction, first-login onboarding, and use SCIM when you need attribute updates, day-one pre-provisioning, or automated deprovisioning — and expect most teams to eventually run both. JIT provisioning creates a user account on the user's first single sign-on (SSO) login by reading attributes from the identity provider's assertion; it is almost free to add but cannot create accounts before first login or remove access when someone leaves. SCIM is a standard protocol (SCIM 2.0, defined by RFC 7643 and RFC 7644) that lets the identity provider (IdP) create, update, and deactivate accounts across the full user lifecycle, independent of any login — which is what makes automated offboarding possible.
The two are not really competitors; they solve different stages of the same problem. The IETF's own SCIM requirements document frames provisioning as happening "in a separate context from authentication (aka just-in-time provisioning)" (RFC 7642). This guide explains how each mechanism works, the deprovisioning gap that drives the decision, a balanced framework of factors to weigh for your own situation, the implementation gotchas that bite teams in production, and how authentication providers — including Clerk — support both.
Why user provisioning is a decision worth getting right
Provisioning is the plumbing behind every enterprise login, and the cost of getting it wrong almost always shows up at offboarding, not onboarding. Before comparing the two mechanisms, it helps to see the full problem they are trying to solve.
The identity lifecycle: joiners, movers, and leavers (JML)
User provisioning is not a single event — it spans an employee's entire relationship with an organization. Identity teams model this as joiners, movers, and leavers (JML): a joiner needs an account and the right access on day one, a mover needs access adjusted when their role or team changes, and a leaver needs access removed the moment they depart (Netwrix; StrongDM). Any provisioning approach that only handles the joiner is solving half the problem.
The hidden cost of manual provisioning
Manual account creation and removal does not scale, and its worst failure mode is invisible. Hand-managed accounts drift away from the directory that is supposed to be the source of truth, and the riskiest gap is offboarding: a departed employee who keeps working access is both a security incident waiting to happen and a compliance finding waiting to be written up.
The security case for automating deprovisioning rests on a simple fact — standing access that outlives its need is exactly what attackers reuse — rather than on any single headline statistic. The data backs the priority up. The IBM Cost of a Data Breach 2025 report put the global average breach at $4.44 million (IBM). The way breaches begin is shifting: in Verizon's 2025 Data Breach Investigations Report (DBIR), stolen credentials were the single most common initial-access vector at 22%, but in the 2026 edition vulnerability exploitation overtook them as the number-one entry point at 31%, and credential abuse as the initial vector fell to 13% (Verizon DBIR). Credentials still matter enormously to how breaches succeed, though: credential abuse appears in 39% of breaches across the full attack chain (DBIR 2026), and 88% of basic web-application attacks involved stolen credentials (DBIR 2025). An account that is never deprovisioned is precisely the kind of standing credential that keeps showing up later in the chain.
Identity incidents are common, and ex-employee access is a measurable part of the problem. Half of organizations (50%) reported an identity-based security incident in the prior 12 months (GuidePoint/Ponemon State of IAM Maturity 2025). A 2023 DoControl survey found that 31% of companies had former employees access SaaS assets after leaving (via Security Magazine), and an older OneLogin survey (2017) found 20% of organizations had suffered a breach tied to failing to deprovision an ex-employee, with 48% aware that former employees still retained access to corporate apps (OneLogin). These vendor and survey figures vary in rigor, but they all point the same direction: the leaver is where manual provisioning hurts.
Where this decision shows up
This choice surfaces in three common settings: B2B SaaS products selling to other organizations, internal enterprise tools used by a company's own workforce, and web apps adopting enterprise SSO for the first time. If your application accepts logins from a customer's identity provider — or will soon — you will eventually have to decide how accounts get created and, more importantly, how they get removed.
What is JIT provisioning?
JIT provisioning is account creation that happens at login time, as a side effect of single sign-on. It is the cheapest way to get accounts into your app, and its limits all stem from the fact that nothing happens unless someone logs in.
How JIT provisioning works
JIT provisioning is triggered by the first successful SSO authentication — most commonly SAML, and in some implementations OIDC. When a new user authenticates, your application reads the identity attributes from the assertion or ID token (the email from the SAML NameID or the OIDC sub plus claims, along with name and any mapped fields), creates the user record on demand, and logs the person in — all in one pass (Clerk; Okta). There is no separate setup step for the administrator and no account in your database until that moment.
What JIT provisioning does — and does not — handle
JIT handles account creation on first login and, in many (but not all) implementations, refreshes attributes on subsequent logins. Whether attributes re-sync on every login is application-specific — some apps update the record each time, others create it once and never touch it again — so never assume a single universal rule.
What JIT cannot do is the rest of the lifecycle. It cannot pre-provision: there is no account until the user logs in, so you cannot grant day-one access or @mention someone before they have ever signed in. And it cannot deprovision: when an administrator removes a user in the IdP, no login occurs, so no signal ever reaches your app. Clerk's own JIT documentation routes deprovisioning needs to Directory Sync (SCIM) for exactly this reason.
Strengths and limitations of JIT
The strengths are real: minimal engineering effort, no extra endpoint to build or operate, and the fastest possible path to "works with our customer's SSO." For an early-stage product landing its first SSO-using customer, JIT is often all you need.
The limitations are the mirror image. JIT is login-dependent, so a terminated employee whose IdP login is blocked never triggers any "JIT deprovision" — their existing account and any live session simply persist until the session expires on its own (OpenIAM). It offers no day-one access, and it leaves orphaned accounts behind when people leave. Those orphaned accounts still carry valid credentials and usually go unmonitored (Trustle).
What is SCIM provisioning?
SCIM is a standard protocol for pushing the full account lifecycle from an identity provider into your application, without waiting for a login. Where JIT reacts, SCIM is proactive.
How SCIM provisioning works (the SCIM 2.0 protocol)
SCIM stands for System for Cross-domain Identity Management. SCIM 2.0 is a REST-and-JSON standard defined by two IETF documents published in 2015: RFC 7643 (the core schema for User and Group resources) and RFC 7644 (the protocol). Both carry the status "Proposed Standard."
In a SCIM integration, the identity provider is the source of truth and your application is the "target" that receives changes. The IdP pushes lifecycle events to your application's SCIM endpoint as standard HTTP operations — POST, GET, PUT, PATCH, and occasionally DELETE — on /Users and /Groups collections, with a few read-only discovery routes (/ServiceProviderConfig, /ResourceTypes, /Schemas). Every request is authenticated with a bearer token over TLS (Microsoft Entra; Okta). Because the IdP drives it, none of this depends on the user ever signing in.
The full identity lifecycle: create, update, deprovision
SCIM covers every JML stage in one protocol: it provisions accounts, updates attributes when they change in the directory, syncs group membership, and deactivates accounts — all without a login event. Crucially, it supports pre-provisioning, so a user can be granted access (and appear in your app's user list, ready to be @mentioned or assigned) weeks before their first sign-in (WorkOS). Role and team changes propagate immediately, instead of waiting for the user to log out and back in.
Why deprovisioning is the core value of SCIM
The asymmetry is the whole point: onboarding is a convenience, but reliable offboarding is what justifies the protocol. When a user is removed or disabled in the IdP, SCIM tells your application to mark the account inactive — typically a PATCH that sets the active attribute to false — at which point a well-built application ends the user's sessions and revokes access, closing the gap that JIT leaves wide open (WorkOS).
One nuance matters for accuracy: RFC 7643 says the meaning of active is "determined by the service provider," so the protocol does not itself guarantee that sessions are revoked — your application (or your auth vendor) implements that behavior. Treat instant session revocation on deprovision as a feature to verify, not a given.
Strengths and limitations of SCIM
SCIM's strengths are everything JIT lacks: full lifecycle automation, real deprovisioning, pre-provisioning, group and role sync, and a directory that stays continuously in sync. Its limitations are operational. You have to build and operate a SCIM endpoint, every IdP has its own quirks, and there are simply more moving parts to maintain — which is what makes the gotchas and the build-versus-buy question (both below) worth taking seriously.
SCIM vs JIT provisioning: the key differences
The two mechanisms differ on what triggers them, what they can create or remove, and how much they cost to run. The table below summarizes the contrast; the prose after it explains the differences that actually drive the decision.
Read the table top to bottom and a pattern emerges: JIT is a feature of the login, while SCIM is a feature of the directory. That single distinction explains the three differences that matter most.
The deprovisioning gap
The most important difference is also the simplest: JIT cannot remove access, and SCIM can. This is the hinge the entire "when to use each" decision turns on. With JIT alone, blocking a user in the IdP stops new logins but does nothing to the account, data, permissions, or active sessions that already exist in your app. With SCIM, the IdP's removal flows through to your app and ends access.
Pre-provisioning vs first-login provisioning
SCIM can create an account before the user ever logs in, so access and group membership are ready on day one. JIT cannot: the account does not exist until the first successful sign-in. If your product needs people to be invited, assigned to teams, or @mentioned before they have authenticated, that is a SCIM capability.
Implementation and maintenance effort
JIT is close to free once you already support SSO — it reuses the login handler and adds no new endpoints. SCIM is a larger, ongoing commitment: a service endpoint to build, per-IdP behavior to accommodate, and load and idempotency concerns to handle over time. That cost difference is real and is the reason many teams reach for a provider that supplies SCIM for them rather than building it.
Clearing up a common confusion: SCIM vs SAML (and where JIT fits)
The most common misconception in this area is conflating "can no longer authenticate" with "the account no longer exists." A team ships SAML SSO with JIT, an employee leaves, the IdP blocks their login — and everyone assumes the account is gone. It is not. The account, its data, its permissions, and any live session all persist, because SAML is stateless: it proves identity at the moment of login and never tells your application that a user was later removed (RFC 7642).
Two related myths follow from the same root. The first is that SCIM and SAML are interchangeable; the second is that SCIM requires SAML. Both are false. They are independent protocols that solve different problems, and SCIM can run over an OIDC connection just as well as a SAML one (WorkOS).
Put another way: SSO decides who can sign in; SCIM decides who should exist. You need both to fully manage enterprise identity, and confusing the two is how the deprovisioning gap goes unnoticed until an auditor or a security questionnaire finds it.
When to use each: a balanced decision framework
There is no universal winner. The right choice depends on how you weigh the factors below for your own application, customers, and stage. Treat them as independent levers, not a ranking — team size matters for some products and barely registers for others.
Factor 1 — Do you need automated deprovisioning?
This is the factor that most often forces the decision. If reliable, automatic offboarding matters — if you cannot accept a departed user keeping access until a session happens to expire — then SCIM (or a provider-managed equivalent) is effectively required, because JIT cannot deprovision at all. If your offboarding is genuinely handled some other way (for example, very short session lifetimes plus a manual removal process you trust), JIT may be acceptable for now.
Factor 2 — Security and compliance requirements
Automated, provable access removal is a recurring theme across the major security frameworks, even though none of them name SCIM specifically. NIST SP 800-53 Rev. 5 control AC-2 (Account Management) and its enhancement AC-2(1) (Automated System Account Management) call for creating, disabling, and removing accounts in step with personnel changes (NIST). ISO/IEC 27001:2022 covers the same ground in Annex A controls A.5.16 (Identity management) and A.5.18 (Access rights) (ISMS.online). SOC 2's Trust Services Criteria CC6.2 and CC6.3 require that credentials and access be removed when access is no longer authorized (AICPA). If you operate in a regulated industry or sell into one, these requirements push hard toward SCIM, because automated deprovisioning is far easier to evidence than a manual checklist.
Factor 3 — Customer size and enterprise procurement
SCIM frequently becomes a hard procurement requirement for larger customers and can block a deal outright. Automated deprovisioning is one of the most-tested items in enterprise security reviews, and many SaaS products gate SCIM behind an enterprise edition or a minimum seat count (for instance, some vendors document SCIM access only above a seat threshold — point-in-time, and worth verifying for any specific product). Practitioners often cite a rule of thumb that SCIM turns into a hard requirement around the time you land your first roughly 1,000-seat customer (CIAM Compass; Hashorn). Treat that number as a heuristic from individual practitioners, not measured data — but treat the underlying pressure as real.
Factor 4 — Integration and engineering complexity
Weigh the cost of building and operating a SCIM endpoint against JIT's near-zero cost. Building SCIM in-house is a handful of routes on paper, but the real work is per-IdP behavior, idempotency, large-tenant load, and ongoing maintenance (covered in the gotchas below). A key question here is whether your authentication provider supplies SCIM for you — if it does, much of this factor disappears, which is the heart of the build-versus-buy decision.
Factor 5 — Provisioning timing (day-one access vs first login)
If users must have access before they ever log in — common when people are added to projects, mentioned, or assigned work ahead of their start — SCIM's pre-provisioning is the only option. If first-login account creation is acceptable for your product, JIT is enough on this axis.
Why most teams end up using both
In practice the common pattern is to ship JIT first for convenience, then add SCIM when the lifecycle, deprovisioning, or enterprise need arrives. There is a genuine tension in when to add it: some practitioners advise waiting until a customer actually asks (Hashorn), while others recommend adding it proactively, before your first large deal, so it never becomes a blocker (CIAM Compass). Both are reasonable rules of thumb; the right call depends on your sales motion and risk tolerance.
Quick-reference scenarios
A few concrete starting points, drawn from the factors above:
- If you are an early-stage SaaS landing your first SSO customer, JIT is usually enough for now.
- If you are closing your first enterprise deal and SCIM is on the security questionnaire, add SCIM.
- If you sell into a regulated industry, plan for SCIM from the start.
- If offboarding and large-tenant lifecycle management are your pain, SCIM is the answer; JIT cannot help.
Implementation considerations and common gotchas
The conceptual difference is clean. The implementations are where the surprises live. This section covers what each side actually requires and the production gotchas worth planning for.
Implementing JIT provisioning
JIT implementation is mostly attribute mapping. You read identity from the assertion and create or update the record. Two practices save pain later: match users on a stable identifier such as the SAML NameID or OIDC sub rather than on email (emails change), and decide deliberately whether to re-sync attributes on every login or only at creation.
Role mapping via the assertion is the brittle part. It relies on exact-string matching of group names, and identity providers complicate it — Microsoft Entra sends group object IDs (GUIDs), not human-readable names, and group claims in a token are capped at 150 for SAML assertions and 200 for JWT, with anything beyond the cap causing the group claims to be omitted entirely (Microsoft Entra). That last detail is a silent failure: past the limit, roles do not just truncate, they disappear.
Implementing SCIM provisioning
A SCIM service provider exposes a small set of routes, secures them with a bearer token, and is configured into each IdP. The endpoint count is smaller than folklore suggests — a minimal users-only implementation is around five routes, and a full users-plus-groups-plus-discovery implementation is closer to fifteen, not the "sixteen endpoints" sometimes quoted. The skeleton below shows the core in TypeScript; note that the deprovisioning path is the active: false branch of PATCH, not DELETE.
import express, { type Request, type Response, type NextFunction } from 'express'
const scim = express.Router()
scim.use(express.json({ type: ['application/json', 'application/scim+json'] }))
// Every SCIM route is bearer-authenticated over TLS.
scim.use((req: Request, res: Response, next: NextFunction) => {
const token = req.header('authorization')?.replace('Bearer ', '')
if (token !== process.env.SCIM_BEARER_TOKEN) {
return res
.status(401)
.json({ schemas: ['urn:ietf:params:scim:api:messages:2.0:Error'], status: '401' })
}
next()
})
// Provision a user — the IdP can call this before the user ever logs in.
scim.post('/Users', async (req: Request, res: Response) => {
const user = await createUser(req.body) // map emails, userName, name, externalId
res.status(201).json(toScimUser(user))
})
// Existence and idempotency checks: GET /Users?filter=userName eq "jane@acme.com"
scim.get('/Users', async (req: Request, res: Response) => {
const results = await findUsers(req.query.filter as string | undefined)
res.json(toListResponse(results))
})
scim.get('/Users/:id', async (req: Request, res: Response) => {
const user = await getUser(req.params.id)
return user ? res.json(toScimUser(user)) : res.sendStatus(404)
})
// Deactivation (active -> false) arrives in different shapes by IdP — Okta sends
// no path (value is the object { active: false }); Entra sends path "active"
// (boolean false only with the aadOptscim062020 compliance flag; the string
// "False" without it). op casing varies too (Entra: "Replace"), so compare
// case-insensitively. This per-IdP variation is what makes PATCH the buggiest op.
function deactivates(ops: Array<{ op: string; path?: string; value: unknown }>): boolean {
const isFalse = (v: unknown) =>
v === false || (typeof v === 'string' && v.toLowerCase() === 'false')
return ops.some((o) => {
if (o.op?.toLowerCase() !== 'replace') return false
if (o.path === 'active') return isFalse(o.value) // Entra: path-based
const v = o.value as Record<string, unknown> | null // Okta: no path
return !o.path && typeof v === 'object' && v !== null && isFalse(v.active)
})
}
// The lifecycle workhorse. A single PATCH can change attributes AND set
// active=false, so apply every operation first, then revoke sessions as a side
// effect of deactivation — never skip ops, and never DELETE.
scim.patch('/Users/:id', async (req: Request, res: Response) => {
const ops = req.body.Operations as Array<{ op: string; path?: string; value: unknown }>
await applyPatch(req.params.id, ops) // persists all changes, including active
if (deactivates(ops)) {
await revokeSessions(req.params.id) // active=false must also end live sessions
}
res.json(toScimUser(await getUser(req.params.id)))
})
export default scimTwo routes round out the set but are used less often: PUT /Users/:id (full replace) and DELETE /Users/:id (rarely exercised, because most IdPs deactivate rather than delete). The same verbs apply to /Groups, plus the three read-only discovery routes. The contrast with JIT is the headline: JIT adds zero new routes — it reuses the SSO login handler — while SCIM is a service you own. And PATCH is consistently the most bug-prone operation, because its exact shape differs by IdP — Okta and Microsoft Entra even encode the same active: false deactivation differently (Okta; Microsoft Entra).
SCIM gotchas to plan for
Most SCIM pain comes from per-IdP differences, even though everyone claims SCIM 2.0 compliance — a situation one IAM vendor calls "premature standardization" (Evolveum). The gotchas worth planning for:
- Push timing varies, so the "SCIM experience" depends on the IdP. Okta pushes changes in an event-driven way — it is notified when a user is created, assigned, changed, or deprovisioned, and acts on it near-immediately (not on a poll) (Okta). Microsoft Entra, by contrast, provisions on a fixed background cycle that runs approximately every 40 minutes and is not configurable, though an admin can force a single user through sooner with on-demand provisioning (typically under 30 seconds) (Microsoft Entra: use-scim; known issues; provision on demand). Deprovisioning latency, therefore, is an IdP property, not something your app controls.
- Not every directory is an equally capable SCIM source. Okta and Microsoft Entra push the full SCIM 2.0 lifecycle — users and groups — to any endpoint you expose, but Google Workspace's automated provisioning is narrower: it provisions users, not groups. Google Groups can only scope which users are provisioned; the groups themselves are never created or synced in the target app, so there is no automatic group provisioning (Google Workspace; Keeper). If your customers standardize on Google Workspace, plan for a users-only directory-sync story rather than the group sync Okta or Entra provide.
- Deprovisioning is deactivation, not deletion. Okta sends
active: falseand never issues aDELETE; Entra disables first and only hard-deletes after a soft-delete window; GitHub suspends enterprise users rather than deleting them (Okta; GitHub). Build your endpoint around deactivation as the normal case. - Microsoft Entra's default SCIM payloads aren't RFC-compliant — a flag fixes it. By default Entra sends the
activeattribute as the JSON string"False"(not the booleanfalse), capitalizes the operation name (Replace), and structures some multi-attribute and group-removalPATCHoperations in non-standard ways. Appending theaadOptscim062020flag to the SCIM Tenant URL switches Entra to RFC 7644-compliant payloads. As of early 2026 it is still opt-in — Microsoft has long said the compliant behavior "will become the default," but it hasn't — so either set the flag or make your endpoint tolerant of both shapes (the skeleton above already is: it lower-casesopand accepts a string or booleanactive) (Microsoft Entra). - Nested groups do not survive cleanly. Entra provisions only the direct members of an assigned group and "can't read or provision users in nested groups"; Okta flattens nested Active Directory groups into the parent on import (Microsoft Entra; Okta). Expect flattened membership, or have admins assign the leaf groups directly.
- Large-tenant initial sync is a load event. Onboarding a big customer can fire thousands of near-concurrent
POSTrequests, which can exhaust connection pools and trigger N+1 database patterns (DEV Community). A robust endpoint returns HTTP429 Too Many Requestswith aRetry-Afterheader so the IdP backs off — Okta honors this, pausing the task and using exponential backoff, and reads only integer-secondsRetry-Aftervalues (Okta). Worth knowing:429is not defined by SCIM itself (RFC 7644 §3.12 does not list it; it comes from RFC 6585), so treat it as standard HTTP back-pressure layered on top of SCIM. - A cloud IdP can only push to an endpoint it can reach. SCIM is server-to-server: the IdP sends provisioning requests into your SCIM endpoint, so that endpoint must be reachable from the IdP. For a public SaaS that is automatic, but an internal tool with no public ingress cannot be reached by a cloud IdP directly — the team running the IdP has to deploy an outbound provisioning agent inside the network (such as the Okta Provisioning Agent or Microsoft Entra's on-premises provisioning agent), which connects outbound so no inbound firewall ports are opened. JIT sidesteps this entirely, because the SAML assertion or OIDC token travels through the user's browser at sign-in rather than over a direct IdP-to-app connection.
- Ordering and idempotency. A group can reference a user before that user's
POSThas landed, producing a transient404; useexternalIdas the stable key to make retries idempotent (Stytch).
How JIT and SCIM coexist (and when to turn JIT off)
When SCIM owns the lifecycle, leaving JIT on can create conflicting or duplicate records, or let a login overwrite attributes that SCIM is supposed to manage. That is why teams often disable JIT once SCIM is authoritative — but which side wins is a platform configuration choice, not a protocol rule. Docker defaults to JIT overwriting SCIM (Docker), whereas data.world automatically disables JIT when SCIM is enabled (data.world). The dedup contract that keeps the two from colliding is a stable shared identifier: externalId on the SCIM side matched to the NameID or sub on the login side.
Build vs. buy
Building SCIM in-house looks like a handful of endpoints, but the cost is in the long tail: per-IdP quirks (with PATCH the buggiest operation), idempotency, large-tenant load, and continuous maintenance as IdPs change. Effort estimates range from roughly 4–8 weeks for a single-IdP MVP (a practitioner estimate from Hashorn) up to several months for a hardened, multi-IdP implementation (per WorkOS's vendor ROI modeling). Both are interested estimates, not neutral benchmarks — but the direction is consistent.
Observability is an underrated part of this decision. When an in-house endpoint silently fails to provision a user, your team often cannot see why, because the IdP's own provisioning logs live on the IdP side — Microsoft Entra's "provisioning logs" and Okta's "System Log" — and the receiving application "[doesn't] have access to these logs" (WorkOS, a vendor source; Microsoft Entra provisioning logs). Triage then degrades into a back-and-forth with the customer's IT admin. A managed provider supplies the missing application-side view — for example, Clerk's "Directory users" tab shows each provisioned user's status and last sync time (Clerk). For many teams, that operational support — not just the endpoints — is the real argument for letting an identity provider handle provisioning.
How authentication providers handle provisioning
Most teams do not build provisioning from scratch; they get it from their authentication or identity platform. Here is how that landscape looks, and where Clerk fits.
The vendor landscape (a fair, balanced survey)
First, a direction check that prevents a lot of confusion: the workforce identity providers your customers operate (Okta, Microsoft Entra ID, OneLogin) push provisioning outward, while the authentication platforms you embed in your app receive it. When you shop for "a SCIM solution," you are shopping for the receiving side.
On that receiving side, mature B2B and CIAM platforms commonly support both JIT and SCIM, with quality and coverage varying by product. WorkOS, Auth0, Frontegg, Stytch, SSOJet, Scalekit, PropelAuth, and Descope all offer SCIM-based directory sync alongside SSO, and several add self-service admin portals so your customers can configure their own connections. Across the industry, SCIM and directory sync tend to sit on higher or enterprise tiers rather than free entry plans — a durable pattern worth budgeting for, though specific tiers and prices change often and should be verified against each vendor's current pricing. The point of this section is capability, not a price comparison: the meaningful differences between providers are SCIM scope (users only versus users and groups), deprovisioning immediacy, group-to-role mapping, and whether a hosted admin portal is included.
Provisioning with Clerk
Clerk supports both approaches, which maps cleanly onto the framework above: JIT for first-login onboarding and Directory Sync (SCIM) for the full lifecycle, plus a lighter OIDC-based middle option. Pricing and feature details below are current as of June 2026 and are point-in-time — verify them against Clerk's pricing page before you commit.
JIT provisioning during SAML SSO
Clerk creates an account on a user's first SAML SSO sign-in, reading the identity from the assertion, and can keep user data current on subsequent sign-ins via a "Sync user attributes during Sign in" toggle. This is documented for Clerk's SAML connections — Microsoft Entra ID (Azure AD), Google Workspace, Okta Workforce, and custom SAML — and is the SAML-side counterpart to the SCIM lifecycle (Clerk).
Directory Sync (SCIM) for the full lifecycle
Clerk's Directory Sync (SCIM) is generally available and enabled for all users. It provides automated provisioning, deprovisioning with immediate session revocation, attribute syncing, and group syncing. When a user is removed or deactivated in the IdP, Clerk deactivates the corresponding Clerk user and immediately revokes all of their active sessions — so deprovisioning is enforced at once, not on a delay (Clerk). Custom attribute mapping and group-to-role mapping are also generally available (the rollout completed in May 2026), with custom attributes mapped into the user's publicMetadata and role mapping enabled by default (Clerk changelog). Documented SCIM identity providers are Okta and Microsoft Entra ID, and Directory Sync is configured per enterprise connection.
A third tier: EASIE
Between JIT and full SCIM, Clerk offers EASIE — an OIDC-based enterprise SSO option for Google Workspace and Microsoft Entra ID. EASIE includes automatic deprovisioning by re-checking, at session-token issuance, whether the user is still active in the OpenID provider, with up to a roughly 10-minute worst-case delay (Clerk). It is a middle ground — lighter than SCIM, but with real deprovisioning that JIT lacks — and it is not a standard provisioning protocol, so it does not replace SCIM where the full lifecycle or broader IdP support is needed.
Example configuration
Setup is concept-first and stays in the dashboard: you enable Directory Sync on an existing enterprise connection, Clerk generates an Endpoint URL (the SCIM base URL) and a bearer token, and you paste both into your IdP's provisioning configuration. Because Directory Sync requires an existing SAML or OIDC enterprise connection, there is no standalone SCIM-only setup — it builds on a connection you already have.
Fair caveats and requirements
A few honest constraints. Directory Sync requires an existing enterprise connection and is not standalone, so it complements your choice rather than removing it. SCIM provisioning and deprovisioning are included with the enterprise connection (there is no separate Directory Sync line item on Clerk's pricing page), but enterprise connections themselves are a paid, metered feature: one is included on the Pro plan, with additional connections metered on a sliding scale (Clerk pricing). Group-to-role mapping additionally requires linking the connection to an organization and using custom roles — capabilities packaged in Clerk's Enhanced B2B Authentication add-on — so the mapping feature is GA and enabled by default, but the org-link-plus-custom-roles prerequisite is a paid boundary (pricing is point-in-time and packaging can change — verify at Clerk's pricing page). Finally, a concrete requirement that catches teams off guard: Clerk requires an email in the SCIM emails attribute for every provisioned user and will not fall back to userName, so a SCIM payload that omits an email fails to provision that user (Clerk). Clerk does not document a specific merge or dedup behavior for pre-existing JIT users when SCIM is later enabled on the same connection, so do not assume automatic reconciliation; on the sign-in path, Clerk does auto-link accounts by verified email (Clerk).
Conclusion: choosing the right provisioning approach
The decision rule is short: use JIT for low-friction first-login onboarding, and use SCIM when you need attribute updates, day-one pre-provisioning, or automated deprovisioning. Because they cover different stages of the same lifecycle, most teams end up running both — shipping JIT first for speed, then adding SCIM as the lifecycle, compliance, or enterprise need arrives. The deprovisioning gap is the factor that most often forces the move to SCIM, but the right weighting of deprovisioning, compliance, customer size, engineering cost, and timing is yours to make for your own product.
Whichever way you lean, you do not have to build it alone. Authentication providers — Clerk among them — support both JIT and SCIM, so you can start with first-login provisioning and turn on the full directory-synced lifecycle when your customers ask for it, without re-architecting your auth.