Vibe Engines
YouTube

Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path

System Design

Design Enterprise SSO

Step 1 / 9

Learn system design by building the identity layer enterprise deals actually stall on.

The numbers to beatper tenantprotocol + configsign the assertionnot just the wrapperpin the certand calendar it

The whole design, in writing

Every step of the build above, written out: the problem each piece solves, the option that was taken and the ones that were not, the numbers, and how it fails in production.

The big idea

Why identity blocks the deal

Nobody has ever lost an enterprise deployment because the model scored two points lower on an eval. They lose it because a security reviewer asked “what happens to access when someone leaves?” and the honest answer was “you email us”.

Build the identity layer properly: federate per tenant, key users on something immutable, provision over SCIM with deactivation handled correctly, map groups to roles through a layer their admin controls, revoke inside the promised window, and log everything a reviewer will ask for.

Step 1 · The skeleton

Let the right people in

The naive version: your own username and password, per user, in your own database. Every enterprise buyer refuses this within one meeting — it means their leavers keep working accounts, their password policy does not apply, and their multi-factor requirement is unenforceable.

Userthe customer’s employeeAuth Servicemulti-tenant
New in this step: User, Auth Service.

Stand up an Auth Service that issues a session after the customer’s own identity system vouches for the user. You are a relying party, never a source of truth. Everything that follows makes that relationship multi-tenant, correct and revocable.

Why this piece earns its place

Worth naming what this skeleton quietly assumes: that there is always a working identity provider on the other side. Two days break it. The first is day zero — before any trust is configured, somebody has to sign in and configure it, and that somebody cannot be federated yet. The second is the morning their provider is down, when federation is the only way in and nobody, including their own administrators, can reach the screen that would fix it. So design the local path rather than discovering it: a small number of named break-glass accounts, hardware-backed second factor, no ordinary work possible while signed in that way, and every use loud — alerted at the time, not found later. The temptation is to leave it undesigned and let someone quietly create a local admin at two in the morning when it is needed. That account then never goes away, it lives outside the customer’s directory, and it is the first thing a reviewer finds. Build it deliberately, keep it narrow, and be the one who raises it.

What the new pieces do

Userclient
Signs in with their work account and expects never to see a password prompt from you. They belong to the customer’s directory, not to yours — which is the fact that shapes the entire design.
Auth Servicebackend
Resolves which tenant a sign-in belongs to, then validates the assertion or token against that tenant’s configuration. One deployment, many trust relationships, no shared state between them.

Step 2 · Federate

SAML or OIDC — and the customer decides

One deployment, many customers, each with a different identity provider, a different protocol preference and a different set of attribute names. Hard-coding one of them means the next customer is a fork.

UserIdentity ProviderAuth ServiceSAML / OIDC
New in this step: Identity Provider, SAML / OIDC. · swipe to pan the diagram

A large regulated customer insists on SAML 2.0. OIDC is technically better. What do you do?

  1. All true, and irrelevant. Their federation service and their security team decided years ago. Arguing spends goodwill you need for the questions where you can actually change the outcome.

  2. Protocol is tenant configuration, not an architectural commitment. Large regulated estates hand you SAML with no alternative, and being able to say yes immediately is worth more than the technical argument.

  3. That closes the door on newer estates, mobile flows and machine-to-machine cases, and it commits you to XML signature validation as your only path — which is the easiest thing in this whole design to get subtly wrong.

Make protocol a per-tenant configuration: issuer, certificate, protocol, attribute mapping, all resolved at sign-in. Validate the assertion’s own signature, audience, recipient and time bounds — and pin the certificate with its expiry in a calendar.

Why this piece earns its place

The part this glosses over is how you know which tenant a sign-in belongs to before you know who the user is. The obvious answer is the email domain they typed, and it holds until two tenants claim the same domain — an acquisition, a subsidiary, a contractor carrying an address at the parent company — or until someone types a domain belonging to a tenant they do not work for and you hand their browser a redirect to that tenant’s provider. Make resolution structural instead: every tenant gets its own sign-in endpoint, so the connection is in the URL and never inferred, with domain hints as a convenience layered on top. Verify domain ownership before you bind one at all. The same problem arrives from the other direction with provider-initiated SAML, where an assertion lands unsolicited and there is no request of yours to match it against — the tenant has to come from which endpoint received it, and you still check that the issuer inside the assertion is the one that endpoint is configured to trust. Otherwise the message is choosing its own trust anchor.

  • per tenantprotocol + config
  • sign the assertionnot just the wrapper
  • pin the certand calendar it

