The Ops Atlas xOps School

Security & Compliance Emerging practice Sources verified

IdentityOps

IdentityOps is the day-to-day operation of workforce and machine identities: HR-driven joiner–mover–leaver, directories and identity providers, SSO, SCIM provisioning, phishing-resistant MFA and recovery, and the lifecycle of non-human identities.

Key takeaways

  • IdentityOps is an emerging label with vendor-specific scopes. The practice beneath it (identity lifecycle, SSO, SCIM, MFA, IGA) is established under its own names and standards.
  • This page owns who exists and how they prove it. What they may do belongs to IAMOps, and how access is requested, elevated and reviewed belongs to AccessOps: an editorial split, not an industry boundary.
  • Every identity needs an authoritative source: HR for people, an owner register for machines. An account that traces to neither is an orphan to remove.
  • Disabling an account in the identity provider does not end sessions already issued to applications. Pair deprovisioning with session and token revocation, and measure time to deprovision everywhere.
  • Recovery is part of authentication. Help-desk password and MFA resets were a documented entry point in the Scattered Spider campaigns.
  • Non-human identities fail quietly: Cloudflare's 2023 intrusion used a token and three service accounts it wrongly believed were unused.

IdentityOps (identity operations) keeps an organisation’s digital identities accurate and their authentication strong. It creates, changes and removes accounts as people join, move and leave, driven by the HR record; connects applications through single sign-on (SSO) and automated provisioning; enrols and recovers multi-factor authentication (MFA); and tracks machine identities (service accounts, API keys, OAuth applications) that have no HR record at all.

In one line: every identity that can sign in belongs to someone or something that still needs it, and proves itself with a method that is hard to phish and hard to talk a help desk into resetting.

For IAM engineers, IT administrators, identity architects and security leaders. Facts checked 2026-10-17.

Item Summary
Term status Emerging. A label in vendor glossaries and team names, with differing scopes. The field beneath it, identity and access management (IAM), is established, with a professional body of knowledge[5] and stable standards.
Goals No account outlives its need; joiners productive on day one; leavers out everywhere within the SLA; phishing-resistant sign-in and recovery; every machine identity owned.
In scope Joiner–mover–leaver (JML) from HR, directories and identity providers (IdPs), SSO (SAML, OIDC), SCIM provisioning, MFA enrolment and recovery, the IGA platform and birthright access, non-human identities (NHIs), identity threat signals.
Out of scope Permission design, access requests and reviews, the HR process, detection: see what it is not and its neighbours.
Prerequisites None; basic web authentication (passwords, cookies, tokens) helps.
Key outputs Lifecycle policy and SLAs, an application register, reconciliation reports, MFA and recovery standards, an NHI register, audit evidence.

MITRE ATT&CK lists valid accounts as a route to initial access and persistence, noting that adversaries “may abuse inactive accounts: for example, those belonging to individuals who are no longer part of an organization”.[6] Every incident in the use cases is an identity that should not have existed, or should not have been usable.

Operating reality Without IdentityOps With IdentityOps
A leaver IT learns days later; some SaaS accounts stay active The HR termination triggers disablement, deprovisioning and session revocation within an SLA
A new SaaS app Local accounts with their own passwords SSO plus SCIM, or a documented exception
A lost phone A help desk resets MFA after a friendly call Recovery by a defined method, with notification
A service account Shared password, no owner, no expiry Registered owner, short-lived or rotated credential, end date
  • Not authorisation design. Roles, policies and least privilege are IAMOps. IdentityOps assigns birthright access (the access a role gets automatically) but does not design the permissions behind it.
  • Not privileged access. Requests, just-in-time elevation, vaults and review campaigns are AccessOps, run on the IGA platform this page operates.
  • Not HR. PeopleOps decides that someone joins, moves or leaves and owns the data; IdentityOps changes accounts.
  • Not a product. An IdP or IGA suite is a tool; a stale HR feed defeats either.
  • Not customer identity first. Customer identity (CIAM) shares the protocols but not the lifecycle; this page is workforce-first.

Where IdentityOps comes from and where it sits

Link to section “Where IdentityOps comes from and where it sits”

No founding document exists. The label is recent; the standards it operates are not: SAML 2.0 (OASIS, March 2005)[7] and SCIM 2.0 (2015)[8][9] for sign-in and provisioning; CISA’s call for phishing-resistant MFA as “the gold standard” (2022);[10] NIST SP 800-63-4 (July 2025);[11] the OpenID shared-signals specifications (approved as Final Specifications in September 2025);[12] and NIST IR 8587 on token protection (September 2026).[13]

Term Meaning on this page
Authoritative source The system that decides an identity should exist: HR for employees, a sponsor record for contractors and guests, an owner register for machines.
Directory / IdP The directory stores accounts and groups (Active Directory, LDAP); the identity provider authenticates users for applications. Microsoft Entra ID plays both roles.
SSO (SAML, OIDC) The IdP vouches for the user with a SAML assertion or an OpenID Connect ID token, whose sub is “never reassigned” within an issuer.[14]
Provisioning (SCIM, JIT) Creating, updating and deactivating accounts in applications. SCIM uses an API; just-in-time (JIT) creates an account at first SSO login and has no channel for removal.
Orphan / dormant account Orphan: no authoritative source or owner. Dormant: unused for longer than policy allows.
Phishing-resistant authenticator One that cannot be relayed through a fake site: FIDO2/WebAuthn and PKI smart cards. Codes typed by hand (OTP, SMS) are not.[15]
AAL1–AAL3 NIST’s authentication assurance levels: at least one factor; two factors; two factors with a phishing-resistant, non-exportable key.[15]
Account recovery Regaining access after losing authenticators; NIST sets the allowed methods per AAL.[15]
NHI A non-human identity: service account, API key, OAuth client, certificate, workload identity.
IGA Identity governance and administration: the platform that holds lifecycle and birthright rules and produces evidence.
Tier-0 A system whose compromise gives control of everything that trusts it: the IdP, its signing keys, the directory-sync server. A term from Microsoft’s administrative tier model.[16]
Shared signals OpenID event standards: SSF is the framework, CAEP carries session and credential changes, RISC account events such as credential-compromise.[17][18]

The mental model: three ledgers that must agree. The HR ledger says who should exist. The directory says who can authenticate. The application ledger (local accounts plus live sessions and tokens) says who is actually in. Incidents live in the gaps: a terminated worker still enabled, a disabled user with a live session, a SaaS account the IdP never knew about.

Page IdentityOps focus Their focus
IAMOps Identities, groups as lifecycle containers, NHI inventory Permission design and evaluation, policy as code
AccessOps Running the IGA platform, birthright rules Requests, elevation, PAM, break-glass, reviews
PeopleOps Account changes, reconciliation The HR event, its data and dates
CloudSecOps Federation into clouds, IAM users and keys Cloud posture and guardrails
EndpointOps Device signals in sign-in Managing devices
DetectionOps, SOC Ops Identity signals and containment actions Detections, triage
ComplianceOps Producing lifecycle evidence Mapping it to frameworks
Figure 1. The identity trio and its neighbours
join, move, leaveidentities, groupsruns the IGA platformsign-in signalslifecycle evidencePeopleOps: HR eventsIdentityOps: who exists, howthey prove itIAMOps:what they may doAccessOps:request, elevate, reviewDetectionOps, SOC Ops:identity alertsComplianceOps:evidence
Diagram source (Mermaid)
flowchart TB
  PEO["PeopleOps: HR events"] -->|"join, move, leave"| IDO
  IDO["IdentityOps: who exists, how they prove it"]
  IDO -->|"identities, groups"| IAM["IAMOps:<br/>what they may do"]
  IDO -->|"runs the IGA platform"| ACC["AccessOps:<br/>request, elevate, review"]
  IDO -->|"sign-in signals"| SIG["DetectionOps, SOC Ops:<br/>identity alerts"]
  IDO -.->|"lifecycle evidence"| CMP["ComplianceOps:<br/>evidence"]
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
  class IDO core
  class PEO,IAM,ACC,SIG,CMP neutral

Text equivalent: PeopleOps sends join, move and leave events into IdentityOps, which owns who exists and how they prove it. IdentityOps hands identities and groups to IAMOps (what identities may do), runs the IGA platform that AccessOps uses for requests, elevation and reviews, and sends sign-in signals to DetectionOps and SOC Ops (identity alerts). ComplianceOps draws lifecycle evidence from IdentityOps (dotted edge).

The split can be mapped onto NIST CSF 2.0’s PR.AA subcategories, an editorial mapping (the CSF assigns no teams): PR.AA-01 to -04 (identities, credentials, proofing, authentication, assertions) to IdentityOps; PR.AA-05 (permissions, least privilege and their review) to IAMOps for design and AccessOps for reviews.[19]

This charter is this Atlas’s proposal; no official IdentityOps manifesto exists.

Mission: every identity that can authenticate is known, owned, needed and strongly verified, and the evidence shows it.

  1. Every identity has an authoritative source. NIST SP 800-53 asks organisations to “Align account management processes with personnel termination and transfer processes”.[20]
  2. Events, not tickets, change accounts. A termination entered once in HR drives every downstream change.
  3. Deprovisioning ends when sessions end.
  4. Phishing-resistant by default; recovery no weaker than sign-in. A security key reset by phone is as strong as the phone call.
  5. Machines get a lifecycle too: owner, purpose, expiry, rotation, decommissioning.
  6. The IdP is tier-0 production: configuration, federation trusts and signing keys under change control.
  7. Measure the gaps between the three ledgers, not tickets closed.

Non-goals: designing permissions (IAMOps) and approving elevated access (AccessOps).

Block Job Failure if missing
Authoritative sources Decide who should exist Orphans; missed leavers
Directory Store accounts, groups, attributes Duplicates; no stable identifier
Identity provider Authenticate; issue assertions and tokens Passwords per app
Lifecycle engine / IGA Turn HR events into account changes Manual tickets; drift
Provisioning connectors Create, update, deactivate in apps (SCIM 2.0, vendor APIs) Accounts survive leavers
Authenticators and recovery Prove control; restore it safely Phishing; help-desk takeover
Signals Detect misuse; share session changes Late detection

Examples of each are in the tooling landscape.

R = responsible, A = accountable, C = consulted, I = informed.

