Entra ID Automation #2 The User Lifecycle: Creation, Disabling, and Lifecycle Workflows
Of JML’s three flows, the most frequent is the lifecycle of the user account itself. This part covers handling an account from birth to cleanup with the Graph API, plus the product feature that packages the flow: lifecycle workflows. Code is shown as REST; translating to SDKs was covered in Graph in Practice #3.
Creation: attributes are the fuel of automation #
Creating a user is a single POST /users. What matters is not the call but what you fill in.
POST https://graph.microsoft.com/v1.0/users
Content-Type: application/json
{
"accountEnabled": true,
"displayName": "Avery Kim",
"userPrincipalName": "avery.kim@contoso.com",
"mailNickname": "avery.kim",
"employeeId": "E12345",
"department": "Engineering",
"jobTitle": "Backend Engineer",
"employeeHireDate": "2026-09-15T00:00:00Z",
"passwordProfile": {
"password": "temporary-strong-password",
"forceChangePasswordNextSignIn": true
}
}Do not treat attributes like employeeId, department, and employeeHireDate as “fill in later.” The dynamic groups of the next part compute membership from department, and the lifecycle workflows below trigger off employeeHireDate. Inaccurate attributes make every automation built on them inaccurate. Deciding the source of truth (the HR system) and the notation standards (a canonical department list) is half of the automation design.
For initial credentials there is something better than a temporary password. A Temporary Access Pass (TAP) is a time-limited, one-time code: the new hire signs in with it once and immediately registers passwordless authentication (Authenticator, passkeys). It is the path that retires the emailed-password ritual.
Leavers: block first, delete last #
The offboarding order is fixed by security logic.
- Block immediately: set
accountEnabledtofalse(PATCH /users/{id}). Sign-in stops. - Invalidate sessions:
POST /users/{id}/revokeSignInSessionsrevokes issued refresh tokens. Disabling alone can leave already-signed-in sessions alive until token expiry. - Reclaim access: remove group memberships, licenses, app assignments.
- Handle data: apply retention and transfer policies to the mailbox and OneDrive.
- Delete last:
DELETE /users/{id}is a soft delete — the account sits restorable for 30 days before permanent removal. There is no reason to rush deletion; the standard is deleting a blocked account after a grace period.
The mnemonic is simple: the goal of offboarding is ending access, not erasing the account. Ending access (steps 1〜3) is urgent by the minute; account cleanup (4〜5) follows process at its own pace.
Licenses: direct assignment is the last resort #
Graph has an assignLicense API that attaches licenses to individual users, but the moment per-user assignment enters your automation loop, “who has which license and why” scatters into code. The default strategy is group-based licensing: attach the license to a group, and joining the group assigns it while leaving the group revokes it. User automation’s job then shrinks to “put the person in the right groups,” and the group structure manages the licenses. Details in the next part.
Lifecycle workflows: JML as a product feature #
You can script all of the above yourself — but Entra productized it as Lifecycle Workflows, requiring an Entra ID Governance (or Entra Suite) license.
The structure is simple: trigger (when) + scope (for whom) + tasks (what).
- Joiner example: 7 days before
employeeHireDate→ for new hires in Sales → assign groups, send the manager a TAP, send a welcome mail. - Leaver example: on
employeeLeaveDateTime→ for all employees → disable the account, remove groups and licenses, delete the account days later. - Inactive account cleanup: a sign-in inactivity trigger can automatically disable and delete users idle beyond a set period — turning stale-account audits into a standing process.
Where built-in tasks fall short, custom extensions call Azure Logic Apps to reach external systems (internal portals, ticketing, Slack notifications). The workflows themselves are created and managed through the Graph API (the identityGovernance namespace), so workflow definitions can live in source control and deploy like code.
Choosing between this and DIY: standard JML flows → workflows (if licensed), lower operational burden; organization-specific logic or license constraints → direct Graph implementation. Mixing them — the skeleton on workflows, special steps as custom extensions — is common in practice.
Connecting the source: HR-driven provisioning #
The last piece is “what triggers all this?” The ideal answer is not a person but the HR system. Entra’s HR-driven provisioning integrates with products like Workday and SuccessFactors so that the moment a hire, move, or termination lands in HR, the Entra account and attributes follow. Even without an HR integration, the principle stands: pick a single source of truth for people data and make the directory follow it. If the source is a spreadsheet, then the script that reads that spreadsheet is your provisioning engine — and as a starting point, that is fine.
Summary #
- The heart of user creation is attribute standardization.
department,employeeId, and hire/leave dates are the inputs to dynamic groups and workflows. - Deliver initial credentials via a Temporary Access Pass rather than a temporary password where possible.
- Offboarding order: block (accountEnabled) → revoke sessions → reclaim access → handle data → delete. Deletion is a 30-day soft delete; no rush.
- Group-based licensing is the default; the per-user API is for exceptions.
- Standard JML goes to lifecycle workflows (Governance license); custom logic goes to direct Graph code. And the trigger should be the HR system, not a person.