What the new pieces do

Identity Providerclient
The customer’s own identity system. It decides who exists, who they are, and — through SCIM — when they stop being an employee. You are a relying party, never the source of truth.
SAML / OIDCservice
Signature on the assertion (not just the response wrapper), audience, recipient, time bounds and in-response-to. Certificate pinned, and its expiry in a calendar — rotation is the classic 12-to-24-month outage.

Back of the envelope

support both, lead with OIDC
the customer decides
validate assertion signature
audience, recipient, time bounds
reject unsigned assertions
no fall-back branch
certificate expiry tracked
the classic 12–24 month outage

Step 3 · Key it correctly

The identifier that does not change

You keyed users on email, and it worked perfectly until the customer was acquired and every address changed on one weekend. Now every user is a stranger, their history is orphaned, and the fix is a data-repair project nobody budgeted for.

SAML / OIDCvalidate the assertionUser Recordimmutable subject id
New in this step: User Record.

Store the User Record under the provider’s immutable subject identifier — oid in Entra, a persistent-format NameID in SAML — and treat email as a display attribute that is allowed to change.

Why this piece earns its place

The assumption underneath this is that the subject identifier outlives the relationship, and it outlives everything except one event: the customer changing provider. Migrate a directory from one vendor to another and every subject identifier is reissued — the key chosen because it never changes has just changed for every user at once, and the system correctly treats an entire company as strangers. That is not an argument for keying on email. It is an argument for having a re-link path designed before the day you need it. Treat it as a one-time supervised migration: propose pairings between old records and new sign-ins using verified email, show the customer’s administrator the proposed list, have them approve it, and record who approved each link. What must never exist is a silent fall-back that matches on email whenever a subject identifier looks unfamiliar, because that is an account-takeover primitive — anyone who can set a display address at a provider you trust inherits somebody else’s account. Key by tenant and issuer alongside the subject too, since these identifiers are unique within a provider, not across the world.

  • immutable subject idthe key
  • emaildisplay only
  • retrofit costa data migration

What the new pieces do

User Recordservice
Keyed on the provider’s immutable subject identifier, with email as a display attribute. This one decision is what survives a marriage, a rebrand and an acquisition without a data-repair project.

Back of the envelope

keyed on immutable subject identifier
oid / persistent NameID
email is a mutable attribute
not an identity
attribute mapping explicit per tenant
names differ everywhere

Step 4 · The question that decides

SCIM, and the PATCH nobody implements

Single sign-on answers who is this. It does not answer should this person still have an account. A user removed from the directory cannot sign in — and their account, their API tokens and their scheduled exports all still exist.

Identity ProviderAuth ServiceUser RecordSCIM Endpoint
New in this step: SCIM Endpoint. · swipe to pan the diagram

You implemented SCIM DELETE. The customer offboards someone. What happens?

  1. Only if their identity provider calls DELETE — and most do not. Entra and Okta typically deactivate rather than delete, precisely so that history and audit trails survive the offboarding.

  2. There is no reconciliation sweep in this design, so nothing is delayed. Nothing happens at all, and no error is raised.

  3. The integration reports success, the dashboard stays green, and the departed employee keeps their access. It is the most common enterprise SSO defect there is, and it is exactly what gets tested.

Implement the SCIM Endpoint properly: idempotent creates, filtered lookups, pagination, and PATCH active=false as the primary deactivation path. If you cannot ship SCIM in time, offer a documented daily reconciliation as a compensating control with a date — reviewers accept that far more often than people expect.

Why this piece earns its place

Deactivation has to be a state change and never a delete, which has a consequence worth saying out loud: the record survives. Their content, their ownership of shared objects, their approvals and their name on things all stay, because a reviewer asking who signed this off last year needs an answer — and a cascading delete destroys the evidence at precisely the moment offboarding was supposed to produce it. It also has to be reversible. Contractors come back, people leave and return, and a provider expresses that as PATCH active=true on the same subject identifier with no other ceremony, expecting the account they had. So reactivation restores the record and re-resolves their group mappings — and restores nothing that was revoked. Old sessions and issued tokens stay dead; they get new ones by signing in. Implementing deactivation as a deletion breaks both halves at once: the history you owed a reviewer is gone, and the return trip becomes a blank new account, which the customer reads as your integration having lost their data.

  • PATCH active=falsethe real path
  • idempotentproviders retry
  • paginatetenants have thousands