Activity HR / PeopleOps Identity team Application owner Service desk SOC
Record join, move, leave with effective date A/R I — — —
Lifecycle rules and birthright policy C A/R C I —
Connect an app (SSO, SCIM) — R A I —
Leaver deprovisioning within SLA C A/R R (non-SCIM apps) I I
MFA enrolment and recovery standard — A/R — R (executes) C
NHI registration and rotation — A R (each owner) — I
Identity alert containment — R I — A
Lifecycle evidence for audit C A/R C — —

Managers and sponsors confirm contractor and guest need.

Figure 2. Identity lifecycle states for a worker
HR record createdstart date, after proofingoffer withdrawn or no-showmover recalculates birthrightleave of absencereturnleaver effective dateleaver effective daterehire under policyretention period endsPrehireActiveDeletedSuspendedDisabled
Diagram source (Mermaid)
stateDiagram-v2
  direction TB
  [*] --> Prehire: HR record created
  Prehire --> Active: start date, after proofing
  Prehire --> Deleted: offer withdrawn or no-show
  Active --> Active: mover recalculates birthright
  Active --> Suspended: leave of absence
  Suspended --> Active: return
  Active --> Disabled: leaver effective date
  Suspended --> Disabled: leaver effective date
  Disabled --> Active: rehire under policy
  Disabled --> Deleted: retention period ends
  Deleted --> [*]

Text equivalent: an identity starts in Prehire when HR creates the record and becomes Active on the start date, once the person is proofed; if the offer is withdrawn or the person never starts, it is deleted, not left as an orphan. A move keeps it Active but recalculates birthright access. Leave moves it to Suspended and back. On the leaver effective date it becomes Disabled. A rehire can reactivate it under policy; otherwise it is Deleted when the retention period ends.

  • Prehire. Create the identity disabled so day-one access is ready. Microsoft’s HR provisioning matches records by employee ID by default and asks how rehires and termination dates are handled.[21]
  • Proof before bootstrap. A bootstrap credential is only as good as the check on who receives it. HR or the hiring manager matches the person to identity documents before day one. For remote hires, Microsoft, writing on North Korean IT workers using stolen or “rented” identities, advises several on-camera sessions, asking people to “physically hold driver’s licenses, passports, or identity documents up to camera”, and notarised proof of identity.[22] Hand the pass only to the proofed person, in person or on live video. NIST SP 800-63A defines identity assurance levels (IAL1–IAL3) if you need a formal standard.[23]
  • Joiner. Enable on the start date, assign birthright groups, and enrol phishing-resistant MFA with a bootstrap credential such as Entra’s Temporary Access Pass, “a time-limited passcode”.[24]
  • Mover. Recalculate birthright and remove what the old role granted; movers are where access accumulates (Lab 1 checks it).
  • Leaver. Disable, deprovision downstream, revoke sessions and tokens, delete after retention (the leaver workflow gives the product behaviour).
  • Rehire. Reactivate with no previous access, or create a new identity, by written policy.

Cadence: HR events, provisioning and alert routing run continuously; reconciliation and provisioning errors daily, with an owner per exception; a sample of assisted recoveries and new-app intake weekly; metrics and the NHI expiry report monthly; the leaver drill and an IdP configuration and federation-trust review quarterly.

SLAs are yours to set: NIST AC-2 leaves notification and disabling periods to the organisation.[20] Review IdP changes (new trust, admin or authentication policy) like production changes; attackers have added rogue federation trusts (Case 4).

Figure 3. Reference architecture: from HR record to application session
SSO, SCIM,CAEP eventssign-in logs,riskHR system: authoritative forpeopleLifecycle engine / IGA: rules,birthrightNHI owner registerDirectory and IdPSaaS and internal appsSOC and detectionReconciliationHR and NHI register vsdirectory export vs appexports
Diagram source (Mermaid)
flowchart TB
  HR["HR system: authoritative for people"] --> LC
  REG["NHI owner register"] --> LC
  LC["Lifecycle engine / IGA: rules, birthright"] --> DIR
  DIR["Directory and IdP"] -->|"SSO, SCIM,<br/>CAEP events"| APPS
  APPS["SaaS and internal apps"]
  DIR -->|"sign-in logs,<br/>risk"| SOC["SOC and detection"]
  APPS --> REC["Reconciliation<br/>HR and NHI register vs<br/>directory export vs app exports"]
  DIR --> REC
  HR --> REC
  REG --> REC
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
  class LC,DIR,REC core
  class HR,REG,APPS,SOC neutral

Text equivalent: the HR system and the NHI owner register feed a lifecycle engine or IGA platform, which writes to the directory and IdP. The IdP signs users in to applications with SAML or OIDC, provisions them with SCIM, sends session events with CAEP, and sends sign-in logs and risk to the SOC. Reconciliation compares all three ledgers: HR and the NHI register (who should exist), the directory’s account export (who can authenticate) and application account exports (who is actually in).

Component Trust boundary notes
HR system A write to HR can create an account: protect HR admin roles
Lifecycle engine / IGA Connector credentials are high-value NHIs
Directory and IdP Tier-0: admin roles, trusts and signing keys; see NIST IR 8587 on key management and token verification[13]
Provisioning connectors One scoped, rotated token per app
Reconciliation Reads each ledger directly, not the provisioning log

Alternatives. Cloud-first: lifecycle in the IdP’s own features (licence-dependent[25]). Hybrid: HR provisions into Active Directory, which synchronises to the cloud;[21] the sync server “must be treated as a Tier 0 component”,[16] and Windows services should prefer group managed service accounts, whose passwords Windows manages.[26] IGA suite: for many sources and complex rules, at the cost of another tier-0 system.

Figure 4. Leaver sequence from HR termination to evidence
EvidenceSCIM appIdPLifecycleHREntra: next cycle6. timestamps recorded as evidencetermination 17:001disable account2revoke sessions3active=false4200 or 2045
Diagram source (Mermaid)
sequenceDiagram
  autonumber
  participant HR as HR
  participant LC as Lifecycle
  participant IDP as IdP
  participant APP as SCIM app
  participant EV as Evidence
  HR->>LC: termination 17:00
  LC->>IDP: disable account
  LC->>IDP: revoke sessions
  IDP->>APP: active=false
  Note over IDP,APP: Entra: next cycle
  APP-->>IDP: 200 or 204
  Note over LC,EV: 6. timestamps recorded as evidence

Text equivalent: HR sends a termination with an effective time to the lifecycle engine, which disables the IdP account and revokes sessions and refresh tokens. The IdP sends each SCIM app a PATCH setting active to false (Okta on deactivation, Entra in its next provisioning cycle); the app replies 200 or 204. Finally the engine records each system’s timestamp as evidence (shown as a note across the lifelines).

Happy path, and what it depends on. Both IdPs deprovision SCIM apps by setting active to false, but only if configured to: Okta needs “Deactivate Users” enabled for the app;[27] Entra needs the update action and the active mapping.[28] Okta sends the request when the user is deactivated; Entra’s cycles run “approximately every 40 minutes” (as of October 2026).[29]

Urgent leavers in Entra. On-demand provisioning can disable a user unassigned from an app, not one already disabled in Entra; a push “typically takes less than 30 seconds”.[30] In this page’s reading, that means: unassign the person from each critical app, push it, then disable the account. This reverses the disable-first order above and in Microsoft’s emergency steps[31] and leaves the account enabled until the last push, so use it only when removal inside the apps matters more than those minutes. It needs the app scoped to “Sync only assigned users and groups”,[28] and apps that authorise with OAuth (Microsoft names G Suite, Box and Slack) need their provisioning job stopped first.[30] An unassigned user leaves the job’s management, so a later soft-deletion sends no delete.[28] Otherwise disable first and deactivate critical apps directly (the Tier B path).

When deactivation means deletion. Okta never sends a delete,[27] but Entra sends a DELETE to apps without soft-delete support and, unless the Delete target action is cleared, when the source user is permanently deleted (automatically 30 days after soft deletion, or earlier by hand).[28] RFC 7643 leaves the meaning of active to each application.[8]

Exception paths (each needs an owner and an SLA):

  • Sessions outlive the account. Entra access tokens last about 60–90 minutes by default (Microsoft’s pages say “1 hour” and “60-90 minutes”), and up to 28 hours where CAE applies (as of October 2026);[31][32] “the user loses access when the access token expires”.[31] revokeSignInSessions invalidates refresh tokens and session cookies after “a small delay of a few minutes”.[33] Okta’s session revocation “doesn’t clear the sessions created for web or native apps”.[34] Apps with their own sessions need their own revocation or short lifetimes.
  • Provisioning is broken. An Entra job whose calls keep failing enters quarantine, where its cycles slow to once a day, and is disabled after more than four weeks in quarantine;[28] leavers silently stay active in that app.
  • Legal hold. Disable sign-in now; delay deletion; check each app’s deprovisioning behaviour first. In Entra, clear the Delete target action; for apps without soft delete, where even a disable becomes a DELETE, preserve the data before disabling or handle that app by hand (Tier B or C).[28] In Okta, deactivating the user is “a destructive operation” that deprovisions all assigned apps; suspension keeps assignments.[34]
Practice Goal Trigger Owner Verification
HR-driven provisioning Accounts follow HR HR event Identity team Daily reconciliation
App connection standard SSO and SCIM everywhere New app App owner Register coverage
Mover recalculation No access accumulation Attribute change Lifecycle engine Group difference report
Leaver drill Prove deprovisioning Quarterly Identity team Per-app timestamps within SLA
Dormant sweep Disable unused accounts, guests included; excluded: HR-suspended identities, emergency accounts,[35] NHIs with a registered longer cadence (owner confirms first) Daily Identity team Window of 90–180 days, as Microsoft suggests;[36] exclusion list reviewed quarterly
Phishing-resistant rollout Remove phishable sign-in Programme Identity team Coverage and usage metrics
Verified recovery No reset on a caller’s word Every reset Service desk Weekly sample review
NHI registration and rotation Machine identities owned and current New credential; monthly Each owner Register vs inventory
IdP change control Catch rogue admins and trusts IdP change Identity team Unapproved-change alert

Phishing resistance. NIST SP 800-63B-4 requires verifiers to “offer at least one phishing-resistant authentication option at AAL2” and requires phishing resistance for US federal staff.[15] CISA calls FIDO/WebAuthn “The only widely available phishing-resistant authentication”; PKI smart cards also qualify.[10] Roll out in risk order: IdP and cloud administrators, then email, remote access and finance, then everyone. Synced passkeys suit most staff, but their keys are exportable, so NIST excludes them from AAL3:[15] give administrators device-bound security keys. Where push MFA remains, limit prompts[15] and use number matching as an interim step.[10]

