49 min read

Eight months after the phishing near-miss, a routine audit at Meridian Regional Bank turned up something nobody on the security team wanted to explain to an examiner. A wire-fraud analyst, reviewing access to the loan-origination system, pulled the...

Prerequisites

  • 16
  • 17

Learning Objectives

  • Explain why identity is the perimeter at scale and what an IAM program (identity governance) adds beyond authentication and authorization.
  • Describe directory services — Active Directory, LDAP, and Entra ID — and the role they play as the source of truth for identity.
  • Walk through single sign-on and federation, tracing a SAML assertion and an OIDC flow end to end, and distinguish SAML from OIDC from OAuth 2.0.
  • Run the joiner-mover-leaver identity lifecycle and automated provisioning (SCIM), and explain how each transition is abused when it is manual or missed.
  • Conduct an access certification (access review), find orphaned and over-privileged accounts, and design deprovisioning that closes the contractor-offboarding gap.

Chapter 18: Identity Governance: SSO, Federation, Directory Services, and Managing a Million Accounts

"Identity is the new perimeter." — a maxim repeated across the identity-security industry

Overview

Eight months after the phishing near-miss, a routine audit at Meridian Regional Bank turned up something nobody on the security team wanted to explain to an examiner. A wire-fraud analyst, reviewing access to the loan-origination system, pulled the list of accounts that could approve disbursements. There were forty-one of them. Thirty-three belonged to current employees who needed the access. Three belonged to people who had moved to other departments two years earlier and never had the entitlement removed. Two belonged to employees who had left the bank. And three belonged to contractors — one of whom had finished a six-week engagement eleven months ago, whose laptop had been returned, whose badge had been deactivated, and whose Active Directory account was still enabled, still a member of the loan-approval group, and still capable of logging into Meridian's single sign-on portal from anywhere in the world.

Nobody had been malicious. Nobody had even been negligent in a way you could put a name to. The contractor's account survived for the most ordinary reason in enterprise security: the human resources system knew the contractor was gone, the badge system knew, the laptop-inventory system knew — and none of them told Active Directory, because the only thing that connected those systems to the directory was a person who was supposed to remember to file a ticket, and that person had been on the project that ended, and the ticket was never filed. The account did not expire. Accounts do not expire on their own. They sit there, valid and forgotten, until an attacker who has bought a leaked password, or a disgruntled insider who remembers the credentials, or an auditor doing exactly what Meridian's analyst was doing, finds them.

This is the problem Chapter 1 flagged in Meridian's very first risk register — "orphaned/over-privileged account enables lateral movement" — and it is the problem this chapter solves. Chapter 16 taught you to prove who someone is. Chapter 17 taught you to decide what they may do. Both assumed the account already existed and that it should. This chapter is about the messy, unglamorous, enormously consequential work of governing identities across their entire lifetime in an organization of thousands of people and tens of thousands of accounts: how identities get created, how they flow from system to system, how access accumulates, and — the part everyone forgets until an examiner asks — how access gets removed. We call this discipline identity governance, and it is where most real breaches actually begin, because the easiest way into an organization is not a zero-day exploit. It is a valid login that should have been turned off and wasn't.

In this chapter, you will learn to:

  • Explain what an IAM program (identity governance and administration) is, and why authentication and authorization are necessary but not sufficient without it.
  • Describe directory services — Active Directory, LDAP, and Entra ID — as the source of truth that every other system trusts for identity.
  • Trace single sign-on and federation end to end, reading a SAML assertion and an OIDC token, and tell SAML, OIDC, and OAuth 2.0 apart without hand-waving.
  • Operate the joiner-mover-leaver lifecycle and automated provisioning (SCIM), and recognize how each transition becomes an attack path when it is manual.
  • Run an access certification, hunt down orphaned accounts and privilege creep, and build deprovisioning that actually closes the gap the contractor walked through.

Learning Paths

Identity governance sits at the intersection of engineering and governance, which is why this chapter is a home chapter for two of our four readers and a heavily tested topic for the third.

🏗️ Security Engineer: This is core territory. Read §18.2 (directories) and §18.3 (SSO/federation) closely — you will design or operate these systems. §18.4 (JML/SCIM) is the automation you will build. The SAML and OIDC flows are things you must be able to draw on a whiteboard. 📋 GRC: §18.5 (access reviews, certification, orphaned accounts) is your chapter. Access certification is an audit cornerstone for SOX, PCI-DSS, and GLBA. The Meridian cleanup in §18.6 is the kind of remediation you will own. 📜 Certification Prep: Security+ and CISSP both test SSO, federation, SAML vs. OIDC vs. OAuth, the identity lifecycle, and access reviews. Every key term in this chapter appears on at least one exam; key-takeaways.md maps them. 🛡️ SOC Analyst: You are less hands-on here, but orphaned and over-privileged accounts are the lateral-movement enabler you will chase in Part V. Read §18.5 so you recognize the wreckage in your logs.


18.1 Identity at scale: why a million accounts is a different problem

Start with a number, because the number is the whole reason this chapter exists. Meridian has about 1,800 employees. It also has several hundred contractors and temporary staff over the course of a year, a few thousand service accounts (the non-human identities we treat fully in Chapter 20), and a customer base of 2.5 million people who each have a digital identity for online banking. Even if you set the customers aside and count only the workforce, Meridian is not managing 1,800 identities. It is managing 1,800 people, each of whom has an account in Active Directory, an account in Entra ID, a mailbox, access to somewhere between five and fifty applications, membership in a dozen security groups, and a set of entitlements that changes every time they get promoted, transfer teams, take a leave, or pick up a side project. The number of access decisions that must be correct at any given moment is not 1,800. It is closer to a hundred thousand, and it changes every day.

At ten accounts, you manage identity by remembering. At a hundred, you manage it with a spreadsheet. At a thousand, the spreadsheet is already lying to you — it was last accurate the day someone updated it, and people have joined, left, and moved since then. At ten thousand, manual identity management is not merely inefficient; it is a guaranteed source of security failures, because the gap between who has access and who should have access widens every single day, and that gap is exactly where attackers live. This is the first principle of the chapter:

🚪 Threshold Concept: In a large organization, the dangerous state is not "an attacker breaks in." It is "the organization has lost track of who can already get in." Most environments are carrying valid credentials for people who left, entitlements for roles people no longer hold, and access nobody remembers granting. An attacker does not need to defeat your authentication if they can find an account you forgot to disable. Identity governance is the practice of continuously closing the gap between actual access and intended access — and at scale, that gap is your largest, quietest attack surface.