What the new pieces do

SCIM Endpointservice
Idempotent, paginated, and correct about the one operation that matters: deactivation arrives as PATCH active=false far more often than as DELETE.

Back of the envelope

PATCH active=false handled first
DELETE is the rare case
idempotent creates
IdPs replay operations
409 on duplicate userName
correct status codes matter
every operation logged
this is audit evidence

Step 5 · Survive the reorg

Groups map to roles through a layer they control

You mapped their directory groups straight to permissions. It works for a month. Then a reorg renames FIN-AP-ANALYSTS, forty people lose access on a Monday, and you are paged for a change nobody told you about.

SAML / OIDCvalidate the assertionUser Recordimmutable subject idGroup → Rolecustomer-editable
New in this step: Group → Role.

Put a Group → Role table in between, editable by their admin in a screen. Their groups map to your small fixed role set — three is usually enough at go-live — which maps to permissions. Keep data scoping on a separate axis.

Why this piece earns its place

The question this table raises on its first day of real use is what happens when someone matches three mapped groups at once, which is normal — directories nest, and everybody is in an all-employees group. Taking the union is the default that feels safe and is not: a well-meaning administrator maps that broad group once so nobody is stranded, and from then on every person at the company carries whatever it granted, on top of everything else they match. Pick a resolution rule — highest wins, or most specific wins — and put it in the screen rather than in the documentation. The one thing that makes this table safe to hand over is a preview: the administrator types a real person’s name and sees the role they would end up with and which mapping produced it, before saving anything. The other pressure is on the role list itself. Every customer asks for one more role; each is easy to add and nearly impossible to withdraw later, because you cannot see who has come to depend on it. A list nobody can explain is how the mapping stops being reviewed at all.

  • 3 rolesat go-live
  • their admin editsnot you
  • unmapped→ deny, loudly

What the new pieces do

Group → Roledata
Their directory groups map to your small fixed role set through a table their own admin edits. Data scoping — "approver for EMEA only" — stays on a separate axis, or the role list explodes.

Back of the envelope

customer-editable mapping table
every change logged and attributed
small fixed role set
roles are your product, groups are theirs
data scoping on a separate axis
or the role list explodes
unmapped user denied with a message
never a silent default

Step 6 · Make revocation true

Sessions and tokens die with the account

Deactivation blocks new sign-ins. The user’s current session is still valid, their API token still works, and their nightly export still runs. You committed to revoking access within four hours and you have revoked nothing.

Auth ServiceSAML / OIDCUser RecordSCIM EndpointGroup → RoleSessions + Tokens
New in this step: Sessions + Tokens. · swipe to pan the diagram

Propagate deactivation to Sessions and Tokens: short lifetimes plus a revocation check, so access ends inside the promised window rather than whenever the user next signs in — which may be never.

Why this piece earns its place

The knob here is token lifetime, and it is set against the revocation check rather than on its own. Long lifetimes put that check on the hot path of every request, turning a security control into an availability question: when the revocation store is unreachable, failing open re-opens the hole you just closed, and failing closed takes the whole product down because one store blipped. Very short lifetimes avoid that and multiply refresh traffic against your auth service — and against the customer’s provider, if refresh re-validates there. What makes it tractable is the shape of the data. You never need to ask is this user still valid on every request; you need the set of subjects revoked recently, and recently is bounded by the longest token lifetime, so that set stays small enough to replicate everywhere and hold in memory. Failing closed is then cheap, because the thing you depend on is tiny. And the window you promised is not the token lifetime alone — it is that plus however long a revocation takes to reach every place that checks. Measure the second number before writing the first into a contract.

  • sessionsrevoked
  • API tokensrevoked
  • windowyou promised it

What the new pieces do

Sessions + Tokenscache
Short-lived tokens with a revocation check, so deactivation ends access inside the window you promised rather than at the user’s next sign-in — which may never come.

Back of the envelope

deactivation revokes sessions and tokens
not just new logins
short token lifetimes
bound the worst case
scheduled jobs re-check identity
exports outlive employment