Passwords, while they last: at least 15 characters (8 when used only with a second factor), no composition rules, no periodic changes, a forced change on evidence of compromise, and a blocklist of common and breached passwords.[15]

Recovery. NIST recognises saved recovery codes, issued recovery codes, recovery contacts and repeated identity proofing; any other method, such as a help-desk agent, must be “based on a risk analysis and documented”. At AAL2, recovery needs two codes obtained by different methods, a code plus a still-bound authenticator, or repeated proofing, and every recovery or new authenticator triggers a notification.[15] CISA’s advisory shows the attack: Scattered Spider posed as employees “to convince IT and/or helpdesk staff to provide sensitive information, reset the employee’s password, and transfer the employee’s MFA to a device they control”.[37] A defensible design:

  1. Self-service first, through a second registered authenticator (NIST encourages “at least two separate means of authentication”[15]).
  2. Assisted recovery issues a one-time bootstrap credential[24] only after the manager (or sponsor) confirms the person on a live video call or in person, and delivers it through that manager or to an already-registered device, never read out to the caller. A call-back to the HR phone number is weak evidence on its own: Scattered Spider conducted “SIM swaps” before calling help desks,[37] and NIST asks verifiers to consider “SIM change, number porting” before using the phone network to deliver an out-of-band secret[15] (a rule written for authentication; this page applies it by analogy to call-back verification).
  3. Privileged and high-risk accounts recover only through repeated proofing (in person or supervised video against an identity document) and a second administrator’s approval.
  4. Watch the seam: alert when a new MFA method follows a reset within hours, and when a federation trust or IdP admin is added.

Machine identities have no HR record, so nothing signals their end. OWASP’s Non-Human Identities Top 10 (2025) starts with “Improper Offboarding”, “the inadequate deactivation or removal of non-human identities (NHIs) such as service accounts and access keys when they are no longer needed”, and includes long-lived secrets, NHI reuse and human use of NHIs.[38]

  1. Inventory per system: IdP app registrations and service principals, cloud IAM users and keys, CI/CD secrets, SaaS API tokens. AWS’s credential report covers IAM users’ passwords, keys and MFA, but only the first two access keys and no service-specific credentials.[39] It lists users only: IAM roles need their own inventory and last-used data,[40] designed with IAMOps.
  2. Register owner, purpose, environment, expiry and expected cadence: a quarter-end job is not dormant at 90 days, so the dormant sweep and Lab 3’s idle rule must read the registered cadence. No owner, no credential.
  3. Prefer short-lived credentials: AWS advises requiring “workloads to use temporary credentials with IAM roles”;[41] designing that federation belongs to IAMOps.
  4. Rotate what must stay long-lived, and record it.
  5. Decommission with evidence: check last use, disable, wait a business cycle, delete (Case 2 shows the cost of guessing).
Source Kind Use in IdentityOps
NIST SP 800-63-4[11] US federal guideline Assurance levels; authentication and recovery design
NIST SP 800-53 AC-2[20] Control catalogue Account management SLAs and evidence
NIST CSF 2.0 PR.AA[19] Voluntary framework Mapping controls across the identity trio
CISA ZTMM v2.0[42] Maturity model (US federal) Calibrating the maturity model
SAML 2.0, OIDC Core, RFC 9700[7][14][43] Protocol standards Federation and OAuth configuration baselines
SCIM 2.0[9] Protocol standard Provisioning requirement for apps
SSF, CAEP, RISC[12] Protocol standards (final 2025) Session and risk events across vendors
OWASP NHI Top 10[38] Community risk list NHI review checklist
MITRE ATT&CK[6] Adversary knowledge base Detection coverage with the SOC

RFC 9700 doubles as an IdP configuration test: the implicit grant “SHOULD NOT” be used and the resource owner password credentials grant “MUST NOT be used”.[43] Most of these documents are US-originated; check your jurisdiction before treating any as a legal requirement.

Categories first; named products are examples verified in documentation (as of October 2026), not endorsements.

Category Verified examples Selection criteria
HR source Workday, SAP SuccessFactors[21] Effective dates, worker types, API
Directory and IdP Microsoft Entra ID, Okta, Active Directory SCIM, phishing-resistant methods, revocation API, logs
Lifecycle and IGA Entra lifecycle workflows;[25] dedicated IGA suites Connectors, testable rules, audit reports
Authenticators FIDO2 security keys, passkeys, PIV cards Exportability, recovery, device support
Identity threat signals Entra ID Protection;[44] tools sold as identity threat detection and response (ITDR)[45] Coverage beyond one IdP; judge ITDR by what it adds to the IdP’s own detections
NHI inventory AWS IAM credential report;[39] IdP app registrations Last-used data; credential types covered

Lock-in. Every application trusts the IdP’s signing keys, which makes it the hardest system to replace; standard connections (SAML or OIDC plus SCIM) keep an exit possible.

Automate the routine lifecycle; keep human approval for contractors without HR records, rehires, privileged identities and bulk changes (a mass termination can be an HR error). Machine learning already sits inside IdP risk detections. A language model may summarise a sign-in investigation; it must never be the verifier in a recovery flow. AI agents are NHIs (going further).

An illustrative design for a 2,000-person company with a cloud HR system, one cloud IdP and about 150 SaaS applications. The policy below is the single place where lifecycle rules live; the schema is this Atlas’s illustration, not a product format.

Example status: YAML syntax-checked by the Atlas validator; not loaded into any product.

# identity-lifecycle-policy.yaml
version: 3
sources:
  employees: {system: hr, match_on: employee_id}
  contractors: {system: sponsor-register, max_days: 180, sponsor_required: true}
  machines: {system: nhi-register, owner_required: true, max_credential_days: 90}
birthright:
  all: [all-staff, email]
  department:
    finance: [finance, erp]
    sales: [sales, crm]
    engineering: [engineering, git]
slas:
  joiner_ready_hours_before_start: 24
  leaver_disable_idp_hours: 4
  leaver_deprovision_all_apps_hours: 24
  dormant_disable_days: 90
  dormant_exclusions: [hr_suspended, emergency_access, nhi_with_registered_cadence]
leaver_actions:
  - disable_idp_account
  - revoke_sessions_and_refresh_tokens
  - scim_deactivate_connected_apps
  - open_tickets_for_non_scim_apps
  - remove_authenticators
retention:
  delete_after_days: 30
  unless: legal_hold
rehire:
  restore_previous_access: false
recovery:
  self_service: {any_of: [second_authenticator]}
  standard:
    require_all: [manager_confirms_on_live_video_or_in_person, one_time_pass]
    pass_delivery: [via_manager, to_registered_device]   # never read out on the call
  privileged:
    require_all: [in_person_or_supervised_video_proofing, second_admin_approval]
  notify_user_on: [recovery, new_authenticator]

Every application gets a connection tier in a register, chosen with the decision framework:

Tier Connection Leaver handling Review
A SSO (SAML or OIDC) plus SCIM Automatic active=false Monthly provisioning error report
B SSO plus a vendor API script Scripted, logged Monthly script run evidence
C SSO with JIT only Daily account export reconciled; manual removal within SLA Weekly
D No SSO (local passwords) Ticket to the app owner Exception expires; quarterly attestation

Labs 1 and 3 run anywhere with Python 3 and were executed for this page. Lab 2 needs a test tenant and was not executed.

Lab 1 (beginner): reconcile the three ledgers

Link to section “Lab 1 (beginner): reconcile the three ledgers”

Objective: find leavers, orphans, duplicate accounts, movers with leftover access, missing joiners, dormant accounts and weak MFA from an HR roster and an IdP export. Prerequisites: Python 3.8 or later; no account, cost or risk; 30 minutes.

  1. Save the data as jml.json and the script as jml_reconcile.py.
  2. Run python3 jml_reconcile.py jml.json, then echo $?.
  3. Fix the findings in jml.json: set enabled to false for cara, dev (on long leave, confirmed by the manager) and test-admin; remove finance and erp from ben’s groups and set his mfa to phishing-resistant; add an account for E104 (eli@example.com, groups all-staff, email, finance, erp, phishing-resistant, last sign-in today). Run again.
  4. What-if: in the original file, change now to 2026-10-16T09:00:00Z and run again. Then restore it and add a second enabled account for E100 (copy ana’s record with "upn": "ana2@example.com") and run again.

Example status: verified by execution (Python 3.8.10, 2026-10-16; re-run 2026-10-17 after the duplicate check was added); output below is verbatim.

{
  "policy": {
    "now": "2026-10-16T12:00:00Z",
    "leaver_sla_hours": 4,
    "dormant_days": 90,
    "birthright": {
      "all": ["all-staff", "email"],
      "finance": ["finance", "erp"],
      "sales": ["sales", "crm"],
      "engineering": ["engineering", "git"]
    }
  },
  "hr": [
    {"id": "E100", "status": "active", "dept": "finance"},
    {"id": "E101", "status": "active", "dept": "sales"},
    {"id": "E102", "status": "terminated", "dept": "sales",
     "end": "2026-10-16T06:00:00Z"},
    {"id": "E103", "status": "active", "dept": "engineering"},
    {"id": "E104", "status": "active", "dept": "finance"}
  ],
  "idp": [
    {"upn": "ana@example.com", "emp": "E100", "enabled": true,
     "groups": ["all-staff", "email", "finance", "erp"],
     "mfa": "phishing-resistant", "last": "2026-10-15T09:00:00Z"},
    {"upn": "ben@example.com", "emp": "E101", "enabled": true,
     "groups": ["all-staff", "email", "sales", "crm", "finance", "erp"],
     "mfa": "otp", "last": "2026-10-16T08:00:00Z"},
    {"upn": "cara@example.com", "emp": "E102", "enabled": true,
     "groups": ["all-staff", "email", "sales", "crm"],
     "mfa": "phishing-resistant", "last": "2026-10-16T07:30:00Z"},
    {"upn": "dev@example.com", "emp": "E103", "enabled": true,
     "groups": ["all-staff", "email", "engineering", "git"],
     "mfa": "none", "last": "2026-06-01T10:00:00Z"},
    {"upn": "test-admin@example.com", "emp": null, "enabled": true,
     "groups": ["all-staff", "email"], "mfa": "none",
     "last": "2026-09-30T23:10:00Z"}
  ]
}
"""Reconcile an HR roster with identity-provider accounts (IdentityOps Lab 1)."""
import json
import sys
from datetime import datetime


