A practice prompt we wrote. No company or candidate report names it, so it carries no company tag.
How to answer
A new login does nothing to a session that already exists, so a person who left this morning keeps working in yesterday’s browser tab until you revoke it. That is the half a clean SSO diagram leaves out, and it is the half the question asks for by name. Identity can be on the job description itself: as of September 2026, Okta’s postings list identity protocols, among them , and . Source 1Senior Forward Deployed Engineer - Okta for AI AgentsPublisherOkta (Greenhouse)Source typecompany job postingSource 2Principal Forward Deployed Engineer - Okta for AI AgentsPublisherOkta (Greenhouse)Source typecompany job postingSource 3Principal Forward Deployed Engineer (Singapore)PublisherOkta (Greenhouse)Source typecompany job posting
So split the question in two before you draw anything, and say the split out loud. Authentication answers “who is this person, right now”, and provisioning answers “should this person have an account here at all, and with which role”. SSO solves the first. Removing access lives in the second.
- Clarify the customer. Which identity provider, SAML or OIDC, whether their directory can push SCIM, and what “the day someone leaves” means to their security team: the moment HR records the exit, or the end of that day.
- Sign-in. Service-provider-initiated login, routing by verified email domain, one IdP connection per customer. Name the assertion checks you never skip.
- Provisioning. SCIM for create, update and deactivate; just-in-time creation only as the fallback.
- De-provisioning, end to end. The deactivate event disables the user, revokes sessions and API tokens, and hands their owned objects to someone. Say how big the gap is when there is no SCIM, and how you bound it.
- Roles. A per-customer table that maps directory groups to your roles, with the least privilege as the default.
- Failure. IdP outage, missed SCIM events, a break-glass admin.
Close with the : one customer, OIDC sign-in, and a SCIM deactivate that ends a live session, shown in a test.
The trap is a clean SAML sequence diagram and nothing after it. Every way into your product needs a bound on how long a leaver keeps it, and you should be able to say each one.
Follow-ups
What the interviewer may ask next, once your first answer is on the table.
- What happens to an active session the day someone leaves?
- The customer’s identity provider is down. What happens to sign-in?
- Groups in their directory do not match your roles. How do you map them?
Where answers go wrong
- Designs SSO and forgets de-provisioning.
Answer this in two minutes
Write the answer you would say out loud. The clock starts with your first word.
Compare with the model answer
Model answer
Clarify. I’d ask four things: which IdP (say Okta or Microsoft Entra ID), whether they can run , whether “the day they leave” means the moment HR records it, and whether our product has API tokens or integrations a person can create. I’ll assume , SCIM, and a target we own: access ends within 5 minutes of our receiving their SCIM deactivate. Two gaps before that are theirs, and I write each down separately: how fast HR’s record reaches their IdP, which is their process, and how often their IdP pushes changes to us, which is their product’s schedule, not ours.
Sign-in. A tenant_idp table holds each customer’s issuer, client ID, verified domains and group mapping. The login page asks for an email, finds the tenant by verified domain, and starts an authorization code flow with PKCE against that issuer. On the callback I validate the ID token per OpenID Connect Core, section 3.1.3.7: signature against the issuer’s JWKS, iss, aud, exp and nonce.
Many large customers run , so I support both. For SAML I use a maintained library and check signature, audience, NotOnOrAfter, InResponseTo and a replay cache. IdP-initiated logins, from the tile in their portal, have no InResponseTo, so I redirect them into an SP-initiated flow. I read their metadata URL and alert 30 days before their signing certificate expires, because an expired certificate locks out the whole tenant.
Sign-in finds the user by (tenant_id, iss, sub), or SCIM’s externalId, never by email, because addresses get renamed and reassigned; a new hire given a departed colleague’s address must not inherit that account. A disabled user stays disabled at sign-in; just-in-time creation, where a tenant opts in, never re-activates one. Once a tenant is on , I turn off every other way in for its verified domains: password login, password reset, magic links and social login. Passwords set before SSO are invalidated, not left dormant. The only exception is the break-glass admin below.
Provisioning. We expose a SCIM endpoint per RFC 7644, with the User schema from RFC 7643. Their directory creates users, updates attributes and group membership, and on exit sends PATCH /Users/{id} with active: false, or a DELETE, after which that user returns 404. The endpoint takes a per-tenant bearer token we can rotate. The deactivate is idempotent, because their directory retries, and a later PATCH with active: true re-enables a rehire without restoring their old sessions or tokens. Both exit calls land in the same handler:
def deactivate(tenant_id: str, user_id: str, source: str) -> None:
with db.transaction():
if users.status_for_update(tenant_id, user_id) == "disabled":
return # their directory retried; nothing left to do
users.set_status(tenant_id, user_id, "disabled")
users.bump_session_epoch(tenant_id, user_id) # for JWTs
sessions.revoke_all(tenant_id, user_id)
tokens.revoke_all(tenant_id, user_id) # API tokens, OAuth
jobs.pause_owned_by(tenant_id, user_id) # schedules, syncs
outbox.add("handoff", tenant_id, user_id) # runs after commit
audit.log("user.deactivated", tenant_id, user_id,
source=source)
Revocation and the handoff request commit together. The slow reassignment of what they owned runs later from the outbox, under the customer’s policy for who inherits, so it can never roll back the revocation, and a crash can’t lose it.
Sessions are server-side and every request checks them, which is what makes the first-slice test true. If the API must use JWTs, each request also checks the per-user session_epoch that deactivate bumps. A token that lives 10 minutes, with no such check, leaves the leaver 10 minutes, and I’d say that number instead of hiding it. Where the customer’s IdP supports it, I also accept OIDC Back-Channel Logout, which ends our session when their IdP ends theirs; it does not replace the SCIM deactivate.
Without SCIM. The browser gap is the session lifetime, so I cap it (max_session=8h, then re-authentication at their IdP). Anything that never returns to the IdP has no bound at all, because it never ends on its own: personal API tokens, grants, mobile refresh tokens. So for tenants without SCIM, personal tokens and OAuth grants expire at max_token_age=8h or are replaced by tenant-owned service accounts, and a mobile refresh is honored only while a refresh against their IdP still succeeds. I give the security team both numbers in writing.
Every way in, and when it closes. Every path in has a bound I can name.
| Way in | Closes |
|---|---|
| Browser session | Next request after the SCIM deactivate; without SCIM, the 8 hour session cap |
| API with JWTs | Next request, through session_epoch; else the token lifetime |
| Personal tokens and OAuth grants | At the deactivate; without SCIM, 8 hours |
| Mobile refresh tokens | At the deactivate; without SCIM, the next refresh at their IdP |
| A missed SCIM event | The next hourly reconciliation |
Roles. A group_role_map(tenant_id, idp_group, role) table the customer admin edits. Unmapped groups get no access, not a default viewer role, and every mapping change is audited.
Failures. If the IdP is down, existing sessions keep working until they expire, and new sign-ins fail. I don’t fall back to passwords for everyone; one break-glass admin per tenant has a local credential with hardware MFA and an alert on every use.
SCIM events can be missed, so an hourly job reads the user list from their directory’s API and disables anyone active with us who is inactive or missing there; a user hard-deleted in their directory counts as inactive. A missed event then costs at most an hour, and I write that next to the target. The job needs a read-only directory credential, which I ask their identity team for in the first meeting, because that approval takes longer than the code. I measure deactivation lag per tenant, from our receiving the SCIM request to the last request we accepted from that user, and alert when it breaks the target.
First slice. One pilot tenant, OIDC login, and a SCIM deactivate with an integration test that asserts a live session gets 401 on its next request.