Step 7 · Prove it

The evidence a reviewer asks for

The security review asks for a joiner–mover–leaver walkthrough, an audit log sample, and a break-glass procedure. You have all three behaviours and none of them written down, so the review takes three more weeks.

Auth ServiceUser RecordSCIM EndpointSessions + TokensAudit Log
New in this step: Audit Log. · swipe to pan the diagram

Log to an immutable Audit Log: every authentication, permission change, provisioning event and break-glass use — retained to their policy and exportable to their SIEM. Then package the artefacts: an identity architecture diagram, the JML walkthrough, ten real redacted log lines, the break-glass procedure, and a named gap list with dates.

Why this piece earns its place

The cheap version of this is pointing the reviewer at your application logs, and it loses for a reason that has nothing to do with volume. Those logs are mutable, rotated on a schedule chosen for operations rather than evidence, and written as sentences — a line saying a role was updated, with no field for who did it, in which tenant, or what the value was before. The first real question, show me every permission change on this user over the past year, then becomes a grep with a human reading the results, which is not evidence and does not survive being asked a second time. Audit events are structured records written in the same transaction as the change they describe, carrying actor, subject, tenant, before and after as fields, into an append-only stream with its own retention. The export is the other half, and it is an authorisation problem rather than a logging one: a customer pulling events into their own tooling must receive theirs and only theirs, from a path scoped per tenant and tested as carefully as sign-in. A cross-tenant leak in the audit export is the worst possible place to have one.

  • 10 real linesbeat any assurance
  • break-glassthey always ask
  • gap listvolunteered

What the new pieces do

Audit Logdata
Every authentication, permission change, provisioning event and break-glass use — immutable, retained to their policy, exportable to their SIEM. Ten real lines end a review that assurances do not.

Back of the envelope

auth, permission, provisioning, break-glass
all logged immutably
exportable to their SIEM
their tooling, not yours
JML walkthrough written
the leaver paragraph is the one they read
named gaps with dates
volunteered, not discovered

You did it

You just designed enterprise SSO & provisioning.

UserIdentity ProviderAuth ServiceSAML / OIDCUser RecordSCIM EndpointGroup → RoleSessions + TokensAudit Log
The finished design, end to end. · swipe to pan the diagram

Everything you assembled, in order

  • You are a relying party — the customer’s directory decides who exists and who has left.
  • Protocol is per-tenant configuration: support both, lead with OIDC, expect SAML.
  • Key users on the immutable subject identifier; email is a display attribute.
  • Deactivation arrives as PATCH active=false — a DELETE-only SCIM implementation fails silently.
  • Map their groups to your small fixed roles through a table their own admin edits.
  • Revocation must reach live sessions and API tokens inside the window you promised.
  • Package the evidence: diagram, JML walkthrough, real log lines, break-glass, and a volunteered gap list.

Where an interviewer pokes next