def ts(value):
    return datetime.strptime(value, "%Y-%m-%dT%H:%M:%SZ")


def main(path):
    with open(path) as f:
        data = json.load(f)
    pol = data["policy"]
    now = ts(pol["now"])
    hr = {w["id"]: w for w in data["hr"]}
    accounts = {}  # employee id -> every account that claims it
    for a in data["idp"]:
        if a["emp"]:
            accounts.setdefault(a["emp"], []).append(a)
    findings = []

    for a in data["idp"]:
        if a["emp"] not in hr and a["enabled"]:
            findings.append("ORPHAN   %s has no HR record" % a["upn"])
    for emp, w in sorted(hr.items()):
        owned = accounts.get(emp, [])
        if w["status"] == "active" and not owned:
            findings.append("JOINER   %s active in HR, no account" % emp)
            continue
        enabled = [a for a in owned if a["enabled"]]
        if len(enabled) > 1:
            findings.append("DUPLICATE %s has %d enabled accounts (%s)"
                            % (emp, len(enabled), ", ".join(a["upn"] for a in enabled)))
        for a in owned:
            if w["status"] == "terminated" and a["enabled"]:
                hours = (now - ts(w["end"])).total_seconds() / 3600
                late = "BREACH" if hours > pol["leaver_sla_hours"] else "within SLA"
                findings.append("LEAVER   %s enabled %.1f h after end date (%s)"
                                % (a["upn"], hours, late))
            if w["status"] == "active":
                allowed = set(pol["birthright"]["all"] + pol["birthright"][w["dept"]])
                extra = sorted(set(a["groups"]) - allowed)
                if extra:
                    findings.append("MOVER    %s (%s) keeps %s"
                                    % (a["upn"], w["dept"], ", ".join(extra)))

    humans = [a for a in data["idp"] if a["emp"] in hr and a["enabled"]
              and hr[a["emp"]]["status"] == "active"]
    strong = [a for a in humans if a["mfa"] == "phishing-resistant"]
    for a in data["idp"]:
        idle = (now - ts(a["last"])).days
        if a["enabled"] and idle > pol["dormant_days"]:
            findings.append("DORMANT  %s last sign-in %d days ago" % (a["upn"], idle))
        if a["enabled"] and a["mfa"] != "phishing-resistant":
            findings.append("MFA      %s uses %s" % (a["upn"], a["mfa"]))

    for f in findings:
        print(f)
    print("Phishing-resistant coverage (active staff): %d/%d (%.1f%%)"
          % (len(strong), len(humans), 100.0 * len(strong) / len(humans)))
    print("Findings: %d" % len(findings))
    return 1 if findings else 0


if __name__ == "__main__":
    sys.exit(main(sys.argv[1]))

Expected output (step 2), exit code 1:

ORPHAN   test-admin@example.com has no HR record
MOVER    ben@example.com (sales) keeps erp, finance
LEAVER   cara@example.com enabled 6.0 h after end date (BREACH)
JOINER   E104 active in HR, no account
MFA      ben@example.com uses otp
DORMANT  dev@example.com last sign-in 137 days ago
MFA      dev@example.com uses none
MFA      test-admin@example.com uses none
Phishing-resistant coverage (active staff): 1/3 (33.3%)
Findings: 8

Validation. Step 3 prints Phishing-resistant coverage (active staff): 3/3 (100.0%) and Findings: 0, exit code 0. Step 4 first prints LEAVER cara@example.com enabled 3.0 h after end date (within SLA): the same gap passes or fails on time alone, so leaver SLAs need timestamps, not daily flags. The duplicate run adds DUPLICATE E100 has 2 enabled accounts (ana@example.com, ana2@example.com) (Findings: 9): two live accounts for one person, the rehire failure in the troubleshooting table. Troubleshooting: KeyError: 'dept' means an HR record lacks a department; a strptime ValueError means a timestamp without the trailing Z. Teardown: delete the files. Next: run it on real exports, handled under your data rules.

Lab 2 (intermediate): deactivate a SCIM account and revoke sessions

Link to section “Lab 2 (intermediate): deactivate a SCIM account and revoke sessions”

Objective: run a leaver by hand against a test application and IdP tenant, as automation would. Prerequisites: a SCIM 2.0 test endpoint and token; for Okta an OAuth token with the okta.users.manage scope (Okta recommends scoped OAuth tokens over API tokens[34]); for Entra a token with User.RevokeSessions.All;[33] curl 7.76 or later for --fail-with-body.[46] Risk: never run it against production users.

Example status: JSON and bash syntax-checked; not executed (needs a SCIM test app and an IdP test tenant). Request shapes from RFC 7644, Okta and Microsoft Graph documentation.[9][27][34][33]

deactivate.json, the body Okta sends to deactivate a user:[27]

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [{"op": "replace", "value": {"active": false}}]
}
#!/usr/bin/env bash
# Leaver drill against TEST systems only.
set -euo pipefail
SCIM="https://scim.example.com/scim/v2"          # placeholder SCIM base URL
: "${SCIM_TOKEN:?set a test SCIM bearer token}"
: "${OKTA_USER_ID:?set the Okta user id}" "${OKTA_ACCESS_TOKEN:?set an Okta OAuth token}"
: "${ENTRA_USER_ID:?set the Entra object id or UPN}" "${GRAPH_TOKEN:?set a Graph token}"
LEAVER="test.leaver@example.com"                 # SCIM userName in the test app
CURL=(curl -sS --fail-with-body)                 # stop on HTTP 4xx/5xx

# 1. Find the user (RFC 7644 filter; Okta sends the same query)
"${CURL[@]}" -G "$SCIM/Users" -H "Authorization: Bearer $SCIM_TOKEN" \
  -H "Accept: application/scim+json" \
  --data-urlencode "filter=userName eq \"$LEAVER\"" > lookup.json
PICK='import json; print(json.load(open("lookup.json"))["Resources"][0]["id"])'
ID=$(python3 -c "$PICK")

# 2. Deactivate (soft delete): PATCH active=false
"${CURL[@]}" -X PATCH "$SCIM/Users/$ID" -H "Authorization: Bearer $SCIM_TOKEN" \
  -H "Content-Type: application/scim+json" --data @deactivate.json

# 3a. Okta: end IdP sessions and revoke OAuth tokens (oauthTokens defaults to false).
#     Also clears remembered-device MFA state: forgetDevices defaults to true on
#     Identity Engine and false on Classic Engine; pass it explicitly to be sure.
OKTA="https://example.okta.com"                  # placeholder org URL
"${CURL[@]}" -X DELETE \
  "$OKTA/api/v1/users/$OKTA_USER_ID/sessions?oauthTokens=true&forgetDevices=true" \
  -H "Authorization: Bearer $OKTA_ACCESS_TOKEN"

# 3b. Entra: invalidate refresh tokens and session cookies
GRAPH="https://graph.microsoft.com/v1.0"
"${CURL[@]}" -X POST "$GRAPH/users/$ENTRA_USER_ID/revokeSignInSessions" \
  -H "Authorization: Bearer $GRAPH_TOKEN" -H "Content-Type: application/json" -d ''

Expected output: step 1 returns a ListResponse with one resource; step 2 HTTP 200 with the user showing "active": false, or 204 with no body;[9] step 3a HTTP 204 with no body, and the user’s remembered devices are forgotten as a side effect;[34] step 3b a 2xx response.[33] Any 4xx or 5xx stops the script and prints the error body. Validation: the user cannot sign in to the test app and an old refresh token fails; issued access tokens stay valid until they expire.[31] Troubleshooting: an empty Resources array means the app matches on another attribute; HTTP 403 means a missing scope or role. Teardown: reactivate with "active": true or delete the test user.

Lab 3 (advanced): audit machine identities from a credential report

Link to section “Lab 3 (advanced): audit machine identities from a credential report”

Objective: find unowned, unused, idle and unrotated access keys and human IAM users, using the real credential-report columns.[39] Prerequisites: Python 3.8 or later; 45 minutes; step 5 needs IAM read access to a non-production account.

  1. Save make_report.py, nhi_audit.py and the owner register owners.json.
  2. Run python3 make_report.py > credential_report.csv to create the synthetic report.
  3. Run python3 nhi_audit.py credential_report.csv owners.json.
  4. Remediate in the data: delete the report-export, jane.admin and old-etl rows from USERS (after their owners confirm), and change legacy-backup to a new key created and used on 2026-10-16. Run steps 2 and 3 again.
  5. Optional, real account (not executed here): aws iam generate-credential-report, then aws iam get-credential-report --query Content --output text | base64 --decode > credential_report.csv. The Content field is Base64-encoded;[47] reports can be generated at most once every four hours.[39] A real report also has a row for the account root user, which the script flags NO-OWNER: check it separately for MFA and no access keys.[48]

Example status: steps 1–4 verified by execution (Python 3.8.10, 2026-10-16, re-run 2026-10-17), output verbatim; step 5 not executed.

"""Write a synthetic AWS IAM credential report (real column names, fake users)."""
import csv
import sys

COLUMNS = [
    "user", "arn", "user_creation_time", "password_enabled", "password_last_used",
    "password_last_changed", "password_next_rotation", "mfa_active",
    "access_key_1_active", "access_key_1_last_rotated", "access_key_1_last_used_date",
    "access_key_1_last_used_region", "access_key_1_last_used_service",
    "access_key_2_active", "access_key_2_last_rotated", "access_key_2_last_used_date",
    "access_key_2_last_used_region", "access_key_2_last_used_service",
    "cert_1_active", "cert_1_last_rotated", "cert_2_active", "cert_2_last_rotated",
]
T = "T00:00:00+00:00"
USERS = [  # user, password, mfa, key 1 created, key 1 last used
    ("ci-deploy", "false", "false", "2026-09-01", "2026-10-15"),
    ("legacy-backup", "false", "false", "2024-03-10", "2026-10-14"),
    ("report-export", "false", "false", "2025-11-20", None),
    ("jane.admin", "true", "false", "2026-08-01", "2026-10-12"),
    ("old-etl", "false", "false", "2025-01-05", "2025-06-30"),
]