This is why identity is the perimeter, the phrase you met as a theme back in Chapter 1 and that frames all of Part IV. The old model of security imagined a hard outer wall — a firewall around a trusted inside (Chapter 6). That model is dead (Chapter 7 is literally subtitled the perimeter that doesn't exist anymore). Meridian's people work from home, from branches, from phones; its applications live in AWS and Microsoft 365 as much as in the data center. There is no single wall to defend. What every request has in common — from a teller in a branch, an executive on a laptop in an airport, an API call from a partner bank — is an identity making it. If you can govern identity well, you can make access decisions anywhere, on any request, which is precisely the foundation that zero trust (Chapter 32) builds on. If you govern identity badly, every other control is built on sand, because an attacker who holds a legitimate identity walks through your defenses as a trusted user.

So what does it actually take to govern identity? Three capabilities, which map to the last three chapters of this part and to the structure of this one:

  • Administration — creating, changing, and removing identities and their access across their whole lifetime (the lifecycle in §18.4). This is the plumbing: who gets an account, what it can reach, and — critically — when it goes away.
  • Authentication — proving the identity is who it claims (Chapter 16), often delivered once via single sign-on so the proof can be reused across many applications (§18.3).
  • Governance — the oversight that checks the plumbing is correct: access reviews, certifications, segregation-of-duties enforcement, and the hunt for the accounts and entitlements that should not exist (§18.5).

Put administration, authentication, and governance together and you have an identity and access management (IAM) program — also called identity governance and administration (IGA) — the organizational capability for managing the full lifecycle of identities and their access, and for proving to yourself and to an auditor that the right people (and only the right people) have the right access to the right resources for the right reasons.

🔗 Connection: Be careful with the word "IAM." Chapter 15 used cloud IAM to mean the access-control service inside a single cloud provider — AWS IAM, the thing that decides whether an EC2 instance may read an S3 bucket. That is one technical mechanism inside one platform. The IAM program of this chapter is the organization-wide governance discipline that spans Active Directory, Entra ID, every SaaS app, every cloud account, and every contractor. Cloud IAM is a tool the program governs; the program is the strategy. Keep the two distinct — the disambiguation matters on the CISSP exam and in real architecture conversations.

Everything an IAM program does depends on having one authoritative answer to the question "who exists here and what are they?" That authoritative answer lives in a directory, and that is where we start.

18.2 Directories: Active Directory, LDAP, and Entra ID

A directory service is a specialized database that stores identities — users, groups, computers, and the attributes that describe them — and answers the constant stream of questions other systems ask about them: Does this user exist? What is their email? Which groups are they in? Is their account enabled? Is this password correct? It is the source of truth for identity, and almost every other system in an enterprise trusts it rather than maintaining its own list of who people are. Get the directory right and you have one place to disable a departing employee. Get it wrong — or have five of them that disagree — and you have the Meridian contractor problem multiplied across the environment.

Directories are optimized for a particular shape of work: they are read enormously more often than they are written (every login reads the directory; accounts are created comparatively rarely), and they are organized hierarchically, like a tree, mirroring how organizations think about themselves — domains contain organizational units, which contain users and groups. The protocol that most directories speak is LDAP (the Lightweight Directory Access Protocol), a standard, vendor-neutral way to query and modify directory data. When an application "authenticates against LDAP," it is asking a directory server, over LDAP, to confirm a username and password and return the user's attributes and group memberships. LDAP is the lingua franca; the most important directory products are implementations of, or speakers of, it.

The directory you will meet most often in an enterprise data center is Active Directory (AD) — Microsoft's on-premises directory service, which has been the backbone of corporate identity for over two decades and runs at the heart of Meridian's data center. AD is far more than an LDAP database. It is a whole identity ecosystem: it speaks LDAP for queries, but it authenticates users with the Kerberos protocol (a ticket-based system where a user proves their identity once to a central authority and receives time-limited tickets to access services without re-sending their password), it distributes configuration and security policy to thousands of machines through Group Policy (which you met hardening Windows in Chapter 11), and it organizes everything into domains managed by domain controllers — the servers that hold the directory and answer authentication requests. Because AD controls authentication and policy for nearly every Windows machine and user in an organization, it is simultaneously the most useful and the most dangerous system in the environment. An attacker who compromises a domain controller does not own a server; they own the identity of everyone in the company. This is why AD is the single most-targeted system in enterprise breaches, why domain-admin lockdown is its own chapter (Chapter 19), and why the orphaned accounts we are hunting matter so much — they live in AD, and AD is the master key.

Here is the structure, because you will be reasoning about it constantly:

            ACTIVE DIRECTORY (Meridian on-prem domain: meridianbank.example)
            ┌──────────────────────────────────────────────────────────┐
            │  DOMAIN CONTROLLER(s)  ── hold the directory, answer       │
            │                            Kerberos auth + LDAP queries    │
            └───────────────────────────┬──────────────────────────────┘
                                        │
                  ┌─────────────────────┼─────────────────────┐
                  ▼                     ▼                     ▼
            OU=Branches            OU=Corporate           OU=Service Accounts
              │                       │                       │
        ┌─────┴─────┐         ┌───────┴───────┐         (non-human; Ch.20)
        ▼           ▼         ▼               ▼
   user=teller1  user=...  group=Loan-Approvers   group=Domain Admins
        │                       │  (members get          │  (the crown jewels:
   member of:                   │   wire-approval         │   keys to everything)
   [Tellers]                    │   entitlement)          ▼
                                ▼                    user=svc_backup, admin1...
                          user=loanofficer3,
                          user=CONTRACTOR_X  <-- still here, 11 months after offboarding

Figure 18.1 — Active Directory as a tree of organizational units (OUs) containing users and groups. Access is granted by group membership: being in Loan-Approvers confers the wire-approval entitlement. The orphaned contractor account sits in an OU, still a group member, indistinguishable to the system from a legitimate user — because nothing told AD the human was gone.

The second directory you must know is Entra ID (Microsoft's cloud identity service, formerly named Azure Active Directory — you will still see "Azure AD" everywhere). Despite the similar name, Entra ID is not cloud-hosted Active Directory; it is a different architecture for a different world. AD was built for machines on a corporate network authenticating with Kerberos. Entra ID was built for the cloud and the web: it authenticates users to SaaS applications and cloud resources using the internet identity protocols we cover in §18.3 (SAML, OAuth 2.0, OIDC), not Kerberos. It has no organizational-unit tree and no Group Policy; it has users, groups, applications, and Conditional Access policies (rules that grant or block access based on user, device, location, and risk — a building block of zero trust). Meridian, like most enterprises, runs a hybrid identity environment: on-prem Active Directory synchronized to Entra ID, so that a single human has one identity that works both for the legacy Windows applications in the data center and for Microsoft 365 and the cloud. The synchronization is done by a connector (Microsoft's Entra Connect) that copies user accounts and password hashes from AD up to Entra ID on a schedule.

That hybrid sync is convenient and it is a trap, and understanding why is the defensive heart of this section:

🛡️ Defender's Lens: In a hybrid environment, AD is usually the source and Entra ID is the copy. That means a departing employee disabled in Entra ID but not in on-prem AD may still be able to authenticate to on-prem systems — and worse, the next sync cycle can re-enable the account in the cloud, faithfully copying the "still enabled" state up from AD. Defenders are routinely surprised to find that "we disabled them in the cloud" did nothing, because the authoritative source was the on-prem directory nobody updated. The lesson: know which directory is authoritative for each population, and disable accounts at the source. The contractor in Figure 18.1 was disabled nowhere, but even partial action against the wrong directory would have left the door open.

Two more directory facts earn their place. First, AD's authentication protocols carry their own classic attack paths that you, as a defender, must recognize even though we never weaponize them: Kerberoasting (an attacker with any domain account requests service tickets for accounts running services, then cracks the tickets offline to recover the service account's password — which is why service-account passwords must be long and random, Chapter 20) and pass-the-hash (an attacker who steals a password hash from one machine reuses it to authenticate elsewhere without ever knowing the plaintext — which is why credential hygiene and admin tiering, Chapter 19, matter). You do not need to execute these to defend against them; you need to know they exist, know they leave traces (anomalous service-ticket requests, authentication from unexpected hosts), and know that the controls in the next chapters blunt them. Second, directories are also a reconnaissance goldmine for attackers: because nearly any authenticated user can read large parts of AD over LDAP, an attacker with one foothold can enumerate every user, every group, every admin, and map the whole organization — which is exactly why monitoring for unusual LDAP enumeration is a worthwhile detection (and why the principle of least privilege, Chapter 17, should limit what ordinary accounts can see).