Getting the boxes right is the easy half. These are the questions that separate a candidate who drew the diagram from one who has run the thing. Answer each one out loud before you open it.

  1. Why is SCIM deactivation the question that decides enterprise deals?

    Because single sign-on answers who a user is and says nothing about whether they should still have an account. A person removed from the customer’s directory can no longer authenticate — but their user record, their issued API tokens, their scheduled exports and their integrations all continue to exist and, in many designs, continue to work. A security reviewer with a compliance obligation asks exactly one question about this, "what happens to access when someone leaves, and within how long?", and they test the answer. The specific trap is that most identity providers deactivate rather than delete, sending PATCH with active set to false so that history and audit trails survive the offboarding. An implementation that only handles DELETE returns success on every request, keeps a green dashboard, and offboards nobody — a control that fails silently, which is the worst possible failure mode for something whose entire value is being verifiable.

  2. Why key users on an immutable subject identifier rather than email?

    Because email addresses change and identities do not. People marry, companies rebrand, and an acquisition can rewrite every address in a directory over one weekend. If your user records are keyed on email, that event turns every existing user into a stranger: their permissions, their history and their audit trail are orphaned, and duplicate accounts appear as people sign in again. The fix afterwards is a data-repair migration that nobody budgeted for, run under time pressure, against a customer who is already unhappy. Keying on the provider’s immutable subject identifier — oid in Entra, a persistent-format NameID in SAML — costs nothing on day one and makes the whole class of problem disappear. Email is still worth storing, as a display attribute that is explicitly allowed to change.

  3. Why put a mapping table between their groups and your permissions?

    Because their group taxonomy is theirs to change and they will change it without telling you. Mapping directory groups straight to permissions works until a reorg renames FIN-AP-ANALYSTS to FIN-OPS-AP-TIER1, at which point forty people lose access on a Monday morning and you are paged for a directory edit you had no visibility into. An indirection layer — their groups map to your small fixed role set, which maps to permissions — turns that into a config change their own admin makes in a screen, with the change logged and attributed. Three roles is usually enough at go-live, and three roles the customer understands beats twelve only you can explain. Two rules make it safe: data-level scoping such as "approver for EMEA only" belongs on a separate axis or the role list explodes combinatorially, and a user who authenticates but matches no mapping must be denied loudly rather than granted a silent default.

  4. What does it actually take to revoke access within four hours?

    More than blocking new sign-ins, which is all that deactivation gives you by default. A user with a live session keeps working, an issued API token keeps working until it expires, and a scheduled export configured under their identity keeps running indefinitely — so a system that only checks status at authentication has revoked nothing measurable. Meeting a stated window means deactivation actively propagates: sessions invalidated, tokens revoked through a revocation check, and long-running jobs re-checking the identity they run as rather than trusting a credential captured at creation. Short token lifetimes bound the worst case so the check does not have to be perfectly synchronous. The clock in any contractual commitment starts at the directory event, not at the user’s next login attempt, which may never come — and that is the distinction most implementations miss until a reviewer asks them to demonstrate it.

  5. What evidence should you have ready before the security review starts?

    Five artefacts, and preparing them takes an afternoon while discovering you need them takes three weeks. A one-page identity architecture diagram showing the provider, the protocol, which claims flow, where the session lives and what talks to what with which identity — reviewers approve things they can picture. A joiner-mover-leaver walkthrough in three short paragraphs, where the leaver paragraph must contain a time bound. Ten real, redacted audit log lines showing authentication events, permission changes and data access, with the retention period stated, because "we log everything" is not evidence and ten lines are. A break-glass procedure describing what happens when their identity provider is down, which every reviewer asks about because the honest answer is often an undocumented local admin account. And a named gap list with dates — volunteering what you do not support yet is counter-intuitive and it is the strongest credibility signal available, because finding what you did not mention is the reviewer’s entire job.

Check yourself — the answers, and why

Eight steps in, these are the calls you should be able to make cold. Pick one, then read why.

  1. A customer insists on SAML 2.0 although OIDC is technically better. You should…

    Their federation service decided years ago. Lead with OIDC, expect SAML, configure per tenant.

  2. User records should be keyed on…

    Email changes on marriage, rebrand or acquisition; re-keying a live system afterwards is a data migration.

  3. In SCIM, offboarding usually arrives as…

    Most IdPs deactivate rather than delete. A DELETE-only implementation offboards nobody, silently.

  4. Directory groups should map to permissions…

    Their groups get renamed in reorgs. Indirection turns an incident into a config change they make themselves.

  5. Revoking access within a promised window requires…

    A live session or a valid token is still access. The clock starts at the directory event, not at next login.

How you’d open this design in an interview

Before any boxes: agree what it must do, pin the qualities that shape everything, then build — naming each trade-off as you make it. The walkthrough above is that exact order.

What it must do

Agree on these before drawing a single box.

  • Federate: one deployment, many tenants, each with its own identity provider and its own trust configuration.
  • Key correctly: store users under the provider’s immutable subject identifier, never under email.
  • Provision: SCIM create, update and — the one that matters — deactivate, which arrives as a PATCH.
  • Authorise: their groups map to your small fixed role set through a table their admin can edit.
  • Revoke: deactivation kills sessions and API tokens inside the window you promised, not at next login.
  • Evidence: every authentication, permission change and provisioning event logged and exportable.

The qualities that shape everything

Each one names the mechanism that buys it.