out = csv.DictWriter(sys.stdout, fieldnames=COLUMNS, lineterminator="\n")
out.writeheader()
for user, pwd, mfa, created, used in USERS:
    row = {c: "N/A" for c in COLUMNS}
    row.update({
        "user": user, "arn": "arn:aws:iam::111122223333:user/" + user,
        "user_creation_time": created + T, "password_enabled": pwd,
        "mfa_active": mfa, "access_key_1_active": "true",
        "access_key_1_last_rotated": created + T,
        "access_key_1_last_used_date": used + T if used else "N/A",
        "access_key_2_active": "false", "cert_1_active": "false",
        "cert_2_active": "false",
    })
    out.writerow(row)
{
  "as_of": "2026-10-16",
  "max_key_age_days": 90,
  "max_idle_days": 90,
  "owners": {
    "ci-deploy": "platform-team",
    "legacy-backup": "storage-team",
    "old-etl": "data-team"
  }
}
"""Audit IAM users and access keys from an AWS credential report (IdentityOps Lab 3)."""
import csv
import json
import sys
from datetime import datetime, timezone

EMPTY = ("N/A", "no_information", "not_supported", "")


def days_since(value, now):
    if value in EMPTY:
        return None
    return (now - datetime.fromisoformat(value)).days


def main(report_path, register_path):
    with open(register_path) as f:
        reg = json.load(f)
    now = datetime.strptime(reg["as_of"], "%Y-%m-%d").replace(tzinfo=timezone.utc)
    with open(report_path, newline="") as f:
        rows = list(csv.DictReader(f))
    findings, owned, ok, keys = [], 0, 0, 0
    for r in rows:
        user = r["user"]
        if user in reg["owners"]:
            owned += 1
        else:
            findings.append("NO-OWNER  %s: no owner registered" % user)
        if r["password_enabled"].lower() == "true":
            mfa = "on" if r["mfa_active"].lower() == "true" else "OFF"
            findings.append("HUMAN     %s: console password, MFA %s; federate"
                            % (user, mfa))
        for k in ("1", "2"):
            if r["access_key_%s_active" % k].lower() != "true":
                continue
            keys += 1
            age = days_since(r["access_key_%s_last_rotated" % k], now)
            idle = days_since(r["access_key_%s_last_used_date" % k], now)
            key = "%s key %s" % (user, k)
            if idle is None:
                findings.append("UNUSED    %s: never used, %d days old" % (key, age))
            elif idle > reg["max_idle_days"]:
                findings.append("IDLE      %s: last used %d days ago" % (key, idle))
            elif age > reg["max_key_age_days"]:
                findings.append("ROTATE    %s: %d days old, in use" % (key, age))
            else:
                ok += 1
    for line in findings:
        print(line)
    print("Owner coverage: %d/%d users" % (owned, len(rows)))
    print("Active keys within policy: %d/%d" % (ok, keys))
    print("Findings: %d" % len(findings))
    return 1 if findings else 0


if __name__ == "__main__":
    sys.exit(main(sys.argv[1], sys.argv[2]))

Expected output (step 3), exit code 1:

ROTATE    legacy-backup key 1: 950 days old, in use
NO-OWNER  report-export: no owner registered
UNUSED    report-export key 1: never used, 330 days old
NO-OWNER  jane.admin: no owner registered
HUMAN     jane.admin: console password, MFA OFF; federate
IDLE      old-etl key 1: last used 473 days ago
Owner coverage: 3/5 users
Active keys within policy: 2/5
Findings: 6

Validation. Step 4 prints Owner coverage: 2/2 users, Active keys within policy: 2/2 and Findings: 0. Lesson: jane.admin is a person on an IAM user; AWS wants humans to “use federation with an identity provider”,[41] so the fix is federation, not rotation. Troubleshooting: a fromisoformat ValueError means a Z suffix (Python 3.8 needs +00:00). Teardown: delete the files; treat a real report as sensitive data.

Four sourced incidents, each a different gap. Facts are the organisations’ or responders’ own accounts; lessons are this page’s.

Case 1: a legacy test tenant and an OAuth app (sourced)

Link to section “Case 1: a legacy test tenant and an OAuth app (sourced)”

From late November 2023, Midnight Blizzard “used a password spray attack to compromise a legacy non-production test tenant account”,[49] which “did not have multifactor authentication (MFA) enabled”. The actor then used “a legacy test OAuth application that had elevated access to the Microsoft corporate environment” and created more OAuth applications to reach mailboxes.[50] Gap: a test account outside MFA policy and a legacy test app that still had elevated access. Practice: inventory every tenant and app registration; MFA for every interactive account. Success measure: zero interactive accounts without MFA; zero privileged app registrations without an owner.

Case 2: a service account, session tokens and credentials nobody rotated (sourced)

Link to section “Case 2: a service account, session tokens and credentials nobody rotated (sourced)”

Okta found that from 28 September to 17 October 2023 an attacker used “a service account stored in the system itself”, whose credentials “had been saved into the employee’s personal Google account”; session tokens in support files let the attacker hijack five customers’ sessions.[51] Cloudflare, one of them, reported that “we failed to rotate one service token and three service accounts (out of thousands)” because “mistakenly it was believed they were unused”.[52] Gap: machine-identity use assumed, not measured. Practice: prove rotation item by item against the inventory, with last-used evidence; treat session tokens as credentials. Success measure: rotated ÷ exposed = 100%, checked by a second person.

Case 3: SaaS accounts signing in with passwords only (sourced)

Link to section “Case 3: SaaS accounts signing in with passwords only (sourced)”

Mandiant’s 2024 investigation of UNC5537, which targeted Snowflake customer instances, found accounts “not configured with multi-factor authentication”, infostealer-harvested credentials that “had not been rotated for as long as four years”, and no network allow lists; about 165 potentially exposed organisations were notified.[53] Gap (this page’s reading): app accounts protected by a password alone, outside any IdP’s MFA policy. Practice: tier every SaaS app (reference implementation); enforce SSO and MFA; reconcile local accounts. Success measure: critical apps at Tier A or B; local accounts without MFA = 0.

Case 4: the help desk as the bypass (sourced)

Link to section “Case 4: the help desk as the bypass (sourced)”

CISA’s Scattered Spider advisory (revised 29 July 2025) describes help-desk password and MFA resets, push bombing, SIM swapping, self-registered MFA tokens and, historically, a federated IdP added to the victim’s SSO tenant.[37] In May 2025 the UK NCSC asked organisations to “review helpdesk password reset processes”.[54] Gap: recovery weaker than authentication. Practice: tiered recovery and alerts on post-reset MFA and federation changes. Success measure: every sampled reset followed the script.

MojoAuth suggests “time to provision and deprovision, orphaned accounts found per review, and the rate of account-recovery requests”;[1] the set below makes them precise.

KPI Definition / formula Pitfall Review
Leaver compliance (end to end) Leavers disabled in the IdP and deactivated in every connected app within SLA ÷ leavers Measuring only the IdP Monthly
Time to disable and deprovision (p50, p95) IdP disable time, and last app deactivation time, − HR effective time Late HR entry looks like an identity delay (track HR lag apart); provisioning cycles add lag per app Monthly
Orphan rate Enabled accounts with no authoritative source or owner ÷ enabled accounts Disabled orphans counted as solved Weekly
Phishing-resistant coverage Active people with a phishing-resistant authenticator ÷ active people Counting “MFA enabled”, SMS included Monthly
Phishing-resistant usage Holders’ interactive sign-ins using such a method ÷ holders’ interactive sign-ins Mixing in non-holders hides weak fallbacks Monthly
Automated deprovisioning coverage User–app assignments on Tier A or B apps ÷ all user–app assignments (sum over apps of their user counts) A per-app count hides one large local-account app Quarterly
Joiner day-one readiness Joiners working with birthright access at start ÷ joiners Counting account creation only Monthly
Verified recovery rate Sampled assisted resets that followed the script ÷ sampled resets Sampling easy cases Weekly
NHI credential compliance Machine credentials owned and within age and idle limits ÷ machine credentials Inventory gaps flatter the ratio Monthly

Worked calculation (illustrative scenario). HR records 40 leavers in a month. The IdP disabled 36 within the 4-hour SLA; HR entered the other four two days late. Three of the 36 still had a Tier C account after 24 hours.

  • IdP-only compliance = 36 ÷ 40 = 90.0%; end to end = (36 − 3) ÷ 40 = 82.5%. The gap has two owners: HR entry lag (PeopleOps) and Tier C reconciliation (IdentityOps).
  • Of 1,400 staff, 1,190 have a FIDO2 key or passkey: coverage = 85.0%. Of those 1,190 holders’ 62,000 interactive sign-ins, 41,000 used one: usage = 66.1%. A third of holders’ sign-ins still use weaker methods, so policy still accepts them from people who own a strong one: require a phishing-resistant method by policy.

Targets: set from the baseline, then tighten. Coverage and Tier A share lead; leaver compliance and identity incidents lag.

Risk Signal Mitigation Owner
Password spray, credential stuffing Detections such as “Password spray” and “Leaked credentials”[44] Phishing-resistant MFA; blocklist; no local passwords Identity, SOC
MFA prompt bombing (T1621)[55] Many push prompts for one user Number matching, prompt limits, phishing-resistant methods Identity
Help-desk social engineering New MFA method soon after an assisted reset Tiered recovery; notification; alert Service desk, SOC
Token theft and replay Detections such as “Anomalous token”[44] Short sessions; revocation; signing-key protection[13] Identity
Rogue federation trust (T1484.002)[56] or authentication-policy change (T1556)[57] IdP change outside change control Few admins; change alerts; trust review Identity
Orphaned machine identity Credential with no owner or recent use Register, expiry, decommissioning Owners

Privacy. Identity records are personal data. Send applications only the attributes they need, restrict HR-sourced attributes, and set retention for disabled accounts and sign-in logs with PrivacyOps. Rules vary by jurisdiction; this page gives no legal advice.

Compliance. Auditors usually ask for leavers with a timestamp per system, reconciliation results and MFA coverage, against controls such as NIST AC-2.[20] Mapping evidence to ISO/IEC 27001, SOC 2 and other frameworks belongs to ComplianceOps.

  • Licence tiers drive design. Entra HR-driven provisioning needs P1 or P2 plus the HR application’s licence;[21] lifecycle workflows need Entra ID Governance or Entra Suite;[25] even the last-sign-in property for dormant checks needs P1 or P2,[36] and the inactive-guest report needs ID Governance or Entra Suite.[58] SaaS vendors often put SCIM in higher plans (Docker’s guide is marked Business).[59] Price the Tier A target, not just the IdP.
  • Labour. Tier C and D apps and assisted recoveries are recurring manual work. Measure both.
  • Hardware. Two security keys per administrator (one spare), plus replacement.
  • Resilience. Every sign-in depends on the IdP: see the FAQ on outages.
  • Sustainability is not material here beyond hardware lifecycle.
  • Independent reconciliation reads application data, not the provisioning log.
  • Control tests: the quarterly leaver drill (a test identity in Tier A–D apps); sign in with a disabled test account; replay an old refresh token; an authorised social-engineering test of the help-desk script.
  • Decay signals: provisioning errors or quarantined jobs, growth of Tier C and D, a spike in recovery requests, expired exceptions still open, and NHIs without owners.
