Representative interview topic

How would you design a reliable SCIM 2.0 provisioning service?

BackendHard
Offer.cc Editorial TeamPublished Updated

Question

You own a B2B SaaS that lets enterprise identity providers create, update, group, and deactivate users through SCIM. Design the API, resource mapping, idempotency, retries, authorization, and session revocation after deactivation.

Question and scenario

An enterprise customer uses your SaaS as a service provider, and its identity provider sends user and group changes. Requests can be duplicated, reordered, delayed, or retried after a timeout. The service must support tenants, external identifiers, group membership, soft deletion, auditability, and prompt revocation while preserving SCIM 2.0 resource and error semantics.

What the interviewer is testing

  • Does the candidate understand SCIM User, Group, schemas, filtering, and PATCH semantics?
  • Can they connect external-resource mapping, idempotency keys, concurrent updates, and retries into one data flow?
  • Do they distinguish active=false, delete requests, and application-session revocation?
  • Can they enforce tenant isolation, token scope, auditing, rate limits, and sensitive-field protection?

Clarifying questions to ask first

Confirm whether the identity provider is authoritative for profiles, whether groups are pushed, whether hard deletion is allowed, sync latency targets, and tenant scale. Clarify whether external userName is stable, whether email renames occur, group-size limits, bulk support, and how quickly existing sessions must expire after deactivation. Do not use email as an immutable primary key.

A 30-second answer framework

Store SCIM external resources and local accounts in a tenant-scoped mapping, keeping stable external identifiers separate from internal IDs. Make create, update, PATCH, delete, and query idempotent with request fingerprints and versions; reject stale writes explicitly. active=false triggers deactivation and session revocation, while deletion follows a tenant retention policy. Every request validates tenant, token scope, and audit context, and retryable asynchronous effects must not grant permissions twice.

Step-by-step deep dive

  1. Define resource boundaries. Expose the SCIM capabilities you really support, such as /Users, /Groups, /ResourceTypes, /Schemas, and /ServiceProviderConfig. Keep schemas consistent with each resource type and return normalized errors for unsupported filters.
  2. Build identity mapping. Per tenant, store external resource ID, local user ID, source system, and current version. Mutable fields such as userName and email are for lookup or display, not for replacing the stable mapping; conflicts require review rather than silent merges.
  3. Implement idempotency and concurrency control. A repeated POST returns the existing resource or safely replays from a request fingerprint. Apply PATCH operations individually and record outcomes. Where supported, require an ETag or version condition so stale writes cannot overwrite newer data.
  4. Handle user and group lifecycle. active=false revokes application permissions, blocks new login, and expires current sessions. Hard deletion follows retention and audit rules. Update group membership by set difference; a partial failure must not remove every member that was not confirmed.
  5. Isolate asynchronous effects. After the API writes a local fact table, enqueue permission sync, welcome notifications, and audit events. Messages carry tenant, resource version, and idempotency key; duplicate consumers cannot grant access or send notifications twice.
  6. Protect and operate the service. SCIM tokens are limited to one tenant and operation scope, with rotation, revocation, and expiry. Bound pagination, filters, and bulk sizes. Record success, rejection, conflicts, retries, and deactivation latency without logging complete tokens or sensitive attributes.

High-quality sample answer

I would treat the SCIM API as the synchronization boundary from an external identity source to local accounts. Each tenant gets its own token, resource mapping, and audit trail. User and Group resources preserve stable external and internal IDs and follow the SCIM schema. Unsupported filters, PATCH operations, or returnability rules produce explicit errors instead of guesses.

Writes first land in a local fact table, then enqueue retryable permission effects by resource version. External IDs, request fingerprints, and conditional versions make retries idempotent; stale versions cannot overwrite fresh data. active=false revokes permissions, blocks new login, and expires sessions, while deletion follows retention. Group updates use set differences and retry partial failures without clearing unconfirmed members. Observe per-tenant sync latency, conflicts, deactivation-to-session-expiry time, and dead letters. References include RFC 7643, RFC 7644, and Okta's SCIM implementation guidance.

Common mistakes

  • Implementing only POST /Users without /ServiceProviderConfig, filters, PATCH, error types, and pagination.
  • Using email as the sole key, creating duplicates or linking the wrong account after a rename.
  • Treating a timeout retry as a new command and granting permissions, sending notifications, or overwriting newer fields twice.
  • Hiding a user after active=false without revoking tokens, permissions, and current sessions.
  • Clearing all local group members after a partial sync failure, turning a transient network issue into broad access loss or overgranting.

Follow-up questions and responses

What if the identity provider repeats the same create request?

Look up the tenant and external resource ID and retain a request fingerprint or version. Return a stable representation for an existing resource; if the payload conflicts, return a diagnosable error and audit it instead of silently overwriting a local change.

How do you preserve account continuity after an email rename?

Use the stable external resource ID to local account ID mapping, with email as a mutable attribute. Check tenant-level uniqueness, update display and login aliases, and never create a new account or match across tenants by email.

How do you stay safe when deactivation and login arrive together?

Authorization reads a linearizable account state or revocation version. Deactivation advances the version and revokes sessions; login checks it again before issuing credentials and rejects a deactivated account, even if an older asynchronous permission task is still running.

Public sources

Related questions