Many customers, one deployment
Per-tenant identity configuration resolved at sign-in — issuer, certificate, protocol, attribute mapping — with tenant isolation enforced below the auth layer, not by it.
Identity survives a domain migration
Users keyed on the provider’s immutable subject identifier, with email stored as a display attribute that may change without consequence.
Offboarding actually offboards
SCIM with PATCH active=false handled as the primary deactivation path, not only DELETE — most identity providers never call DELETE.
Authorisation survives a reorg
A customer-editable mapping table between their directory groups and your small fixed role set, so a renamed group is a config change rather than an incident.
Revocation inside the promised window
Deactivation propagates to live sessions and issued API tokens through a revocation check, bounded by short token lifetimes — not deferred to the next sign-in.
A security review that ends
Immutable logs of authentication, permission change, provisioning event and break-glass use, exportable to the customer’s SIEM.

The trade-offs you say out loud

Senior signal isn’t the boxes — it’s naming what you gave up and why it was the right price.

Keying users on the immutable subject id over keying on email address

Email changes — people marry, companies rebrand, an acquisition rewrites the whole directory. Re-keying a live system after a customer’s domain migration is a data-repair project nobody budgeted for, and it surfaces as duplicate accounts and lost history rather than as a clean error.

Handling SCIM PATCH active=false as the primary path over implementing DELETE only

Most identity providers deactivate rather than delete, so a DELETE-only implementation means offboarding silently does nothing while the integration reports success. It is the single most common enterprise SSO defect and the exact thing a security reviewer tests.

A group-to-role mapping table the customer edits over mapping directory groups straight to permissions

Their groups get renamed in reorgs you are not told about. An indirection layer turns that from a support incident into a config change their own admin makes, and it removes you from a loop that otherwise lasts the whole engagement.

Active revocation of sessions and tokens over checking status at next sign-in

A deactivated user with a live session or a valid API token still has access, so a "revocation" that waits for the next login does not meet any commitment you made. Short token lifetimes plus a revocation check is what makes a four-hour promise true.

Supporting SAML as well as OIDC over OIDC only, on technical merit

OIDC is the better protocol and the customer decides, not you. A large regulated enterprise with a mature federation service will hand you SAML with no alternative — arguing costs goodwill and does not change the outcome, so lead with OIDC and expect SAML.

The answer, out loud