Symptom Likely cause Diagnosis Remediation Prevention
Leaver still active in an app Tier C or D app; provisioning job failing or quarantined[28] Job status; app export Deactivate by hand; fix connector Alert on quarantine; daily reconciliation
Disabled user still reads mail or files Sessions and tokens issued before disablement Logs after the disable time Revoke sessions and refresh tokens Revocation as a leaver step; continuous access evaluation where supported[60]
Duplicate identity after rehire New employee ID; matching rule misses Compare HR and directory IDs (Lab 1 prints DUPLICATE) Merge or disable the duplicate Written rehire policy[21]
Mover keeps old access Rules only add groups Group difference against birthright Remove extra groups Recalculate on every change (Lab 1)
Hundreds of accounts disabled at once HR feed error or changed scoping filter Spike in disable events Pause the job; restore from the audit log Bulk-change threshold needing approval
An app’s SSO fails one morning Expired SAML signing certificate App error; certificate dates Update certificate and metadata Certificate expiry calendar

Illustrative scenario. At 10:05 the SOC sees a new authenticator registered for a finance manager, 20 minutes after a phoned-in MFA reset, then a sign-in from an unfamiliar device: the pattern CISA describes for Scattered Spider.[37]

Figure 5. Response to a suspected fraudulent MFA reset
yes, it was themno or unreachableAlert: new MFA method aftera resetUser confirms via knownchannel?Close; record and review thescriptContain: block sign-in, revokesessions, remove newmethodsScope: sign-ins, consents,inbox rules, roles, federationEradicate: remove rogueapps, rules, trusts; rotateexposed secretsRecover: re-proof the user,issue new authenticatorsLearn: fix recovery script anddetections
Diagram source (Mermaid)
flowchart TB
  A["Alert: new MFA method after a reset"] --> B{"User confirms via known channel?"}
  B -->|"yes, it was them"| Z["Close; record and review the script"]
  B -->|"no or unreachable"| C["Contain: block sign-in, revoke sessions, remove new methods"]
  C --> D["Scope: sign-ins, consents, inbox rules, roles, federation"]
  D --> E["Eradicate: remove rogue apps, rules, trusts; rotate exposed secrets"]
  E --> F["Recover: re-proof the user, issue new authenticators"]
  F --> G["Learn: fix recovery script and detections"]
  classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  class A,C risk
  class B decision
  class D,E,F,G,Z core

Text equivalent: an alert of a new MFA method after a reset leads to one question: does the user confirm it through a known channel? If yes, close and review the script. If not, contain, scope, eradicate, recover and learn, in that order.

  1. Verify (0–10 min). Reach the user through the manager or a device registered before the reset, not the number on the ticket; a call to the HR number alone may ring a SIM-swapped phone.
  2. Contain (10–20 min). Block sign-in; revoke sessions and refresh tokens (Graph revokeSignInSessions[33] or Okta DELETE /api/v1/users/{userId}/sessions?oauthTokens=true&forgetDevices=true, which also clears remembered devices, a default on Identity Engine but not on Classic Engine[34]); remove the attacker’s authenticator; end app sessions that outlive the IdP’s (exception paths).
  3. Scope (20–90 min). Sign-ins since the reset; new OAuth consents and app registrations (Midnight Blizzard kept access through OAuth apps[50]); inbox rules[44]; role assignments; federation and authentication-policy changes.
  4. Eradicate. Remove rogue consents, apps, rules and trusts; ask owners to rotate secrets she could reach.
  5. Recover. Re-proof her through the privileged path, issue new authenticators and confirm the recovery notifications NIST requires.[15]
  6. Learn (within 5 days). Compare the ticket with the script, fix the failed step, and send the alert to DetectionOps. Incident coordination follows IncidentOps; adversary-facing work (evidence, forensics, notification) belongs to ResponseOps.

Done when no session issued after the reset survives, no rogue method or consent remains, and the script fix is live.

  • “Disabled in the directory means offboarded.” Sessions, local app accounts and machine credentials survive. Measure end to end.
  • “MFA is 100%.” If SMS and push count, phishable sign-ins hide in the number. Report phishing-resistant coverage and usage.
  • Forced password expiry. NIST says verifiers “SHALL NOT require subscribers to change passwords periodically”;[15] CISA’s advisory agrees.[37] Change on evidence of compromise.
  • JIT as the provisioning strategy. It never removes accounts; Docker, for example, recommends “SCIM with JIT turned off”.[59]
  • The help desk as the default recovery path. It makes social engineering a supported feature.
  • People sharing service accounts. OWASP lists “Human Use of NHI” as a top risk;[38] it also destroys attribution.
  • Myth: SSO concentrates risk, so avoid it. It concentrates control too: one place to enforce MFA, revoke and log. Treat the IdP as tier-0 instead of scattering passwords.

Name and staff it when you have dozens of SaaS apps, contractors or guests without HR records, a hybrid directory, auditors asking for leaver evidence, machine identities growing faster than people, or a recent identity incident.

Do not build a separate practice in a small organisation (a few dozen people, a handful of apps): one administrator with the IdP’s built-in features, SSO wherever possible, security keys for administrators and a monthly reconciliation are enough. Do not buy an IGA suite before HR data is clean and the application register exists: rules on bad attributes automate bad decisions.

Hidden responsibilities: an IdP on-call with change control; a service desk with a script and authority to refuse callers; app owners who accept SLAs for what cannot be automated.

Decision framework: connecting an application

Link to section “Decision framework: connecting an application”
Figure 6. How to connect a new application
noyesyesnoyesnoSAML or OIDC?Replace, block or Tier DexceptionSCIM on our plan?Tier A: SSO + SCIMDeactivation API?Tier B: SSO + scriptTier C: daily reconciliation
Diagram source (Mermaid)
flowchart TB
  A{"SAML or OIDC?"} -->|"no"| D["Replace, block or Tier D exception"]
  A -->|"yes"| C{"SCIM on our plan?"}
  C -->|"yes"| TA["Tier A: SSO + SCIM"]
  C -->|"no"| E{"Deactivation API?"}
  E -->|"yes"| TB["Tier B: SSO + script"]
  E -->|"no"| TC["Tier C: daily reconciliation"]
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
  class A,C,E decision
  class TA,TB,TC core
  class D risk

Text equivalent: without SAML or OIDC, replace or block the app, or record a Tier D exception with an expiry. With SSO and SCIM on your plan, use Tier A. Without SCIM but with a user-deactivation API, use Tier B. Otherwise use Tier C with daily reconciliation; if the app holds sensitive data or many users, negotiate SCIM with the vendor meanwhile.

IdP-native lifecycle or an IGA suite? Ask four questions: several authoritative sources? complex birthright rules? many non-SCIM or on-premises targets? heavy audit reporting? Two or more “yes” answers usually justify a dedicated platform and its running cost.

This model is this Atlas’s proposal, calibrated against CISA’s Zero Trust Maturity Model, whose identity pillar runs from Traditional (the agency “manually orchestrates (onboards, offboards, and disables)” identities) to Optimal (“continuously validates identity with phishing-resistant MFA”).[42] Thresholds are suggestions.

Level Observable behaviour Exit criteria to the next level
0 Ad hoc Accounts by email and ticket; local passwords; no reconciliation Sources named; application register exists
1 Centralised One IdP; SSO for major apps; any MFA; JML by ticket HR feed live; leaver SLA measured
2 Automated HR-driven JML; SCIM for top apps; daily reconciliation; NHI inventory Leaver compliance ≥ 90%; orphan rate tracked
3 Governed Phishing-resistant admins and most staff; tiered recovery; owned NHIs; IdP change control; drills Phishing-resistant usage ≥ 80%; all NHIs owned
4 Continuous Session events shared (CAEP) where supported; risk-driven re-authentication; short-lived machine credentials Sustained ≥ 95% leaver compliance

Levels 0–1 resemble CISA’s Traditional stage, 2 Initial, 3 Advanced and 4 Optimal; the mapping is approximate.

Window Actions Milestone and metric
Days 1–30 Name owners; build the tiered application register; run Lab 1 on real exports; security keys for administrators; recovery script Baseline KPIs
Days 31–60 HR-driven provisioning for one population; SCIM for the ten largest apps; daily reconciliation; NHI inventory (Lab 3) First automated leavers; owned exception list
Days 61–90 Session revocation for leavers; first drill; alerts on post-reset MFA and federation changes; Tier D expiry dates Drill evidence; leaver compliance rising

Dependencies: clean HR dates (PeopleOps), app owners’ time, licences, SOC capacity. Quick wins: delete orphans; security keys for IdP administrators; remove SMS where a stronger method exists.

Quick start

  • Authoritative source named for employees, contractors, guests and machines
  • Application register with a tier and owner per app
  • Leaver SLA measured from the HR effective time
  • Security keys for every IdP and cloud administrator
  • Recovery script approved by security and the service desk
  • New hires proofed against identity documents (live video for remote hires) before a bootstrap pass is issued

Application onboarding preflight

  • SSO tested; local password sign-in disabled where possible
  • Deactivation enabled (Okta “Deactivate Users”; Entra update action and active mapping) and tested with a test user: what active=false means in this app, whether it deletes, and how long the push takes
  • Only needed attributes mapped; session lifetime and revocation documented
  • Provisioning token registered as an NHI with owner and expiry

Quarterly review

  • Leaver drill across Tier A–D apps, timestamps recorded
  • No provisioning job in error or quarantine
  • Admin roles, federation trusts and signing-certificate expiry dates reviewed
  • Alerts firing for new admins, new trusts and authentication-policy changes
  • Legal-hold path tested (disable without delete)

1. Application connection record

