it · level 1

Directory Services & User Lifecycle

Users, groups, OUs — and the specific order you offboard someone to avoid leaving a hole.

150 XP

Directory Services & User Lifecycle

Every company with more than a handful of employees runs a directory service — the single source of truth for who exists, what they can touch, and whether their account can sign in right now. Everything downstream (email, laptop login, the VPN, the ticket system, every SaaS app wired to SSO) trusts what the directory says.

Analogy

Think of a corporate badge system. HR prints you a badge on your first day. The badge opens certain doors depending on which team-access lists you're on. If you lose the badge, security disables it first (the badge still exists, but the scanners reject it). Only later does someone physically shred the badge. No one has ever, in the history of badges, done the shredding first — because the badge's ID is stamped on the sign-in sheets for the last six months of visits and you need that trail to stay intact.

A directory service is that badge system, but for every piece of software the company owns.

The user object model

A user in a directory is a structured record. The names differ by product, but the shape rhymes:

Field What it is Example
login Short, globally unique handle (sAMAccountName, UPN, principal) alice
display name Human-readable form Alice Alvarez
organizational unit (OU) Where the user lives in the org tree — used for policy inheritance ou=engineering
groups Permission bundles the user belongs to [eng-all, prod-deploy, vpn-users]
enabled flag Can this account authenticate right now? true or false
last sign-in When did this account last actually authenticate? 2026-04-22

The user object is metadata about a human; the enabled flag is the single toggle that decides whether the laptop login screen, the VPN, and the SSO provider all accept them. That toggle is the most important switch in the whole system.

Groups vs OUs

New IT folks blur these two; they are not the same thing.

  • An OU (organizational unit) is a tree node. It models where the person fits in the company: ou=engineering/ou=backend. Policies and delegated admin rights inherit down the tree. A user has exactly one OU.
  • A group is a permission bundle. prod-deploy is a group; being in it lets you push to production. A user can be in many groups, and groups have nothing to do with where the user lives in the OU tree.

The rule of thumb: OU answers "where do they report?"; group answers "what can they do?"

The lifecycle

Every user moves through the same states:

  (none)  --create-->  enabled  --disable-->  disabled  --delete-->  (none)
                          ^                      |
                          +--------enable--------+

Short, neat, and deceptively simple. The question is which order you walk it when someone leaves.

Why "disable" always precedes "delete"

Delete looks like the clean move. It's not. The moment you delete the row:

  • Federated apps (SSO-connected SaaS) may keep serving the user for minutes or hours — their session tokens are still valid, their OAuth refresh tokens still work, and each SaaS provider pulls identity updates on its own schedule. A disabled account is rejected immediately on the next auth check; a deleted account becomes a dangling session no one can revoke cleanly.
  • Audit trails break. Logs that reference alice now point at a ghost. Forensic investigations, compliance reviews, and "who pushed this change" queries all degrade.
  • Ticket and change-request history loses its author. Every requested_by = alice field becomes a dangling reference.
  • Accidental same-name recreation inherits nothing and everything. If a new hire named Alice Alvarado gets the login alice three months later, she does not inherit the old Alice's permissions — but she does inherit every artifact that ever mentioned the login, which is its own mess.

Disable first, wait, then delete. In practice "wait" is measured in weeks to months depending on policy.

The full offboarding sequence

There are four steps, and the order is not negotiable:

  1. Disable the account. The account still exists; auth now fails.
  2. Revoke group memberships. This shrinks the blast radius if disable is ever reversed — no one should silently re-inherit prod-deploy if the account is re-enabled for a data-retrieval reason next week.
  3. Revoke active sessions. Even with the account disabled, existing session tokens may still be valid. Kill them explicitly (e.g. Revoke-AzureADUserAllRefreshToken, okta-admin users:clear-user-sessions).
  4. Delete — only after the first three have landed and the grace period has elapsed.

Skip step 3 and a logged-in laptop can keep reaching Slack and Drive for hours. Skip step 2 and a same-name hire inherits ghosts. Skip step 1 and — well, they can still log in.

Stale account detection

A stale account is an enabled account that hasn't authenticated in a long time. The exact threshold is a policy choice (90 days is typical; 30 days for privileged accounts). Stale accounts are a ripe attack surface:

  • They are exactly the accounts nobody is watching.
  • They tend to retain old groups long after the person's role changed.
  • Service accounts and contractor accounts often become stale and stay that way.

Accounts with no sign-in at all are treated as stale too — freshly created accounts that were never used should be reviewed.

Find them with a filter on lastLogonTimestamp (AD), signInActivity.lastSignInDateTime (Entra ID), or lastLogin (Okta). Then: disable first, ask questions later.

Real products

The abstraction above maps onto every major directory. A one-liner each:

Product Disable a user
Active Directory (PowerShell) Disable-ADAccount -Identity alice
Microsoft Entra ID (Graph) Update-MgUser -UserId alice@corp.com -AccountEnabled:$false
Okta (CLI) okta-admin users deactivate alice
Google Workspace (GAM) gam update user alice@corp.com suspended on
JumpCloud (API) POST /api/systemusers/{id} { "suspended": true }

Creation is mirrored: New-ADUser, New-MgUser, okta-admin users create, gam create user .... Stale detection is Search-ADAccount -AccountInactive, a Graph filter on signInActivity, Okta's /api/v1/users?filter=status eq "STAGED", or gam report users.

Learn the shape once; the shape is the same everywhere.

Playground

The playground on this page is a simulated directory CLI. Type dir user list to see the seed directory, then walk a user through the lifecycle. Every command you run shows the real-product equivalent on hover — the abstraction is shared; the tooling varies.

Visualizer

The visualizer draws the directory as a tree: OUs as rectangles, users as pills coloured by their state (active, disabled, stale). Click a user to see their group memberships edge out to the group boxes — a visual reminder that group membership is a graph, not a tree.