What a strong answer to “Design Enterprise SSO & Provisioning” sounds like, first question to last trade-off. It is about 7 minutes of talking; the whiteboard and the interviewer fill the rest of the 45. Read it aloud once, then close the page and give it yourself.

  1. 0–4 min

    What this feature really is

    Let me start by naming what we’re building, because it changes what I optimise for. This isn’t a login page. It’s the thing a security reviewer interrogates before a large customer signs, and the question they always come to is what happens to access when somebody leaves, and how fast. So I’m designing for that reviewer as much as for the person signing in. The other thing I want on the table early is that we are never the source of truth about who exists — the customer’s directory is, and almost everything after this follows from accepting that instead of mirroring it.

  2. 4–9 min

    The skeleton

    The skeleton is small. A user reaches our auth service, the customer’s own identity system vouches for them, and we issue a session. We’re a relying party. I’d say early that we won’t be storing passwords for these users at all, because enterprise buyers refuse that in the first meeting — their leavers keep working accounts, their password policy doesn’t reach us, and their multi-factor requirement is unenforceable. Everything I add from here makes that relationship multi-tenant, then correct, then revocable, roughly in that order.

    Built in step 1: Let the right people in
  3. 9–15 min

    Federation, and who picks the protocol

    Then federation, and the first real decision: one deployment serving many customers, each with a different provider. I’d make protocol per-tenant configuration rather than an architectural commitment — issuer, certificate, protocol, attribute mapping, all resolved at sign-in. Lead with OIDC, expect SAML. I wouldn’t spend the meeting arguing for OIDC with a regulated customer whose federation team settled this years ago; saying yes immediately is worth more than winning that point. On validation, the thing I’d check is that we verify the signature on the assertion itself, not just the response wrapper, plus audience, recipient and time bounds. And the certificate expiry goes in a calendar at handover, because that’s the outage that turns up a year after go-live.

    Built in step 2: SAML or OIDC — and the customer decides
  4. 15–20 min

    The key that doesn’t move

    Next, how we key the user record: on the provider’s immutable subject identifier, with email stored as a display attribute that’s allowed to change. This looks like a detail and it’s the one I’d least want to get wrong, because nothing goes visibly wrong until the customer is acquired and every address changes over one weekend. At that point every user is a stranger, their history is orphaned, and the repair is a migration nobody budgeted for.

    Built in step 3: The identifier that does not change
  5. 20–27 min

    The question that decides the deal

    Now the part I’d spend the most time on. Single sign-on tells us who someone is. It says nothing about whether they should still have an account. So I want SCIM, and I want to be careful about deactivation specifically, because most providers don’t delete — they send a PATCH setting active to false so history survives on their side. If we only implement DELETE, every request succeeds, the dashboard stays green, and nobody is ever offboarded. That’s a control failing silently, and it’s exactly what gets tested. If we can’t ship SCIM by the date, I’d offer a documented daily reconciliation as a compensating control with a date on it.

    Built in step 4: SCIM, and the PATCH nobody implements
  6. 27–33 min

    Groups to roles

    For authorisation I wouldn’t map their directory groups straight onto permissions. Their group names belong to them and get rewritten in reorgs we never hear about, so I’d put a table in between that their own admin edits: their groups map to our small fixed role set, which maps to permissions. Three roles at go-live is usually enough, and three the customer understands beats twelve only we can explain. Data-level scoping, like approver for one region, sits on a separate axis or the role list explodes. And someone who authenticates but matches nothing gets denied with a message naming who to ask, never a quiet default.

    Built in step 5: Groups map to roles through a layer they control
  7. 33–39 min

    Making revocation true

    Then I’d make revocation mean something. Deactivating an account blocks new sign-ins and nothing else — the live session keeps working, the API token keeps working, the nightly export they configured keeps running. So deactivation has to actively reach sessions and issued tokens, with short lifetimes bounding the worst case, and scheduled jobs re-checking the identity they run as rather than a credential captured when they were created. And the clock in any commitment starts when the directory changed, not at the user’s next login, which may never come.

    Built in step 6: Sessions and tokens die with the account
  8. 39–43 min

    The evidence pack

    The last piece is evidence, prepared before the review rather than during it. An immutable log of authentications, permission changes, provisioning events and break-glass use, retained to their policy and exportable into their own tooling. Then the packet: a one-page identity diagram, a joiner-mover-leaver walkthrough where the leaver paragraph carries a time bound, ten real redacted log lines, the break-glass procedure, and a list of what we don’t support yet with dates against it. Volunteering that gap list feels wrong and it’s the strongest move available, because finding what you didn’t mention is the reviewer’s job.

    Built in step 7: The evidence a reviewer asks for
  9. 43–45 min

    What I’d trade, and what’s next

    The trade-off across all of this is that nearly every choice buys correctness later at the cost of work now, and the one I’d defend hardest is the indirection — the mapping table and the immutable key both exist so that a change on their side isn’t an incident on ours. With more time I’d spend it on the mover case, the one that gets skipped between joiner and leaver: the promotion that should also take access away, where nothing is deactivated and the old access quietly persists. And I’d want the customer able to test their own offboarding on demand, without us in the loop.

What this teaches

Learn system design by building the identity layer enterprise deals actually stall on. An interactive guide covering multi-tenant SAML and OIDC federation, a stable immutable user key, SCIM provisioning where deactivation is a PATCH rather than a DELETE, group-to-role mapping that survives a reorg, session and token revocation within the promised window, and the audit evidence a security reviewer asks for.

Key takeaways

  • You are a relying party — the customer’s directory decides who exists and who has left.
  • Protocol is per-tenant configuration: support both, lead with OIDC, expect SAML.
  • Key users on the immutable subject identifier; email is a display attribute.
  • Deactivation arrives as PATCH active=false — a DELETE-only SCIM implementation fails silently.
  • Map their groups to your small fixed roles through a table their own admin edits.
  • Revocation must reach live sessions and API tokens inside the window you promised.
  • Package the evidence: diagram, JML walkthrough, real log lines, break-glass, and a volunteered gap list.

Concepts covered

  • Why identity blocks the deal
  • Let the right people in
  • SAML or OIDC — and the customer decides
  • The identifier that does not change
  • SCIM, and the PATCH nobody implements
  • Groups map to roles through a layer they control
  • Sessions and tokens die with the account
  • The evidence a reviewer asks for
built for the question that decides the deal — what happens to access when someone leaves?
Finished this one? 0 / 65 System Designs done
NextDesign an Enterprise Eval Pipeline Next in “Become a Forward Deployed Engineer” · step 45 of 63

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More System Designs