APPLICATION CONNECTION RECORD                          v1  (owner signs)
Application / vendor:            ______________   Business owner: ________
Data classification:             public | internal | confidential | restricted
Users (now / in 12 months):      ____ / ____
SSO protocol:                    SAML | OIDC | none (=> Tier D exception)
Provisioning:                    SCIM | API script | JIT only | manual
Tier:                            A | B | C | D        Exception expiry: ______
Meaning of deactivate here:      blocks sign-in | frees licence | deletes data
App session lifetime / revoke:   ______ / how: ____________________________
Attributes sent:                 ____________________ (minimum needed only)
Provisioning credential:         NHI id ______  owner ______  expiry ______
Leaver SLA accepted by owner:    yes / no      Next review: ______________

2. Assisted recovery script (service desk)

ASSISTED MFA / PASSWORD RECOVERY                                    v2
1. Never act on the number, email or chat the caller gives you.
2. Look up the person in HR. A call-back to the HR number is NOT proof
   on its own: numbers can be SIM-swapped or ported.
3. The manager (or sponsor) confirms the person on a live video call or
   in person, reached through a known channel.
4. Privileged or finance role?  STOP. Route to in-person or supervised
   video proofing AND approval by a second administrator.
5. Issue a ONE-TIME bootstrap pass valid <= 1 hour. Deliver it via the
   manager or to a device registered before the request; never read
   it out on the call. Never set a password or register an
   authenticator on the user's behalf.
6. Record: ticket, verification steps, approver, delivery channel, time.
7. Tell the caller the user will be notified of the reset.
8. Pressure, urgency or "the CEO needs this now" = escalate to security.

3. Non-human identity registration

Example status: YAML syntax-checked by the Atlas validator; field names are this Atlas’s suggestion.

nhi_id: nhi-0427
kind: oauth-client              # service-account | api-key | oauth-client | certificate
system: idp-prod
purpose: "Nightly export of invoices to the data warehouse"
owner: team-finance-data        # a team, plus a named individual below
owner_person: a.rossi@example.com
environment: production         # never shared with test
cadence: nightly                # expected use; the dormant sweep compares against it
credential:
  type: client-secret
  max_age_days: 90
  last_rotated: 2026-09-30
permissions_ref: iamops-review-2026-q3   # design and review live in IAMOps
expires: 2027-03-31             # re-register or decommission by this date
decommission:
  disable_first: true
  observe_days: 14

Provisioning methods

Method Creates Updates Removes Main risk
HR-driven into the directory Yes Yes Yes Dirty HR data spreads everywhere
SCIM 2.0 to apps Yes Yes Deactivates (active=false) Connector token theft; quarantined jobs
Vendor API script Yes Partly If written Script rot when the API changes
JIT at first SSO login Yes At sign-in, if supported No Accounts outlive leavers; reconciliation needed
Manual ticket Yes Slowly Slowly Delay and forgotten steps

Is IdentityOps just IAM with a new name? Largely, for the operational half of IAM; the label stresses running the lifecycle as a measured production service.

Do we need an IGA product? Not to start; ask the four questions in the decision framework.

Disable or delete a leaver? Disable at once, delete later, and first learn what each app does on “disable”: some connectors delete (legal hold). Keep the account disabled for the retention period, longer under legal hold.

Contractors have no HR record. What is their source? A sponsor register: a named employee sponsors each contractor, with an end date that disables the account unless renewed. Guest (B2B) accounts need the same rule; Microsoft’s inactive-guest report (an Entra ID Governance or Entra Suite feature) defaults to 90 days without sign-in.[58]

What if the IdP is down? Existing sessions last until they expire; new sign-ins fail. Microsoft advises “two or more emergency access accounts”, cloud-only and not federated;[35] practise with them. The procedure belongs to AccessOps.

  • Shared signals (final 2025, early adoption). CAEP events such as session-revoked and credential-change let an IdP tell applications to cut a session it has revoked:[17] the standard answer to sessions outliving accounts. Check each app’s support first.
  • Token and signing-key protection (new guidance). NIST IR 8587 (September 2026) covers protecting tokens and assertions “from forgery, theft, and misuse”, including key management, token verification and life-cycle controls.[13]
  • Passkeys at workforce scale (maturing). Recovery and device turnover are the open operational questions.
  • AI agents as identities (unsettled). No standard defines their lifecycle yet; treat each as an NHI with an owner, purpose, expiry and short-lived credential.
Stage Do this
Prerequisites HTTP, cookies and TLS basics; what a token is
1 day Read the authenticator, phishing-resistance and recovery sections of SP 800-63B-4;[15] run Lab 1
1 week In a test tenant, connect one SSO app and one SCIM app; run Lab 2
30 days Run Lab 3 on a non-production cloud account; build the application register; run one leaver drill
Specialisation Federation and key security, IGA design, shared signals, identity proofing
Portfolio A reconciliation tool; an NHI register; a recovery script with a tabletop record

The IDPro Body of Knowledge is a vendor-neutral reading list for the wider IAM field.[5]

Topic Remember
Definition Running who exists and how they prove it
Decisions Authoritative source per identity type; app tiers; recovery tiers; IdP-native or IGA suite
Practices HR-driven JML; SCIM plus session revocation; daily reconciliation; NHI register; IdP change control
Metrics End-to-end leaver compliance; time to disable; orphan rate; phishing-resistant coverage and usage; verified recovery rate
Watch-outs Sessions outlive accounts; JIT never removes; help-desk resets; machine credentials believed unused
Next action Run Lab 1 on real exports this week; enrol IdP administrators on security keys

After this page you can explain the three-ledger model and the identity trio; design a leaver flow that ends sessions; choose connection and recovery tiers; evaluate an estate with the KPIs and the maturity model.

  1. HR marks a leaver at 09:00; the IdP account is disabled at 09:20; at 11:00 the leaver is still editing a document in a SaaS app connected by SCIM. Give two likely reasons.
Show answer for question 1

Not the access token: one issued before 09:20 had expired by 10:50 at the latest (Entra’s default is 60–90 minutes;[32] services that support CAE cut their longer tokens on disable[60]). Likely: the app’s own session survives, and active=false, whose meaning each app defines,[8] may only block new sign-ins; or the deactivation never arrived (a failing or quarantined job,[28] or Okta’s “Deactivate Users” left off[27]). Entra’s 40-minute cycle explains a short delay, not 100 minutes.[29] Revoke app sessions as a leaver step and measure end to end.

  1. Your dashboard shows “MFA enabled: 100%”. Why is that not evidence of strong authentication?
Show answer for question 2

It counts phishable methods; NIST does not treat typed codes (OTP, SMS) as phishing-resistant.[15] Report phishing-resistant coverage, and usage among holders: below 100% means weak fallbacks are still accepted from people who own a strong method.

  1. After a supplier breach your team rotated “all” exposed credentials, yet one was used weeks later. What was missing?
Show answer for question 3

An inventory with last-used evidence to prove completeness against; Cloudflare’s missed credentials were “believed they were unused”.[52] Measure rotated ÷ exposed, item by item.

  1. A SaaS app holding customer contracts offers SAML with JIT, no SCIM on your plan and no user API. Which tier, and what interim control?
Show answer for question 4

Tier C: JIT never removes accounts, so reconcile the app’s user export daily and remove leavers within the SLA. Because the data is sensitive, negotiate SCIM with a deadline (decision framework).

  1. Design challenge: name three alerts that catch help-desk recovery abuse.
Show answer for question 5

A new authenticator registered within hours of an assisted reset; a new federated IdP or trust (ATT&CK T1484.002; Scattered Spider historically added one[37]) or an authentication-policy change; and a risky sign-in or token anomaly for the reset user.[44]

IdentityOps is a new name for old, unglamorous work, and the work matters more than the name. Its core is simple to state and hard to sustain: three ledgers that agree every day; a sign-in method a fake website cannot steal; a recovery path a confident caller cannot talk through; machine identities that end when their purpose ends. None of the incidents on this page defeated cryptography: a test account had no MFA, a service account was believed unused, a password was four years old, a help desk was persuaded. If you can show, with timestamps, that leavers are out everywhere, that sign-in resists phishing and that every machine identity has an owner, you are doing IdentityOps, whatever your teams are called.

Claim-by-claim evidence: research/identityops-ledger.md. Product documentation changes often: the identity team should re-check the product facts on this page (cycle intervals, token defaults, licence tiers, API versions) at its quarterly IdP configuration review, and before relying on any of them.

Further reading: Passkeys (FIDO Alliance); Microsoft Entra ID Governance overview.

