Identity & Access Deep Dive
SAML, OAuth/OIDC, SCIM and lifecycle automation at config depth
SAML at config depth
After this you can debug a SAML integration the way an interviewer will ask you to.
Every IT technical screen reaches the same moment: "a user can't log into app X via SSOSingle Sign-On. One company login (usually via SAML or OIDC) instead of a separate password per tool. - walk me through it." The candidates who pass don't recite the spec, they read a decoded assertion out loud and name the field that's wrong.
SAMLAn enterprise standard that powers single sign-on. is a browser-redirect protocol that lets a user authenticate once at the IdP (Okta, Entra) and ride that login into a SP (the app - Slack, Zoom, an internal tool). The IdP packages identity into a signed XML assertion and the SP trusts it because of a shared certificate. Nothing in the flow is secret; the trust comes entirely from the signature.
- IdP - Identity Provider
- Holds the identity and signs the assertion (Okta, Entra, Google)
- SP - Service Provider
- The app the user wants in; consumes the assertion at its ACS URL
- Assertion
- Signed XML stating who the user is, plus attributes, plus validity conditions
- Metadata
- XML the two sides exchange once: entity IDs, ACS URL, signing certificate
SP-initiated vs IdP-initiatedwhere the flow starts
The difference is just where the user begins. SP-initiated is the common, safer path; IdP-initiated skips the SP's request and is a frequent source of the dreaded "unsolicited response" error.
- 1SP-initiated. User hits the app, the SP redirects to the IdP with an
AuthnRequest, the IdP authenticates them, then POSTs a signed assertion back to the SP's ACS URL. - 2IdP-initiated. User clicks a tile in the Okta dashboard, the IdP POSTs an assertion to the SP cold - no prior
AuthnRequest. Apps that require a matching request will reject it as unsolicited.
Inside the assertionthe fields you'll be asked to read
- Element
- NameID
- What it carries
- The user identifier the SP keys on (email, UPN, persistent ID)
- Why it breaks logins
- Format mismatch means the SP can't find the account
- Element
- AttributeStatement
- What it carries
- Claims: groups, first/last name, department
- Why it breaks logins
- Wrong attribute names break role mapping and JIT user creation
- Element
- Conditions / Audience
- What it carries
- Who the assertion is valid for + NotBefore/NotOnOrAfter
- Why it breaks logins
- Audience ≠ SP entity ID or clock skew, voids it
- Element
- Signature
- What it carries
- The IdP's signature over the assertion or response
- Why it breaks logins
- Rotated/expired cert means signature validation fails
| Element | What it carries | Why it breaks logins |
|---|---|---|
| NameID | The user identifier the SP keys on (email, UPN, persistent ID) | Format mismatch means the SP can't find the account |
| AttributeStatement | Claims: groups, first/last name, department | Wrong attribute names break role mapping and JIT user creation |
| Conditions / Audience | Who the assertion is valid for + NotBefore/NotOnOrAfter | Audience ≠ SP entity ID or clock skew, voids it |
| Signature | The IdP's signature over the assertion or response | Rotated/expired cert means signature validation fails |
Decode a real assertion (base64 → XML) and you can point at the failing line.
Signing vs encryption
Signing proves the assertion came from the IdP and wasn't altered; it's mandatory. Encryption hides the assertion contents from the browser that relays it and is optional, used when attributes are sensitive. Most break-fix work is signature-related, because certificates expire and rotate.
The troubleshooting treesay this structure out loud
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
Narrate this order; the signature/cert check is the gate that catches whole-app outages.
- 1Isolate scope. One user or everyone? One user points at attributes or account state; everyone points at config or a rotated cert.
- 2Capture the SAMLAn enterprise standard that powers single sign-on. trace. Use the browser SAML-tracer extension or Okta's System Log to grab the raw response, then base64-decode the assertion.
- 3Check the signature and cert. Did the IdP signing certificate rotate without updating the SP? This is the single most common total outage.
- 4Check Audience and ACS URL. The
Audiencemust equal the SP's entity ID and the response must land on the registered ACS URL. - 5Check timestamps.
NotBefore/NotOnOrAfterplus server clock skew - a few minutes of drift kills assertions. - 6Check the NameID and attributes. Right format? Right value? Are group claims arriving with the names the SP expects?
Certificate rotation is the outage that wakes you up. When an Okta app's signing cert rolls (or the SP rotates theirs), every login fails at signature validation until both sides hold the new cert. In the interview, naming "rotated signing certificate" first when an entire app goes dark signals you've actually run this in production.
When handed "user can't SSOSingle Sign-On. One company login (usually via SAML or OIDC) instead of a separate password per tool. into Zoom," don't guess a cause - narrate the tree. "First I'd check if it's one user or all of them, then pull the SAMLAn enterprise standard that powers single sign-on. trace and decode the assertion." The structure is what they're grading; a candidate who jumps straight to "probably the cert" looks lucky, not rigorous.
Takeaway. SAMLAn enterprise standard that powers single sign-on. trust lives in the signature; debug by decoding the assertion and checking signature/cert, Audience/ACS, timestamps, then NameID/attributes - in that order.
Self-check
QAn entire app's SSOSingle Sign-On. One company login (usually via SAML or OIDC) instead of a separate password per tool. breaks at once - every user gets a signature-validation error. What's the most likely cause?
OAuth 2.0 & OIDC flows
After this you can pick and defend the right flow for a given integration.
The fastest way to lose credibility in an identity screen is to say "we'll use OAuth to log the user in." OAuth doesn't log anyone in. Naming that boundary cleanly is the first thing a sharp interviewer listens for.
OAuth 2.0 is an authorization framework - it answers "can this client call this API on the user's behalf" and hands back an access token. OIDCOpenID Connect. A modern standard that powers single sign-on, built on OAuth. is a thin identity layer on top that adds an ID token, a signed JWT stating who the user is. You ask OAuth for permission to act; you ask OIDC who just authenticated.
The grants worth memorizingpick by who holds the secret
- Grant
- Authorization Code + PKCE
- Use it for
- Interactive apps, SPAs, native/mobile
- Why
- Public client with no safe secret; PKCE binds the code to the requester
- Grant
- Client Credentials
- Use it for
- Service-to-service, your automation calling Okta/Google APIs
- Why
- No human in the loop; the service authenticates as itself with a real secret
- Grant
- Device Authorization
- Use it for
- Headless boxes, CLIs, TVs
- Why
- No browser locally; user approves on a phone with a short code
- Grant
- Implicit / ROPC
- Use it for
- Nothing new
- Why
- Deprecated - implicit leaked tokens in URLs, ROPC handles raw passwords
| Grant | Use it for | Why |
|---|---|---|
| Authorization Code + PKCE | Interactive apps, SPAs, native/mobile | Public client with no safe secret; PKCE binds the code to the requester |
| Client Credentials | Service-to-service, your automation calling Okta/Google APIs | No human in the loop; the service authenticates as itself with a real secret |
| Device Authorization | Headless boxes, CLIs, TVs | No browser locally; user approves on a phone with a short code |
| Implicit / ROPC | Nothing new | Deprecated - implicit leaked tokens in URLs, ROPC handles raw passwords |
Auth Code + PKCE is the modern default for anything a human logs into.
Why PKCE and why not implicit
A public client (a desktop app, a SPA) can't keep a secret - anything shipped to a user's machine can be extracted. PKCE solves this without a secret: the client generates a random code_verifier, sends its SHA-256 hash up front, then proves possession when it redeems the code. An intercepted authorization code is worthless without the verifier.
code_verifier = random(64) // kept in memory on the client
code_challenge = base64url(sha256(code_verifier))
// 1. authorize: ?code_challenge=...&code_challenge_method=S256
// 2. user logs in -> redirect back with ?code=...
// 3. token: POST { code, code_verifier } // server recomputes the hashImplicit returned tokens directly in the redirect URL fragment, where they leaked into history, referrer headers and logs. It's deprecated and PKCE replaced it for browser clients. Naming that when asked "why not implicit" signals you track the current spec.
Three token types, three jobsknow where each is validated
- Access token
- Short-lived (minutes); sent to APIs; validated by the resource server against scopes
- Refresh token
- Long-lived; held carefully; traded for a new access token at the token endpoint
- ID token
- OIDCOpenID Connect. A modern standard that powers single sign-on, built on OAuth. only; proves who logged in; validated by the client, never sent to APIs
Sending an ID token to an API or an access token to a client is a classic tell.
The pattern you'll actually buildautomating the SaaS stack
Most of your OAuth work as an IT engineer is service-to-service: a script that provisions a Slack user, pulls Okta logs or manages Google Workspace groups. That's client credentials (or a Google service account with domain-wide delegation), not interactive login.
Service account + domain-wide delegation.
Scope it to exactly the Admin SDK methods you call - directory read/write only.
Bot/app token with granular OAuth scopes.
Request users:read, not admin, unless you truly run SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave./admin actions.
API token or OAuth client-credentials app.
Prefer a scoped OAuth service app over a long-lived super-admin API token.
Security gotchas to name unprompted
- Exact-match redirect URIs. Wildcards turn PKCE into theater - the code gets delivered to the attacker's URL.
- Least-privilege scopes. A token that reads one group is a smaller breach than one that admins the tenant. Scope is your blast-radius dial.
- Secret rotation. Client secrets and API tokens live in a secrets manager, rotate on a schedule and never sit in a repo or a Slack message.
- Token storage. Refresh tokens are bearer credentials - anyone who has one is the user until it's revoked.
When asked to design an integration, lead with the secret question: "Is there a human and a browser or is this a backend service? If it's my automation calling the Okta API, that's client credentials with a scoped service app, not a personal admin token." That framing shows you reach for least privilege by reflex.
Don't conflate authentication and authorization. "Log the user in with OAuth" is the single most common giveaway that someone learned auth from copy-paste. Login is OIDCOpenID Connect. A modern standard that powers single sign-on, built on OAuth.; OAuth grants API access.
Takeaway. Pick the grant by who holds a secret: Auth Code + PKCE for humans, client credentials for your automation, device flow for headless - and keep OAuth (authorization) separate from OIDCOpenID Connect. A modern standard that powers single sign-on, built on OAuth. (identity).
Self-check
QYou're writing a Python script to deprovision users in Slack via its API. Which OAuth grant fits and what's the access principle?
SCIM provisioning & deprovisioning
After this you can explain and troubleshoot automated provisioning across the stack.
SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. is the difference between offboarding that happens in seconds and offboarding that sits in a ticket queue for three days while a departed employee still has live access. The deprovisioning half is where IT security actually lives.
SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. 2.0 is a standardized REST schema for synchronizing users and groups between an IdP and downstream apps. The IdP is the source; it pushes create, update and deactivate events to each app's SCIM endpoint as identities change. It's the engine behind "auto-provisioning" in Okta and Entra.
- SCIM operation
- Create user
- HTTP
- POST /Users
- Lifecycle meaning
- Joiner - account spun up in the app on assignment
- SCIM operation
- Update / replace
- HTTP
- PUT or PATCH /Users/{id}
- Lifecycle meaning
- Mover - attribute or group change recalculated downstream
- SCIM operation
- Deactivate
- HTTP
- PATCH active:false
- Lifecycle meaning
- Leaver - access cut without deleting history (audit-safe)
- SCIM operation
- Group membership
- HTTP
- PATCH /Groups/{id}
- Lifecycle meaning
- Push/pull membership so app roles track IdP groups
| SCIM operation | HTTP | Lifecycle meaning |
|---|---|---|
| Create user | POST /Users | Joiner - account spun up in the app on assignment |
| Update / replace | PUT or PATCH /Users/{id} | Mover - attribute or group change recalculated downstream |
| Deactivate | PATCH active:false | Leaver - access cut without deleting history (audit-safe) |
| Group membership | PATCH /Groups/{id} | Push/pull membership so app roles track IdP groups |
PATCH active:false is the offboarding workhorse - disable, don't delete.
Attribute and group mappingwhere it silently goes wrong
SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. only works if the IdP attributes map cleanly onto the app's expected schema. A mismatch doesn't always error loudly - it provisions a user with a blank department or no role and you find out when someone can't see the channel they need.
- 1Map core attributes.
userName,emails,name.givenName/familyNameand any app-specific custom attributes the SP requires. - 2Decide group strategy. Either push IdP groups as SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. groups or map IdP groups to app roles. Pick one model per app and document it.
- 3Test with one user. Provision a test identity, verify it lands with the right role and attributes, then move it to a different group and confirm the change propagates.
- 4Confirm deactivation. The single most important test: deactivate the test user in the IdP and verify access is actually gone in the app, not just hidden.
Drift and reconciliationthe reality of distributed state
Apps drift. An admin grants access directly in Slack, a SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. webhook silently fails or an app was provisioned before SCIM existed. Now the app's state diverges from the IdP, which is exactly the gap an auditor or attacker finds.
Manual grants made directly in the app, bypassing the IdP.
Failed/dropped SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. events with no retry or alert.
Pre-SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. accounts never reconciled into the lifecycle.
Periodic job: pull app users, diff against IdP truth, flag deltas.
Auto-remediate the safe cases (deactivate orphaned accounts); ticket the rest.
Alert on SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. failures so drift never accumulates silently.
When SCIM isn't availableown the gap with code
Plenty of apps in a real stack have no SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. support or only support it on a tier the company doesn't pay for. This is where the engineer-not-help-desk mindset shows: you don't shrug and offboard by hand, you write the provisioning yourself.
def deprovision(email: str) -> None:
for app in NO_SCIM_APPS:
user = app.find_user(email)
if user is None: # already gone -> safe to re-run
log.info("%s absent in %s", email, app.name)
continue
app.deactivate(user.id) # disable, don't delete
log.info("deactivated %s in %s", email, app.name)Provisioning that's a day late is an inconvenience. Deprovisioning that's a day late is a live credential in the hands of someone who no longer works here. Treat offboarding as a same-second event with an audit record and be visibly obsessive about it in the interview - it's the instinct Security wants to hear.
When SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. comes up, volunteer the drift problem before they ask: "SCIM handles the happy path, but I'd run a reconciliation job that diffs each app against the IdP, because manual grants and silent webhook failures are how access leaks accumulate." That moves you from configuring a feature to owning a system.
Takeaway. SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. syncs users/groups from the IdP outward; deactivate (don't delete) on leave and run a reconciliation job to catch the drift SCIM's happy path misses.
Self-check
QOn offboarding via SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave., what's the correct operation and why not delete?
Lifecycle automation (Joiner/Mover/Leaver)
After this you can design HRIS-driven identity lifecycle end-to-end.
"Design an automated JML pipeline" is the canonical systems-design prompt for this role. The strong answer starts from one principle: the HRIS is the source of truth and identity flows downhill from it without a human in the loop.
JML - Joiner, Mover, Leaver - is the identity lifecycle. The HRIS (Workday, Rippling, BambooHR) records the human-resources fact; everything else reacts. Identity events flow HRIS → IdP → SaaS apps over SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. and API, so onboarding and offboarding are instant, consistent and audited.
- Source of truth
- HRIS - start date, role, department, manager, termination
- Orchestrator
- IdP (Okta/Entra) or a workflow engine that watches HRIS events
- Access model
- Group-based - role/department maps to groups, groups map to app access
- Targets
- SaaS apps via SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave., plus MDM for device provisioning/wipe
Joinerinstant day-one experience
- 1Trigger. HRIS marks a new hire active on the start date (or a few days ahead for pre-provisioning).
- 2Create identity. IdP creates the account, sets the username convention and enrolls MFA.
- 3Assign group-based access. Role + department drive group membership; groups auto-grant the right SaaS apps via SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. - no manual app-by-app grants.
- 4Provision the device. MDM zero-touch enrollment ships a configured laptop tied to the new identity.
- 5Day-one experience. Welcome flow, accounts ready, no "file a ticket to get Slack" friction.
Moverthe case people forget
A role or department change should recalculate access automatically - add what the new role needs, remove what the old one granted. The failure mode is access accretion: people collect permissions as they move and never lose the old ones, which is how you end up with a marketing manager who can still touch the finance system.
Movers are where most JML designs leak. If you only add access on a transfer and never revoke the prior role's groups, you build standing privilege that no access review can keep up with. Say explicitly that a mover event recomputes the full group set and removes stale membership - that one sentence separates a real design from a checklist.
Leaversame-second, fully audited
- 1Trigger. HRIS marks termination; for involuntary exits, support an immediate manual override that fires now.
- 2Deactivate identity. Disable the IdP account, which cascades SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. deactivation to every connected app.
- 3Catch the non-SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. apps. Script-based deprovision for anything without SCIM, so there's no manual gap.
- 4Handle the device. MDM lock or remote wipe and reclaim the hardware.
- 5Write the audit record. Log what was revoked, when and by what trigger - this is your offboarding evidence for SOC 2.
Engineering the pipeline wellwhat makes it production-grade
- Idempotent. Re-running a leaver event on an already-offboarded user is a no-op, never an error - events get redelivered.
- Retried with backoff. A downstream API being down can't drop a deprovision; queue it, retry and alert if it stays stuck.
- Audited end-to-end. Every action emits a record: who, what, when, triggered by which HRIS event.
- Alerted on failure. A silent deprovision failure is the worst outcome - page on it.
- Version-controlled. The mappings and workflow logic live in Git, reviewed like any other code.
"HRIS is my source of truth. A leaver event disables the IdP account, which cascades SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. deactivation across every connected app; a script handles the non-SCIM stragglers; MDM wipes the device; and the whole thing writes an audit record. It's idempotent and retried, so a redelivered event or a flaky API never leaves a live credential behind."
Takeaway. HRIS is the source of truth; identity flows HRIS → IdP → apps, access is group-based and movers must recompute (not just add) access - built idempotent, retried and audited.
Self-check
QWhy must the leaver workflow be idempotent and what does that mean concretely?
Authorization models & least privilege
After this you can design access that's both secure and low-friction.
The goal isn't to lock everything down - it's to make the right access automatic and the wrong access impossible to keep. Standing privilege is debt; you design so it pays itself off.
Three models do the heavy lifting and a real environment combines them. The interview test is whether you can say when each fits rather than reciting definitions.
- Model
- RBACRole-Based Access Control. Granting permissions by role rather than configuring each person individually.
- Access keyed on
- Role → a fixed set of permissions
- Fits when
- Stable, well-defined job functions; the default for most apps
- Model
- ABAC
- Access keyed on
- Attributes (dept, location, clearance, device)
- Fits when
- Context-sensitive rules RBACRole-Based Access Control. Granting permissions by role rather than configuring each person individually. can't express cleanly
- Model
- Dynamic groups
- Access keyed on
- Live attribute query → auto membership
- Fits when
- Membership should track HR data with zero manual upkeep
| Model | Access keyed on | Fits when |
|---|---|---|
| RBACRole-Based Access Control. Granting permissions by role rather than configuring each person individually. | Role → a fixed set of permissions | Stable, well-defined job functions; the default for most apps |
| ABAC | Attributes (dept, location, clearance, device) | Context-sensitive rules RBACRole-Based Access Control. Granting permissions by role rather than configuring each person individually. can't express cleanly |
| Dynamic groups | Live attribute query → auto membership | Membership should track HR data with zero manual upkeep |
RBAC for the backbone, ABAC for the nuance, dynamic groups to keep both self-maintaining.
These combine: a dynamic group built from an ABAC-style query ("department = Engineering AND employment = full-time") becomes the RBACRole-Based Access Control. Granting permissions by role rather than configuring each person individually. unit that grants a bundle of apps. Attributes feed groups, groups grant roles.
Group-based access is the unit of provisioningno manual one-offs
Access should derive from role and attributes, never from a manual "add Jordan to this app" request. When access is a property of who you are, JML automation can grant and revoke it deterministically. One-off grants are exactly the entries that survive offboarding and show up in an audit.
Least privilege and just-in-time elevationshrink standing access
- Standing access
- Always-on permission; the larger your attack surface and audit burden
- Just-in-time (JIT)
- Elevation requested and granted for a task, then auto-expires
- Time-boxed
- Sensitive access (prod, admin consoles) granted for hours, not forever
- Default posture
- Revoke by default - access has to be justified to persist
For sensitive systems - production, the IdP admin console, finance - the right pattern is request-and-expire rather than a permanent grant. The person asks for elevation, it's approved (or auto-approved by policy) and it evaporates on a timer. The audit log then shows exactly who had power and for how long.
Access reviews and recertificationthe SOC 2 tie-in
- Recurring, not annual-panic. Quarterly recertification where owners attest that each person still needs each grant.
- Partly automated. Generate the review from live IdP/app state; the human only judges the deltas, not the whole list by hand.
- Evidence-producing. Each review leaves a timestamped record auditors accept as proof of the control operating.
- Closed-loop. Revocations from the review flow back through the same group mechanism that grants access.
Frame least privilege as an enabler, not a brake - that's the security-as-enabler value Cursor screens for. "Group-based access plus JIT elevation means engineers get what they need instantly and lose it automatically, so I improve posture without adding a single approval queue people route around." Security that's frictionless is security that actually holds.
Beware access sprawl. Every manual grant and every standing admin role is debt that compounds and at hypergrowth headcount it compounds fast. Design for revocation by default so the system trends toward least privilege on its own, rather than relying on a heroic annual cleanup.
Takeaway. Make access a property of role and attributes (group-based), keep sensitive grants just-in-time and time-boxed and design for revocation by default so standing privilege never accumulates.
Self-check
QEngineers need occasional production access. A standing 'prod-admin' group is easy but risky. What do you propose instead?
IdP administration (Okta / Entra)
After this you can speak fluently about running the IdP day-to-day.
The IdP is the single most security-critical system you'll run - own it and you own access to everything. Interviewers want to hear that you treat it with the operational discipline that blast radiusHow much breaks if a change goes wrong; the scope of potential damage. deserves.
App integration patternscatalog vs custom
Most integrations come from the IdP's app catalog (OIN in Okta, the gallery in Entra), which ships pre-built SAMLAn enterprise standard that powers single sign-on./OIDCOpenID Connect. A modern standard that powers single sign-on, built on OAuth. and SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. config for known apps. For homegrown or unlisted apps, you create a custom SAML or OIDC app and wire metadata, ACS URL, attribute statements and provisioning by hand.
Pre-built protocol + SCIMSystem for Cross-domain Identity Management. A standard for automatically creating and removing user accounts when people join or leave. config for a known SP.
Faster, fewer mistakes; you still set attribute/group mappings.
For internal or unlisted apps.
You own entity ID, ACS URL, signing cert, claims and provisioning fallback.
MFA and passwordlessphishing-resistant by default
Not all factors are equal. SMS and TOTP are phishable; FIDO2/passkeys are phishing-resistant because the credential is bound to the origin and never leaves the device. For a security-forward company, the target is phishing-resistant MFA as the baseline, with weaker factors phased out.
- Factor
- SMS / voice
- Phishing-resistant?
- No - SIM-swap and relay attacks
- Use as
- Last resort, deprecate where possible
- Factor
- TOTP authenticator
- Phishing-resistant?
- No - codes can be relayed
- Use as
- Acceptable fallback, not the goal
- Factor
- Push with number-match
- Phishing-resistant?
- Better - defeats push fatigue
- Use as
- Reasonable interim
- Factor
- FIDO2 / passkey
- Phishing-resistant?
- Yes - origin-bound credential
- Use as
- Baseline target for the workforce
| Factor | Phishing-resistant? | Use as |
|---|---|---|
| SMS / voice | No - SIM-swap and relay attacks | Last resort, deprecate where possible |
| TOTP authenticator | No - codes can be relayed | Acceptable fallback, not the goal |
| Push with number-match | Better - defeats push fatigue | Reasonable interim |
| FIDO2 / passkey | Yes - origin-bound credential | Baseline target for the workforce |
Drive the fleet toward passkeys; keep one phishable fallback only for recovery edge cases.
Risk-based & conditional accesscontext gates the login
Conditional access lets you require more (or block) based on signals: is the device managed and compliant, is the network expected, is the sign-in behavior anomalous. This is the IdP side of zero-trust - access is granted on posture, not just a correct password.
- Device posture
- Managed + compliant via MDM device trust; block unmanaged for sensitive apps
- Network / location
- Step-up or block on impossible-travel or unexpected geos
- Behavior / risk score
- Anomalous sign-in triggers re-auth or denial
- App sensitivity
- Finance/prod consoles demand stricter conditions than a wiki
Admin hygieneprotect the thing that protects everything
- Scoped admin roles. No one carries super-admin for daily work; delegate the narrowest role that does the job.
- API tokens as service apps. Prefer scoped OAuth service apps over long-lived super-admin API tokens and rotate them.
- Break-glass accounts. A small number of emergency accounts, MFA-exempt only by deliberate design, vaulted, alerted on every use.
- Logging everywhere. Stream the System Log to the SIEM; admin actions and sign-in events are your forensic record and SOC 2 evidence.
Okta vs Entrahave a view, hold it lightly
- Dimension
- Sweet spot
- Okta
- Best-of-breed, app-agnostic, huge OIN catalog
- Entra ID
- Deep in Microsoft 365 / Azure shops
- Dimension
- Lifecycle
- Okta
- Strong workflows + universal directory
- Entra ID
- Strong when the org lives on Microsoft
- Dimension
- Cost model
- Okta
- Standalone spend
- Entra ID
- Often bundled with existing M365 licensing
- Dimension
- Pick it when
- Okta
- Mixed SaaS stack, want neutral identity hub
- Entra ID
- Already all-in on Microsoft and want one bill
| Dimension | Okta | Entra ID |
|---|---|---|
| Sweet spot | Best-of-breed, app-agnostic, huge OIN catalog | Deep in Microsoft 365 / Azure shops |
| Lifecycle | Strong workflows + universal directory | Strong when the org lives on Microsoft |
| Cost model | Standalone spend | Often bundled with existing M365 licensing |
| Pick it when | Mixed SaaS stack, want neutral identity hub | Already all-in on Microsoft and want one bill |
State a preference with a reason, then concede the other side's case - that's how staff engineers argue.
If asked Okta vs Entra, don't dodge - commit and qualify: "I lean Okta for a SaaS-diverse, vendor-neutral stack because the catalog and lifecycle workflows are strong, but in a Microsoft-everything org Entra's bundling and tight M365 integration usually win." A reasoned preference plus an honest trade-off reads as senior; "it depends" with no opinion reads as evasive.
Before the loop, be able to answer for any IdP you've run: where do admin tokens live and when did they last rotate, how many super-admins exist, are break-glass accounts vaulted and alerted and is the System Log shipping to a SIEM? Concrete answers here are the texture that separates an operator from someone who read the docs.
Takeaway. The IdP is your highest-blast-radius system: drive phishing-resistant MFA, gate access on device/risk posture, scope admin tightly with vaulted break-glass and hold a reasoned Okta-vs-Entra view.
Self-check
QWhy are FIDO2/passkeys considered phishing-resistant when TOTP and SMS are not?