🔄 Check Your Understanding: 1. What is the relationship between LDAP and Active Directory? Is one a kind of the other? 2. A help-desk technician disables a departing employee's account in Entra ID (the cloud), but the bank uses on-prem AD as the source of truth synced upward. Two days later the account is enabled again. What happened, and where should the technician have disabled it?

Answers

  1. LDAP is a protocol (a standard language for querying and modifying directory data); Active Directory is a product (Microsoft's directory service) that, among other things, speaks LDAP. AD is not "a kind of LDAP" and LDAP is not "a kind of AD" — AD implements/uses LDAP alongside other protocols like Kerberos. 2. The directory-synchronization process copied the still-enabled state from the authoritative on-prem AD up to Entra ID, overwriting the cloud-side disable. The account should have been disabled in on-prem AD (the source), which would then propagate the disabled state to the cloud.

18.3 Single sign-on and federation: SAML, OIDC, and OAuth

Now we solve a problem the directory alone does not: how a user proves who they are once and reaches many applications, including applications that live in other companies' clouds and never see Meridian's directory at all. This is the domain of single sign-on and federation, and it is where three protocols — endlessly confused with one another — do three different jobs.

Single sign-on (SSO) is the capability that lets a user authenticate one time and then access multiple independent applications without re-authenticating to each. The user logs in to a central identity provider (IdP) — at Meridian, that is Entra ID — and the IdP vouches for them to each application, called a service provider (SP) or relying party. The user experience is the obvious win: one login, then everything. But the security win is larger and is the reason a defender loves SSO. When authentication happens in one place, you can enforce strong, phishing-resistant MFA (Chapter 16) in that one place and have it protect every connected app; you can apply Conditional Access — block logins from impossible-travel locations or unmanaged devices — in that one place; and, most relevant to this chapter, when an employee leaves, disabling their one identity at the IdP cuts off every application at once, instead of leaving you to remember forty separate accounts. SSO turns identity into a single chokepoint, and chokepoints are where defenders want to stand.

⚠️ Common Pitfall: SSO concentrates risk as well as control. If the IdP is the one place that grants access to everything, then a compromise of the IdP — or of a single user's SSO session — is a compromise of everything that trusts it. This is the lesson of several major breaches where attackers who stole or forged identity-provider tokens moved laterally into dozens of downstream applications. SSO is the right architecture, but it raises the stakes on protecting the IdP itself: phishing-resistant MFA on every IdP login, tight admin control of the IdP (Chapter 19), monitoring of token issuance, and short session lifetimes. Do not deploy SSO and then guard the front door with a password.

Federation is SSO that crosses organizational boundaries — a trust relationship that lets one organization's users authenticate to another organization's applications without the second organization managing those users' credentials. When a Meridian employee logs into a third-party benefits portal run by an insurance company, and that portal trusts Meridian's Entra ID to vouch for the employee, that is federation. Meridian is the identity provider; the insurance company is the service provider; and the magic is that the insurance company never sees the employee's password, never stores their account, and trusts Meridian's say-so because the two organizations established a cryptographic trust in advance. Federation is what makes the modern web of interconnected SaaS possible: you do not have a separate password at every vendor; your home organization vouches for you everywhere it has set up trust. The protocols below are the languages in which that vouching is spoken.

SAML: the enterprise federation workhorse

SAML (Security Assertion Markup Language, version 2.0) is an XML-based open standard for exchanging authentication and authorization data between an identity provider and a service provider. It is the older of the two federation protocols, it is built around XML and digital signatures, and it absolutely dominates enterprise SSO to SaaS applications — when a corporate user clicks "Log in with your company account" at a business application, the exchange behind the curtain is very often SAML. The core artifact is the SAML assertion: a signed XML document in which the IdP states "this user authenticated, here is who they are, here are some attributes, and here is my cryptographic signature proving I really said this."

Here is the flow, which you must be able to trace, with the artifact at its center:

   USER's BROWSER          SERVICE PROVIDER (SP)        IDENTITY PROVIDER (IdP)
   (Meridian employee)     app.example  (a SaaS app)    Entra ID (login.meridianbank.example)
        │                        │                            │
        │  1. GET /app          │                            │
        ├───────────────────────►│                            │
        │                        │  2. Not authenticated.     │
        │  3. Redirect to IdP    │     Build SAML AuthnRequest │
        │◄───────────────────────┤                            │
        │                                                     │
        │  4. GET /sso?SAMLRequest=...   (browser carries it) │
        ├─────────────────────────────────────────────────────►│
        │                                                     │  5. IdP authenticates
        │                                                     │     the user (password
        │                                                     │     + phishing-resistant
        │                                                     │     MFA — Ch.16), then
        │                                                     │     builds + SIGNS a
        │                                                     │     SAML Assertion
        │  6. Redirect back to SP with signed SAML Assertion  │
        │◄─────────────────────────────────────────────────────┤
        │                                                     │
        │  7. POST /acs  (Assertion Consumer Service)         │
        │      body = <signed SAML Assertion>                 │
        ├───────────────────────►│                            │
        │                        │  8. SP VERIFIES the IdP's   │
        │                        │     signature, checks the   │
        │                        │     audience + timestamps,  │
        │  9. App grants session │     reads the user identity │
        │◄───────────────────────┤                            │
        │   (logged in — never sent a password to the SP)     │

Figure 18.2 — The SAML SSO flow (service-provider-initiated). The user never sends a credential to the application (the SP). The SP trusts the IdP's signed assertion. The browser is the courier that carries signed messages between two parties that never talk directly.

A trimmed, illustrative SAML assertion looks like this — read it as the content of the signed document in step 6, not as something to copy:

<!-- Illustrative SAML 2.0 assertion (trimmed). Real assertions are larger and fully signed. -->
<saml:Assertion IssueInstant="2026-06-14T13:02:11Z">
  <saml:Issuer>https://login.meridianbank.example/idp</saml:Issuer>
  <ds:Signature> ... IdP's cryptographic signature over this assertion ... </ds:Signature>
  <saml:Subject>
    <saml:NameID>loanofficer3@meridianbank.example</saml:NameID>
  </saml:Subject>
  <saml:Conditions NotBefore="2026-06-14T13:02:11Z" NotOnOrAfter="2026-06-14T13:07:11Z">
    <saml:AudienceRestriction>
      <saml:Audience>https://app.example/saml</saml:Audience>   <!-- only THIS app -->
    </saml:AudienceRestriction>
  </saml:Conditions>
  <saml:AttributeStatement>
    <saml:Attribute Name="department"><saml:AttributeValue>Lending</saml:AttributeValue></saml:Attribute>
    <saml:Attribute Name="groups"><saml:AttributeValue>Loan-Officers</saml:AttributeValue></saml:Attribute>
  </saml:AttributeStatement>
</saml:Assertion>

Every line here is a security control. The <Issuer> says who is vouching. The <Signature> proves the issuer really vouched and that nothing was altered in transit — the SP rejects the assertion if the signature does not verify against the IdP's known public key. The <Conditions> window (NotBefore/NotOnOrAfter) makes the assertion valid for only a few minutes, so a stolen assertion expires almost immediately. The <AudienceRestriction> binds the assertion to one specific application, so an assertion captured by app.example cannot be replayed against a different SP. Understanding these fields is understanding both how SAML protects you and where it breaks:

🛡️ Defender's Lens: Most SAML disasters come from a service provider that does not properly verify the assertion — accepting an unsigned assertion, failing to check the signature, ignoring the audience restriction, or not enforcing the time window. The infamous class of "SAML signature bypass" vulnerabilities lets an attacker who can craft or tamper with an assertion log in as anyone, because the SP trusted the XML without truly validating it. As a defender configuring or selecting an SSO integration: confirm that signatures are required and verified, that the audience is enforced, that assertions expire quickly, and that you are using a mature, maintained SAML library rather than parsing XML by hand. The protocol is only as strong as the SP's validation of it.

OAuth 2.0 and OIDC: authorization and identity for the modern web

The second pair of protocols is younger, JSON-and-HTTP-based instead of XML, and built for mobile apps, single-page web applications, and APIs. They are constantly conflated, and the single most useful thing this chapter can give you is the precise distinction:

OAuth 2.0 is an authorization framework — a standard for delegated authorization. It lets a user grant one application limited access to their resources held by another service, without sharing their password. The canonical example: you let a scheduling app read your calendar. You do not give the scheduling app your Google password; instead, OAuth issues the scheduling app a scoped, revocable access token that says "the bearer may read this user's calendar, nothing else, until it expires." OAuth answers the question "what is this app allowed to do on the user's behalf?" — it is about access, about authorization, about scopes and tokens. It was never designed to tell an application who the user is; people misused it for login anyway, which is exactly why the next protocol exists.

OpenID Connect (OIDC) is a thin identity layer built on top of OAuth 2.0 that standardizes authentication — proving who the user is. It reuses OAuth's flows and adds one crucial artifact: the ID token, a signed JSON Web Token (JWT) that asserts the user's identity (who they are, when they authenticated, which IdP vouched). OIDC is what powers "Sign in with Google / Microsoft / Apple" and modern enterprise SSO to web and mobile applications. The mnemonic to burn in:

  • OAuth 2.0 → authorization ("this app may access your calendar"). The token is an access token; the question is what may it do?
  • OIDC → authentication ("this is Jordan, who logged in at 1:02 p.m."). The token is an ID token (a JWT); the question is who is this?
  • SAML → authentication + federation, in XML, for enterprise apps. Older, heavier, signature-based; still dominant in corporate SaaS SSO.

A decoded OIDC ID token (the JWT payload — illustrative) makes the identity claim concrete:

{
  "iss": "https://login.meridianbank.example/",   // issuer: which IdP vouches
  "sub": "a1b2c3d4-EXAMPLE-user-id",              // subject: a stable user identifier
  "aud": "client-id-of-the-app",                  // audience: which app this token is for
  "exp": 1781787731,                              // expires (Unix time) — short-lived
  "iat": 1781784131,                              // issued-at
  "email": "loanofficer3@meridianbank.example",
  "groups": ["Loan-Officers"]
}

The claims do the same security jobs as the SAML assertion's fields, in JSON: iss is the issuer, aud binds the token to one application, exp enforces a short lifetime, and the IdP's signature (over the whole JWT) proves authenticity. Same defensive checklist, different syntax — verify the signature, enforce the audience, honor the expiry.

⚠️ Common Pitfall: Using a raw OAuth access token as proof of identity. An access token says what the bearer may do; it does not reliably say who the user is, and apps that infer identity from an OAuth token (rather than an OIDC ID token verified for the correct audience) have been tricked into logging one user in as another — the classic "confused deputy" and token-substitution problems. If you are building or integrating login, use OIDC and validate the ID token's aud and signature; do not roll authentication out of bare OAuth. This is also a frequent exam discriminator: OAuth is authorization, OIDC is authentication.

🔗 Connection: Notice how everything in this section reduces to signed, short-lived, audience-bound tokens issued by a trusted identity provider after authentication. That is the same primitive that the cryptography you learned in Chapter 4 (digital signatures binding identity to a key) makes possible, and it is the foundation that zero trust (Chapter 32) generalizes: every request carries a verifiable, fresh proof of identity, and resources make access decisions on that proof rather than on network location. Federation tokens are the connective tissue of the post-perimeter world.

🔄 Check Your Understanding: 1. State, in one sentence each, the primary job of SAML, OAuth 2.0, and OIDC. Which two are about who you are, and which one is about what an app may do on your behalf? 2. In the SAML flow (Figure 18.2), does the user ever send their password to the service provider (the app)? Why is that a security advantage?

Answers

  1. SAML: authentication + federation between an IdP and an SP, using signed XML assertions (who you are). OIDC: authentication on top of OAuth, using a signed ID token / JWT (who you are). OAuth 2.0: delegated authorization, issuing scoped access tokens (what an app may do on your behalf). SAML and OIDC are about identity; OAuth is about delegated access. 2. No — the user authenticates only to the IdP; the SP receives a signed assertion, never the password. The advantage: the application never handles or stores the credential, so a breach of the app cannot leak passwords, MFA is enforced centrally at the IdP, and disabling the one IdP identity cuts off every federated app at once.

18.4 Joiner-Mover-Leaver and provisioning

We have the directory (who exists) and federation (how they prove it and reach apps). Now the lifecycle that keeps the directory true: how an identity is born, how it changes, and — the part that failed for Meridian's contractor — how it dies. The framework is joiner-mover-leaver, abbreviated JML, and it is the spine of identity administration. The principle is simple and the failure modes are where breaches live.

A joiner is a new person — a hire, a contractor, an intern. When they join, identity must be provisioned: an account created in the directory, an email mailbox stood up, and access granted to the applications and groups appropriate to their role. Provisioning is the creation and configuration of accounts and their access; deprovisioning is the removal of them. Done well, provisioning is driven by the authoritative system of record for that population — for employees, the HR system (HRIS), which knows on day one who was hired, into what role, in what department, starting when. The HR record is the trigger: when HR marks a new hire as active, automation creates the identity and grants the baseline access for their role. This is birthright access — the set of entitlements every member of a role gets automatically (every teller gets the teller application and the branch mailbox), derived from the role engineering you did in Chapter 17. Birthright provisioning is both efficient and safer than manual, because it is consistent, logged, and least-privilege by design: people get exactly the role's baseline, not whatever a busy manager copied from the last person's account.

A mover is a person who changes roles — a promotion, a transfer, a new project. Movers are the quiet killers of least privilege, because of one specific failure: privilege creep (which you met in Chapter 17), the accumulation of access over time as people gain new entitlements for new roles but never lose the old ones. The teller who becomes a loan officer needs loan-system access; they no longer need teller access — but if the mover process only adds and never removes, after a few moves an employee holds the combined access of every role they have ever had. Over years, a long-tenured employee can become more dangerous than an external attacker, holding the keys to half the organization, none of it currently justified. A correct mover process reconciles access against the new role: grant what the new role needs, revoke what the old role no longer justifies. This is also where segregation of duties (SoD, Chapter 17) is enforced or violated — a mover who keeps the ability to initiate wire transfers and gains the ability to approve them now holds a toxic combination that lets one person commit fraud unchecked.

A leaver is a person who departs — quits, is terminated, or, for a contractor, reaches the end of an engagement. This is the most security-critical transition and the most commonly botched, and it is exactly what failed at Meridian. When someone leaves, every account and every entitlement must be deprovisioned — promptly, completely, everywhere. "Promptly" matters because the window between a person leaving and their access being removed is a window of pure risk: a terminated employee with a grievance, or an attacker who phishes the credentials of someone the organization no longer monitors, has a live, trusted identity. "Completely" matters because a person has identities in many places — AD, Entra ID, SaaS apps that may not be wired to SSO, VPN, building access, a personal mobile device with cached corporate tokens. "Everywhere" is the hard part: the leaver process must reach every system the person touched, and the systems that are not integrated with central provisioning are the ones that get missed.

Here is the lifecycle, with the data flow that makes it automatic — and the gap that makes it fail:

   SYSTEM OF RECORD (HR/HRIS)         IDENTITY GOVERNANCE / IdP            TARGET SYSTEMS
   (authoritative for employees)      (Entra ID + provisioning engine)    (apps, AD, SaaS, VPN)
        │                                     │                                  │
   JOINER: HR marks "Active" ───trigger──────►│  create identity, assign        │
        │                                     │  birthright access by role ─────►│  account + baseline
        │                                     │  (via SCIM where supported)      │  groups created
        │                                     │                                  │
   MOVER: HR changes dept/role ──trigger─────►│  RE-EVALUATE access:            │
        │                                     │  +grant new-role access,        │
        │                                     │  -REVOKE old-role access ───────►│  entitlements
        │                                     │  (prevents privilege creep)      │  reconciled
        │                                     │                                  │
   LEAVER: HR marks "Terminated"─trigger─────►│  DISABLE identity immediately,  │
        │                                     │  revoke all tokens/sessions, ───►│  account DISABLED
        │                                     │  deprovision everywhere          │  everywhere it reaches
        │                                     │                                  │
        │                                     │     ⚠ THE GAP: any target NOT    │
   CONTRACTOR: engagement ends...             │     wired to this pipeline (a    │
   ...but contractors often live OUTSIDE      │     SaaS app, an AD account a    │
   the HR system → NO trigger fires ──────────X  contractor got manually) is    │  ← CONTRACTOR_X
                                              │     NEVER told to deprovision    │    survives here

Figure 18.3 — The joiner-mover-leaver lifecycle driven by the HR system of record. Automation makes each transition consistent and logged. The gap (bottom) is precisely Meridian's failure: contractors were not in the HR system, so no leaver trigger ever fired for them, and any system reached by a manual, non-integrated account never heard that the person was gone.

The automation that connects the provisioning engine to target systems is, increasingly, a standard protocol: SCIM (the System for Cross-domain Identity Management), an open standard for automatically provisioning and deprovisioning identities across systems via a simple REST/JSON API. When Meridian's IdP supports SCIM and a SaaS application supports SCIM, the IdP can push account creations, updates, and — critically — deletions/disables to that application automatically. A new hire's account appears in the SaaS app the moment HR activates them; a leaver's account is disabled in that app the moment HR terminates them. SCIM is how "disable them everywhere" becomes real instead of aspirational, because it turns deprovisioning from forty manual tickets into one automated event that fans out. The applications not connected by SCIM (or some equivalent automation) are the ones that accumulate orphans.

🛡️ Defender's Lens: The leaver event is the single highest-value automation in identity security, and the contractor population is its biggest blind spot. Attackers and malicious insiders specifically prey on the deprovisioning gap: leaked-credential databases are full of valid enterprise logins for people who left, and the accounts that survive are disproportionately for contractors, vendors, and service accounts that live outside the HR-driven pipeline. The defensive moves: (1) make every population — including contractors — have an authoritative system of record that fires a leaver trigger (even a simple contractor roster with mandatory end dates); (2) set account expiration dates on contractor accounts at creation, so they die automatically even if no one remembers (a control that would have killed CONTRACTOR_X on schedule); (3) integrate as many targets as possible via SCIM so deprovisioning fans out automatically; and (4) for the unavoidable manual remainder, run the access reviews of §18.5 to catch what the pipeline misses. Defense in depth applies to deprovisioning: assume the trigger will sometimes fail, and have a review that catches the survivors.

📟 War Story: A constructed but representative incident. A regional firm offboarded a database administrator after a tense departure. HR closed his email and badge the same afternoon, and everyone considered it handled. Six weeks later, customer data appeared on a criminal forum. The investigation found the cause: the DBA had a separate, manually created account on a cloud database that was never wired to the HR-driven leaver process. His employee identity was gone; that one account was not, and he had used it — or sold it — to reach the data after leaving. No firewall was breached and no exploit was used. A single un-deprovisioned credential, living outside the lifecycle automation, was the entire breach. The fix was not a new product; it was making the leaver process complete: an inventory of every system holding accounts, and a review to confirm each terminated person was gone from all of them.

🔄 Check Your Understanding: 1. Define joiner, mover, and leaver, and name the specific security failure most associated with the mover transition. 2. Why is setting an expiration date on a contractor account at the moment it is created a stronger control than relying on someone to remember to disable it when the engagement ends?

Answers

  1. Joiner: a new person who must be provisioned with an account and birthright access. Mover: a person who changes roles and whose access must be reconciled. Leaver: a departing person whose access must be fully deprovisioned. The mover failure is privilege creep — access accumulates because the process adds new-role entitlements without revoking old-role ones (and can also create toxic segregation-of-duties combinations). 2. An expiration date is a fail-safe default (Chapter 3): the account dies automatically on a known date with no human action required, so it closes even when the leaver process is forgotten — exactly the failure mode that left the Meridian contractor active. Relying on someone to remember is a process that fails silently; an expiration date fails closed.

18.5 Access reviews and orphaned accounts

The lifecycle automation of §18.4 is the prevention. This section is the detection and correction — the governance half of IGA that assumes, correctly, that the automation will sometimes fail and that access drifts even when every process runs. Two practices do the work: access certification and the active hunt for accounts that should not exist.

Access certification — also called an access review or attestation — is the periodic process in which someone with authority reviews who has access to what and explicitly confirms (certifies) that each grant is still appropriate, or flags it for removal. The reviewer is usually the manager (who should know what their people need) or the application/resource owner (who knows what the entitlement confers), and the cadence is typically quarterly for sensitive access and at least annually for everything, with extra reviews triggered by events like a department reorganization. The output is a decision per grant: keep (this access is still justified) or revoke (remove it). Access certification is not optional theater; it is a hard requirement of major compliance regimes — SOX requires periodic access reviews of financial systems, PCI-DSS requires reviews of access to the cardholder data environment, and GLBA and FFIEC expect them for a bank like Meridian — and it is the control that would have caught the contractor even though the leaver automation missed him, because a review of the loan-approval group asks, account by account, "should this person still be here?" and the honest answer for CONTRACTOR_X was plainly no.

⚠️ Common Pitfall: "Rubber-stamp" certifications. The most common way access reviews fail is that managers, faced with a long list and a deadline, click "approve all" without actually reading it — converting a real control into a compliance fiction that produces an audit artifact and zero security. Signs you have this problem: reviews completed suspiciously fast, near-100% "keep" rates, and managers certifying access to systems they have never heard of. The defenses are to make reviews reviewable — show the manager plain-language descriptions of what each entitlement actually allows (not cryptic group names), highlight the risky and anomalous grants for scrutiny (access nobody else in the role has; access that creates a segregation-of-duties conflict; access not used in 90 days), keep the lists short by reviewing high-risk access more often than everything, and track and act on the revocations so a "revoke" decision actually removes the access. A certification that does not result in removals is not catching anything.

An orphaned account is an account that no longer has a valid owner or business purpose — most classically, an account belonging to a person who has left the organization (like the contractor), but also accounts for systems that were decommissioned, service accounts for applications no longer running, and duplicate accounts a person accumulated and abandoned. Orphaned accounts are dangerous out of all proportion to their number, because they combine three properties an attacker prizes: they are valid (they authenticate successfully, so they defeat the front door), they are unmonitored (nobody is watching an account for a person who left, so misuse raises no eyebrows), and they are often privileged or well-connected (they accumulated access during the person's tenure and never lost it). An orphaned account is a pre-positioned foothold inside your perimeter, and finding them is one of the highest-value, lowest-cost activities in identity security.

How do you find an orphaned account? You reconcile two lists: the list of accounts that exist (from the directory — AD and Entra ID) against the list of people who should have accounts (from the systems of record — HR for employees, the contractor roster, the application inventory for service accounts). Any account in the directory that does not correspond to an active, authorized person or purpose is a candidate orphan. The same reconciliation, run on entitlements rather than accounts, finds over-privileged access: compare each person's actual entitlements against the baseline for their current role, and the difference is privilege creep awaiting cleanup. This reconciliation is exactly what we automate in this chapter's bluekit checkpoint, because it is the kind of repetitive, large-scale cross-referencing that humans do badly and code does perfectly. Three complementary signals make the hunt sharper:

  • No corresponding HR/roster record — the account exists but the person does not (or never did). This is the strongest orphan signal.
  • Stale activity — the account has not authenticated in 90 or 180 days. A long-dormant account is either unused (and should be disabled on the principle that unused access is pure risk) or used only rarely by something you should identify. Disable-after-inactivity is a powerful automatic control.
  • No owner / no purpose — especially for service accounts (Chapter 20): if no human or team will claim an account and explain what it is for, it should not exist.

🛡️ Defender's Lens: Tie the hunt to the kill chain you learned in Chapter 2. Orphaned and over-privileged accounts are the engine of lateral movement and privilege escalation — the middle of nearly every breach. An attacker who gains an initial foothold (a phished credential, a compromised laptop) does not usually find the crown jewels on the first machine; they survive and spread by harvesting and reusing other credentials, and a forgotten over-privileged account is the perfect vehicle: valid, trusted, and reaching far. This is why identity hygiene is not paperwork — every orphaned account you disable and every excess entitlement you strip is a rung removed from the attacker's ladder. In the SOC (Part V), authentication from a long-dormant account, or a single account suddenly touching systems across many departments, is a high-fidelity detection precisely because good governance should have made those accounts rare.

A worked access-review report makes the whole practice concrete. Suppose Meridian runs a quarterly certification of the Loan-Approvers group — the very group the audit flagged. The reviewer (the lending manager) is handed not a raw list of usernames but an enriched, decision-ready report:

ACCESS REVIEW — Group: Loan-Approvers  (entitlement: approve wire disbursements)
Reviewer: Lending Manager        Period: Q2 2026        Generated: 2026-06-14
Reconciled directory members against HR + contractor roster + last-login telemetry.

  USER              HR/ROSTER STATUS     LAST LOGIN   FLAG                 DECISION
  ----------------  -------------------  -----------  -------------------  --------
  loanofficer3      Active (Lending)     2026-06-14   ok                   KEEP
  loanofficer7      Active (Lending)     2026-06-13   ok                   KEEP
  smitchell         Active (MOVED→Ops)   2026-06-10   role mismatch        REVOKE
  rkhan             Active (MOVED→Ops)   2025-11-02   role mismatch+stale  REVOKE
  dvargas           TERMINATED 2026-03   2026-03-29   ORPHAN (ex-employee) REVOKE
  pwozniak          TERMINATED 2026-01   2026-01-15   ORPHAN (ex-employee) REVOKE
  contractor_x      NOT IN ANY ROSTER    2025-07-20   ORPHAN (contractor)  REVOKE
  tellerlead2       Active (Branch)      2026-06-12   SoD: also INITIATES  REVOKE
  ----------------  -------------------  -----------  -------------------  --------
  41 members reviewed | 33 KEEP | 8 REVOKE  (2 orphan ex-employees, 1 orphan
  contractor, 2 role-mismatch movers, 1 SoD toxic combination, +2 similar)

ACTION: 8 entitlements removed; contractor_x + 2 ex-employee ACCOUNTS disabled
        in source AD; SoD conflict (tellerlead2) escalated to fraud review.

Figure 18.4 — An access-review report enriched for decision-making. The reviewer is not guessing: each row carries the person's HR status, last login, and an automatically computed flag. The eight problems — two terminated employees, an orphaned contractor, two movers carrying old access, and a segregation-of-duties violation (a teller who can both initiate and approve disbursements) — are surfaced for the reviewer rather than buried in a flat list. This is what turns certification from rubber-stamp into control.

Notice that this single report exercises every concept in the chapter. The orphaned contractor is found by reconciling against the roster (§18.4's gap, caught by §18.5's review). The two movers carrying loan-approval access into Operations are privilege creep (§18.4). tellerlead2 is a segregation-of-duties violation (Chapter 17) — one person who can both initiate and approve a wire, which is precisely the fraud-enabling toxic combination banks exist to prevent. And the corrective action disables the orphans at the source directory (§18.2's hybrid lesson) so they cannot resurrect on the next sync. The report is the chapter, applied.

🧩 Try It in the Lab: In your own environment (a personal Microsoft 365 developer tenant, a lab AD, or even just the list of apps connected to your personal Google/Microsoft account), perform a tiny access review. List every third-party app and service that can access your account, and for each ask the §18.5 questions: do I still use this? does it need the access it has? when did I last touch it? Revoke everything that fails. You have just run, in miniature, the exact reconciliation a security team runs across an enterprise — and you will almost certainly find an orphan.

🔄 Check Your Understanding: 1. Why is an orphaned account more dangerous than its raw count suggests? Name the three properties that make it valuable to an attacker. 2. An access certification of a sensitive group comes back with a 100% "keep" rate, completed by every manager within an hour of being assigned. Why should this worry you rather than reassure you, and name two changes that would make the review more meaningful?

Answers

  1. Because each orphaned account combines three attacker-friendly properties: it is valid (authenticates successfully, defeating the front door), it is unmonitored (no one watches an account for someone who left, so misuse is invisible), and it is often privileged or well-connected (it accumulated access during the owner's tenure and never lost it). One forgotten account is a pre-positioned foothold. 2. A near-instant, 100%-keep review is the signature of rubber-stamping — managers approving without reading — which produces an audit artifact but catches nothing. Improvements: show plain-language descriptions of what each entitlement allows and automatically flag risky/anomalous/stale grants for scrutiny; shorten lists by reviewing high-risk access more frequently; and track-and-enforce revocations so decisions actually remove access. (Any two.)

18.6 Meridian's identity cleanup

Pull the chapter together the way Meridian's team did, because the bank's eight-week identity-governance project is the program increment this chapter contributes and the model for the work you will do in your own career. After the audit surfaced the orphaned contractor in the loan-approval group, CISO Dana Okafor did not buy a product first. She did what the discipline demands: she had Sam Whitfield (the engineer) and Elena Vasquez (the GRC analyst) establish ground truth, then build the prevention and the detection together.

Week 1–2: Reconcile and find the orphans. Sam exported every account from on-prem Active Directory and from Entra ID and reconciled the combined list against the HR system's roster of active employees and a hastily assembled (and overdue) contractor roster. The reconciliation — the same logic as this chapter's idgov.py — found the damage: 1,847 enabled AD accounts against 1,792 active employees and 140 known-current contractors, leaving roughly 80 accounts with no corresponding active person. Most were stale: employees who had left over the prior two years whose accounts had been disabled in some systems but not all, plus a long tail of contractors like CONTRACTOR_X whose engagements had ended with no leaver trigger because contractors had never been in any authoritative system. Cross-referencing last-login telemetry sharpened the list: a dozen of the orphans had authenticated in the last 90 days — meaning they were not merely dormant but in use, the most urgent category, since something or someone was actively logging into accounts that should not exist.

Week 3–4: Remediate at the source and reconcile entitlements. The orphaned accounts were disabled — deliberately disabled, not deleted, and disabled in on-prem AD (the authoritative source) so the change would propagate to Entra ID rather than be overwritten by the next sync (the §18.2 lesson, learned the right way). Disabling rather than deleting preserves the account for forensic investigation (Chapter 25) — if an orphan had been misused, its history is evidence — and allows recovery if a disable turns out to be a mistake. In parallel, Elena ran the first real entitlement reconciliation on the bank's most sensitive groups, starting with anything touching wire transfers and the cardholder data environment, producing reports like Figure 18.4. The wire-approval group alone shed eight members; the broader sweep stripped hundreds of creped entitlements from long-tenured movers and surfaced four segregation-of-duties conflicts that went to fraud review.

Week 5–6: Close the gap that created the problem. Finding orphans is detection; preventing the next one is the real fix. Sam and Elena addressed the root cause — the missing leaver trigger for contractors — with a layered set of controls, because a single fix would itself eventually fail (defense in depth applied to a process):

  • A system of record for contractors. Every contractor now has a record in an authoritative roster with a mandatory engagement end date. The roster fires leaver triggers just as HR does for employees, so contractor departures now flow into the same deprovisioning pipeline.
  • Mandatory account expiration. Every contractor (and temporary) account is now created in AD with an expiration date matching the engagement end date. Even if every human forgets, the account dies on schedule — a fail-safe default that makes CONTRACTOR_X's eleven-month survival structurally impossible.
  • Automated deprovisioning via SCIM to the SaaS applications that supported it, so a leaver event fans out to those apps automatically instead of waiting on tickets.
  • Disable-after-inactivity. Any account with no successful login for 90 days is automatically flagged and, after a grace period and notification, disabled — a safety net that catches whatever the other controls miss.

Week 7–8: Make it recurring and provable. Elena established a quarterly access-certification cycle for high-risk entitlements (wire approval, the CDE, domain admin) and an annual review for everything else, with the reports enriched as in Figure 18.4 so managers certify meaningfully rather than rubber-stamp. The whole effort was documented as Meridian's identity governance (IGA) process — the program artifact for this chapter — and folded into the security program Dana is assembling for the board (Chapter 38). The before-and-after was the kind of result a CISO can present without flinching: roughly 80 orphaned accounts eliminated, contractor offboarding moved from "hope someone files a ticket" to "automatic and reviewed," and the specific finding the auditor raised — the contractor in the wire-approval group — not merely fixed but rendered impossible to recur.

🔗 Connection: This cleanup is the direct payoff of the risk Meridian wrote down in its very first risk register in Chapter 1: R2 — "orphaned/over-privileged account enables lateral movement," scored 15 (CRITICAL). You watched it get identified as a risk in Chapter 1, understood the access models behind it in Chapter 17, and have now seen it driven down with concrete controls in Chapter 18. That is the program maturing exactly as designed — a risk named early, then systematically retired chapter by chapter. The residual risk that remains (a contractor roster that is itself maintained by humans and could fall out of date; SaaS apps that still resist SCIM) is honestly acknowledged and handed to the ongoing certification cycle and to the privileged-access controls of Chapter 19.

Project Checkpoint

This chapter contributes the identity governance (IGA) process to Meridian's security program and the idgov.py module to bluekit. Together they let the bank find orphaned accounts and run access reviews repeatably — turning the eight-week cleanup of §18.6 into a standing capability.

Program increment — the IGA process. You will add a one-to-two-page Identity Governance section to Meridian's program document, defining: the systems of record (HR for employees, a contractor roster with mandatory end dates, the application inventory for service accounts); the JML lifecycle and how each transition is triggered and automated (birthright provisioning on join, entitlement reconciliation on move, full deprovisioning on leave, with mandatory expiration on contractor accounts); the access-certification cadence (quarterly for high-risk entitlements, annual for the rest, enriched for meaningful review); and the orphaned-account hunt (periodic reconciliation of directory against systems of record, plus disable-after-inactivity). The template is in Appendix I; this section sits between the access-control policy (Chapter 17) and the PAM standard (Chapter 19) in the program.

bluekit increment — idgov.py. We turn §18.5's reconciliation into the toolkit's identity-governance module. As always, the code is illustrative and is never executed during authoring — the expected output is hand-traced in a comment.

# bluekit/idgov.py  — Chapter 18 increment
"""Identity governance: find orphaned accounts and review access grants.

orphan_accounts() reconciles directory users against the HR/roster source of
truth (the core §18.5 hunt). access_review() flags grants for certification.
Illustrative only; not executed during authoring.
"""

def orphan_accounts(users, hr):
    """Return enabled directory users with no active record in the source of truth.

    users: list of dicts {"name", "enabled"}.  hr: set of names of active people.
    """
    return [u["name"] for u in users
            if u["enabled"] and u["name"] not in hr]


def access_review(grants):
    """Tag each access grant KEEP or REVOKE for a certification report.

    grants: list of dicts {"user", "active", "role_ok"}.
    Revoke if the user is not active (orphan) OR the grant mismatches their role.
    """
    report = []
    for g in grants:
        revoke = (not g["active"]) or (not g["role_ok"])
        report.append((g["user"], "REVOKE" if revoke else "KEEP"))
    return report


if __name__ == "__main__":
    users = [{"name": "loanofficer3", "enabled": True},
             {"name": "contractor_x", "enabled": True},   # gone, never disabled
             {"name": "pwozniak",     "enabled": True}]    # terminated ex-employee
    hr = {"loanofficer3", "loanofficer7"}                  # active people only
    print("orphans:", orphan_accounts(users, hr))

    grants = [{"user": "loanofficer3", "active": True,  "role_ok": True},
              {"user": "rkhan",        "active": True,  "role_ok": False},  # moved
              {"user": "contractor_x", "active": False, "role_ok": False}]  # orphan
    for user, decision in access_review(grants):
        print(f"{decision:6s} {user}")

# Expected output:
# orphans: ['contractor_x', 'pwozniak']
# KEEP   loanofficer3
# REVOKE rkhan
# REVOKE contractor_x

Trace it by hand to see the discipline of §18.5 encoded. orphan_accounts walks the directory users and keeps only those that are enabled yet absent from the HR set — contractor_x and pwozniak are both enabled but not active people, so both surface; loanofficer3 is in HR, so it does not. access_review revokes any grant where the user is inactive or the grant does not match their current role — catching rkhan (a mover whose role no longer justifies the grant) and contractor_x (an orphan), while keeping loanofficer3. Eighteen lines of logic reproduce the two findings that took the bank an audit to discover — which is the point: governance at scale is reconciliation, and reconciliation is exactly what code does well. You have written the engine of Meridian's identity hygiene.

Summary

This chapter built the discipline of governing identity across its whole lifecycle at scale.

  • An IAM program (identity governance and administration, IGA) is the organization-wide capability for managing the full lifecycle of identities and their access, and for proving the right people have the right access for the right reasons. It combines administration (the lifecycle), authentication (Chapter 16, often via SSO), and governance (reviews and certification). It is distinct from Chapter 15's cloud IAM, which is one technical mechanism the program governs.
  • A directory service is the source of truth for identity. LDAP is the protocol; Active Directory is Microsoft's on-prem directory (LDAP + Kerberos + Group Policy, organized into domains/OUs, guarded by domain controllers — the most-targeted system in the enterprise); Entra ID is the cloud identity service for SaaS and the web. Most enterprises run a hybrid sync; know which directory is authoritative and disable accounts at the source.
  • Single sign-on (SSO) authenticates a user once and reaches many apps, concentrating both control (central MFA, one place to disable) and risk (protect the IdP). Federation extends SSO across organizational boundaries via a pre-established trust, so an app trusts your IdP's say-so without ever seeing the user's password.
  • SAML = authentication + federation in signed XML assertions, dominant in enterprise SaaS SSO. OAuth 2.0 = delegated authorization (scoped access tokens — what an app may do). OIDC = authentication layered on OAuth, using a signed ID token / JWT — who the user is. The defensive checklist is identical across them: verify the signature, enforce the audience, honor the short expiry; never infer identity from a bare OAuth access token.
  • The joiner-mover-leaver (JML) lifecycle keeps the directory true: provision birthright access on join; reconcile (grant new, revoke old) on move to stop privilege creep and SoD conflicts; fully deprovision on leave. SCIM automates provisioning/deprovisioning across systems so "disable everywhere" is real. The leaver event is the highest-value automation; contractors are its biggest blind spot — give them a system of record and a mandatory account-expiration date.
  • Access certification (access review) is the periodic, authoritative confirmation that each access grant is still appropriate — a hard requirement of SOX, PCI-DSS, and GLBA, and the control that catches what JML automation misses. Beware rubber-stamping; make reviews reviewable and act on the revocations.
  • An orphaned account (no valid owner/purpose) is dangerous out of proportion to its number — valid, unmonitored, and well-connected — and the engine of lateral movement and privilege escalation. Find orphans by reconciling the directory against the systems of record, sharpened by stale-activity and no-owner signals; this chapter's idgov.py automates exactly that.

Spaced Review

Retrieval from this chapter and the two before it. Answer without scrolling up.

  1. (Ch.17) Distinguish authentication from authorization in one sentence each, and say which one SSO primarily delivers and which one RBAC primarily delivers.
  2. (Ch.17) What is a segregation-of-duties (toxic) combination, and which row of the access-review report in Figure 18.4 was an example of one?
  3. (Ch.16) SSO concentrates authentication at the identity provider. Why does that make phishing-resistant MFA (a FIDO2 security key) on the IdP login especially valuable — and how does it connect to the control that saved Meridian in Chapter 1?
  4. (Ch.18) State the one-sentence difference between OAuth 2.0 and OIDC.
  5. (Ch.16) A leaked-credential database contains a valid username and password for a person who left the bank a year ago. Which two controls from this chapter would have prevented that credential from still working, and which Chapter 16 control would blunt the password even if the account were still active?
Answers 1. Authentication proves *who you are*; authorization decides *what you may do*. SSO primarily delivers authentication (one proof of identity, reused across apps); RBAC primarily delivers authorization (access by role). 2. A segregation-of-duties / toxic combination is a set of entitlements that, held by one person, lets them complete a sensitive action with no second party (enabling fraud or error) — e.g., the ability to both *initiate* and *approve* a wire transfer. In Figure 18.4 it was `tellerlead2`, who could both initiate and approve disbursements. 3. Because the IdP is the single point that grants access to everything downstream, the IdP login is the highest-value target; phishing-resistant MFA (FIDO2/WebAuthn) makes that login impossible to phish, so even a stolen password yields nothing — exactly the control that defeated the attacker in Chapter 1, now protecting *every* federated app at once instead of just one portal. 4. OAuth 2.0 is delegated *authorization* (scoped access tokens — what an app may do on your behalf); OIDC is *authentication* layered on OAuth (a signed ID token proving who the user is). 5. The leaver/deprovisioning automation and a mandatory account-expiration date would each have disabled the account so the credential no longer works (and an access certification would have caught it); even if the account were still active, the Chapter 16 control of phishing-resistant MFA would mean the stolen password alone could not complete a login.

What's Next

You have governed the whole population of identities — created them, federated them, reviewed them, and disabled the ones that should not exist. But a small subset of those identities is categorically more dangerous than the rest: the privileged accounts that can change the directory itself, take over a domain controller, or move money. An orphaned teller account is a problem; an orphaned domain-admin account is a catastrophe. Chapter 19 turns to privileged access management — vaulting and rotating the keys to the kingdom, granting admin rights just-in-time instead of standing, recording privileged sessions, and tiering administration so that compromising one admin does not compromise everything. The governance you built here is the foundation; privileged access is where you apply it with the most force, because that is where the attacker most wants to be.