Changelog: 2026-10-16 — first version: research, ledger, draft, six diagrams; Labs 1 and 3 executed on synthetic data, Lab 2 syntax-checked only; no independent fact-check review yet. 2026-10-17 — revised after independent review r1: recovery no longer trusts phone call-backs (SIM swap); Entra deletion behaviour corrected; proofing before bootstrap; provisioning preconditions and latency; ATT&CK, CSF and case wording; Lab 2 hardened; figures 2–4 corrected; repetition cut; 11 sources added, 1 removed. 2026-10-17 — revised after independent review r2 (12 minor findings): access-token lifetime stated as 60–90 minutes with Microsoft’s token-lifetime page added; IR 8587 authorship; shared-signals dating; quarantine mechanism; Okta forgetDevices side effect in Lab 2 and the runbook; Lab 1 detects duplicate accounts (re-executed); policy YAML schema; deprovisioning-coverage formula; dormant-sweep exclusions and NHI cadence; guest-report licence; figure 4 note; ephemeral term-status sources archived. 2026-10-17, post-score polish: AAL1 glossary wording (“at least one factor”); the PSTN risk-indicator rule labelled as applied by analogy; Entra’s unassign-then-push path for urgent leavers with its caveats; re-check cadence for product facts; figure 1 edges carry handoff labels; figure 3 reconciliation inputs named in the node instead of on curved edges; NIST and Entra sources re-opened. 2026-10-17, after the polish check: the urgent-leaver path labelled as this page’s reading, with its trade-off and two preconditions.


  1. Identity Operations: What It Means — MojoAuth glossary, updated 2026-09-28. Checked 2026-10-16. ↩︎ ↩︎

  2. What Is Identity Operations? — NHI Mgmt Group glossary, updated 2026-06-07. Checked 2026-10-16. ↩︎

  3. What is IdentityOps? — Opsio, 2025-08-25 (updated 2025-10-13), as seen 2026-10-16; archived copy of 2026-10-17. Checked 2026-10-16. ↩︎

  4. Security Operations Engineer (Identity Operations team) — Microsoft job posting via AnitaB.org, undated (“Posted 6+ months ago”), as seen 2026-10-16; archived copy of 2026-10-17. Checked 2026-10-16. ↩︎

  5. IDPro Body of Knowledge — IDPro. Checked 2026-10-16. ↩︎ ↩︎

  6. Valid Accounts, T1078 — MITRE ATT&CK, modified 2026-05-12. Checked 2026-10-16. ↩︎ ↩︎

  7. SAML V2.0 Technical Overview — OASIS, 2008-03-25 (cites the March 2005 core specification). Checked 2026-10-16. ↩︎ ↩︎

  8. RFC 7643, SCIM: Core Schema — IETF, September 2015. Checked 2026-10-16. ↩︎ ↩︎ ↩︎

  9. RFC 7644, SCIM: Protocol — IETF, September 2015. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎

  10. Implementing Phishing-Resistant MFA — CISA fact sheet, October 2022. Checked 2026-10-16. ↩︎ ↩︎ ↩︎

  11. SP 800-63-4, Digital Identity Guidelines — NIST, 2025-07-31. Checked 2026-10-16. ↩︎ ↩︎

  12. Three Shared Signals Final Specifications Approved — OpenID Foundation, 2025-09-02. Checked 2026-10-16. ↩︎ ↩︎

  13. NIST IR 8587, Protecting Tokens and Assertions from Forgery, Theft, and Misuse — NIST Internal Report (authors from NIST, Accenture Federal Services and CISA), 2026-09-15. Checked 2026-10-16, authorship re-checked 2026-10-17. ↩︎ ↩︎ ↩︎ ↩︎

  14. OpenID Connect Core 1.0 incorporating errata set 2 — OpenID Foundation, 2023-12-15. Checked 2026-10-16. ↩︎ ↩︎

  15. SP 800-63B-4, Authentication and Authenticator Management — NIST, 2025. Checked 2026-10-16, re-checked 2026-10-17. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  16. Microsoft Entra Connect: Prerequisites and hardware — Microsoft Learn, 2026-01-16. Checked 2026-10-17. ↩︎ ↩︎

  17. OpenID Continuous Access Evaluation Profile 1.0 — OpenID Foundation, 2025-08-29. Checked 2026-10-16. ↩︎ ↩︎

  18. OpenID RISC Profile Specification 1.0 — OpenID Foundation, 2025-08-29. Checked 2026-10-17. ↩︎

  19. The NIST Cybersecurity Framework (CSF) 2.0 — NIST CSWP 29, 2024-02-26. Checked 2026-10-16. ↩︎ ↩︎

  20. SP 800-53 Rev. 5 (Release 5.2.0), control AC-2 — NIST, release 5.2.0 of 2025-08-27; control text read in the OSCAL catalog. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎

  21. Plan cloud HR application to Microsoft Entra user provisioning — Microsoft Learn, 2025-07-24. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  22. Jasper Sleet: North Korean remote IT workers’ evolving tactics to infiltrate organizations — Microsoft Threat Intelligence, 2025-06-30 (updated 2026-04-21). Checked 2026-10-17. ↩︎

  23. SP 800-63A-4, Identity Proofing and Enrollment — NIST, 2025. Checked 2026-10-17. ↩︎

  24. Configure Temporary Access Pass — Microsoft Learn, 2026-03-04. Checked 2026-10-16. ↩︎ ↩︎ ↩︎

  25. What are lifecycle workflows? — Microsoft Learn, 2026-03-12. Checked 2026-10-16. ↩︎ ↩︎ ↩︎

  26. Group Managed Service Accounts overview — Microsoft Learn, 2025-07-01. Checked 2026-10-17. ↩︎

  27. Understanding SCIM and SCIM 2.0 protocol guide — Okta Developer. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  28. How Application Provisioning works in Microsoft Entra ID — Microsoft Learn, 2025-03-04 (updated 2026-02-05). Checked 2026-10-16, re-checked 2026-10-17. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  29. Tutorial: Develop and plan provisioning for a SCIM endpoint — Microsoft Learn, 2026-09-15. Checked 2026-10-16. ↩︎ ↩︎

  30. Provision a user or group on demand — Microsoft Learn, 2025-03-04 (updated 2026-10-14). Checked 2026-10-17. ↩︎ ↩︎

  31. Revoke user access in an emergency in Microsoft Entra ID — Microsoft Learn, 2026-06-19. Checked 2026-10-16, re-checked 2026-10-17. ↩︎ ↩︎ ↩︎ ↩︎

  32. Configurable token lifetimes in the Microsoft identity platform — Microsoft Learn, 2026-04-08 (updated 2026-06-15). Checked 2026-10-17. ↩︎ ↩︎

  33. user: revokeSignInSessions — Microsoft Graph v1.0, 2024-04-17. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  34. Okta Management API OpenAPI file, version 2026.41.0 — Okta (operations “Revoke all user sessions”, “Deactivate a user”, “Suspend a user”); rendered as User Sessions and User Lifecycle. Checked 2026-10-17. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  35. Manage emergency access admin accounts — Microsoft Learn, 2026-06-04. Checked 2026-10-16. ↩︎ ↩︎

  36. How to manage inactive user accounts — Microsoft Learn, 2025-02-21. Checked 2026-10-16. ↩︎ ↩︎

  37. AA23-320A, Scattered Spider — CISA and partners, 2023-11-16, last revised 2025-07-29. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  38. OWASP Top 10 Non-Human Identities Risks – 2025 — OWASP, 2025. Checked 2026-10-16. ↩︎ ↩︎ ↩︎

  39. Get credential reports for your AWS account — AWS IAM User Guide. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎

  40. RoleLastUsed — AWS IAM API Reference. Checked 2026-10-17. ↩︎

  41. Security best practices in IAM — AWS IAM User Guide. Checked 2026-10-16. ↩︎ ↩︎

  42. Zero Trust Maturity Model, Version 2.0 — CISA, April 2023. Checked 2026-10-16. ↩︎ ↩︎

  43. RFC 9700, Best Current Practice for OAuth 2.0 Security — IETF, January 2025. Checked 2026-10-16. ↩︎ ↩︎

  44. What are risk detections? — Microsoft Learn, 2026-04-22. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  45. Microsoft Defender for Identity dashboard — Microsoft Learn, 2026-07-02. Checked 2026-10-16. ↩︎

  46. curl man page, --fail-with-body — curl project (“Added in 7.76.0”). Checked 2026-10-17. ↩︎

  47. get-credential-report — AWS CLI Command Reference. Checked 2026-10-16. ↩︎

  48. Root user best practices for your AWS account — AWS IAM User Guide. Checked 2026-10-17. ↩︎

  49. Microsoft Actions Following Attack by Nation State Actor Midnight Blizzard — MSRC, 2024-01-19. Checked 2026-10-16. ↩︎

  50. Midnight Blizzard: Guidance for responders on nation-state attack — Microsoft Security Blog, 2024-01-25. Checked 2026-10-16. ↩︎ ↩︎

  51. Unauthorized Access to Okta’s Support Case Management System: Root Cause and Remediation — Okta Security, 2023-11-03. Checked 2026-10-16. ↩︎

  52. Thanksgiving 2023 security incident — Cloudflare, 2024-02-01. Checked 2026-10-16. ↩︎ ↩︎

  53. UNC5537 Targets Snowflake Customer Instances for Data Theft and Extortion — Mandiant (Google Cloud), 2024-06-10. Checked 2026-10-16. ↩︎

  54. Incidents impacting retailers – recommendations from the NCSC — NCSC (UK), 2025-05-04. Checked 2026-10-16. ↩︎

  55. Multi-Factor Authentication Request Generation, T1621 — MITRE ATT&CK, modified 2025-10-24. Checked 2026-10-16. ↩︎

  56. Domain or Tenant Policy Modification: Trust Modification, T1484.002 — MITRE ATT&CK, modified 2026-05-12. Checked 2026-10-17. ↩︎

  57. Modify Authentication Process, T1556 — MITRE ATT&CK, modified 2026-05-12. Checked 2026-10-16. ↩︎

  58. Monitor and clean up stale guest accounts — Microsoft Learn, 2024-12-30. Checked 2026-10-17. ↩︎ ↩︎

  59. Migrate JIT to SCIM — Docker Docs. Checked 2026-10-16. ↩︎ ↩︎

  60. Continuous access evaluation — Microsoft Learn, 2026-04-08. Checked 2026-10-16. ↩︎ ↩︎

Related Ops

IAMOps

IAMOps is an informal label for IAM operations. This Atlas uses it for authorisation as code: designing, testing and evaluating the policies that decide what people, workloads and agents may do, so permissions stay minimal, explainable and testable.

AccessOps

AccessOps is not a standard term. Here it means running the moment of access beyond birthright, above all privileged access: how people request, receive, use and give back access, with no standing admin rights, expiry the system enforces, a tested break-glass path and reviews that can say no.

PeopleOps

PeopleOps (people operations) runs an organisation's employee lifecycle (hiring, onboarding, moves, pay, performance and exits) as a reliable, measured operation built on one trusted system of record, clear owners and service levels.

CloudSecOps

CloudSecOps is running security for a cloud estate at the provider-API layer: guardrails that block unsafe configuration, continuous posture checks, complete audit logs, and detection and response for control-plane activity. The label is emerging and loosely defined.

EndpointOps

EndpointOps is an informal name for running user devices through their whole life: enrolment, configuration, compliance, encryption, EDR health, access decisions and retirement, where IT management and security meet. The practice is established as endpoint management plus endpoint security.

ComplianceOps

ComplianceOps runs regulatory and contractual compliance as a continuous operation: one library of controls mapped to every framework in scope, evidence collected and tested on a schedule, exceptions with expiry dates, and audits served from records that already exist.

SOC Ops

SOC Ops is running a security operations centre as a dependable service: turning alerts into timely, recorded decisions through tiers, playbooks, SIEM and SOAR, shift handover, metrics and sourcing choices that people can sustain around the clock.

DetectionOps

DetectionOps is a rare label for detection engineering run like software delivery: detections are written as code from threat-informed requirements, tested, peer-reviewed, deployed through a pipeline, measured in production, tuned and retired.

Practise and get certified

From xOps School

Practise IdentityOps and get certified

The free IdentityOps track on xOps School has study notes, a 25-question practice quiz with explanations, and a verifiable certificate when you score 70% or more. Sign in with Google to start.

For teams

Instructor-led training

Live batches for your team, with completion certificates and reports for L&D/HR.

Source: master.md (the editorial source of this page) · built 2026-10-17 · diagrams rendered with @mermaid-js/mermaid-cli 11.17.0 (mermaid 11.17.2)