Releases: yusha/Microsoft-365-Offboarding
Release list
v1.10.0
Stronger lockdown and clearer Conditional Access handling
- Legacy mail protocols are now disabled at offboarding (Step 3). In addition to removing ActiveSync partnerships, the tool turns off IMAP, POP, ActiveSync, and authenticated SMTP on the mailbox (
Set-CASMailbox), closing the app-password / basic-auth path even if the account is ever re-enabled. - App-only backdoor review (Step 5). Alongside revoking delegated OAuth grants, the tool now lists any app registrations or service principals the departing user owns - an app with its own secret and application permissions keeps access independent of the user account. These are surfaced (advisory, no automatic deletion) so an admin can remove ownership and rotate credentials.
- Conditional Access on tenants without Entra ID P1 (Step 10). On a tenant that does not include Conditional Access (for example Microsoft 365 Business Standard), the step now reports a clear message - it skips the optional CA policy and notes that disabling the account (Step 2) is the enforcing block - instead of a raw error.
Full Changelog: v1.9.0...v1.10.0
v1.9.0
Accurate screenshots under any terminal
Per-step screenshots could come out one step behind under GPU-rendered terminals (Windows Terminal, VS Code), because classic Windows capture can't read their live content. On Windows the tool now captures with ffmpeg's DXGI Desktop Duplication (ddagrab), which reads the real composited frame — so every screenshot matches its step. When you opt into screenshots and ffmpeg isn't installed, the tool installs it automatically with winget (one-time; falls back to the built-in capture if it can't).
- No more per-step pause — screenshots are captured immediately (the old 2-second "press ENTER" wait is gone).
- Full-screen capture, reliable across multi-monitor, mixed-DPI, and projector setups. Close private windows and keep the terminal maximized.
- Safer for automation — capture is skipped on non-interactive / headless hosts, ffmpeg calls have a hard timeout and never touch stdin, and outputs are validated.
- macOS and Linux desktop capture are unchanged; headless hosts still record a text transcript.
Full Changelog: v1.8.2...v1.9.0
v1.8.2
Fix: accurate screenshots under Windows Terminal (no setup)
Windows Terminal renders on the GPU, and no classic Windows capture method can read its live content, so per-step screenshots came out one step behind. The Run-Offboarding.bat and demo.bat launchers now detect Windows Terminal and automatically relaunch in the classic console host (a separate window opens), where the capture is accurate. Nothing to configure — just run the launcher as usual. Runs already in the console host are unchanged.
Full Changelog: v1.8.1...v1.8.2
v1.8.1
Fix: accurate screenshots under Windows Terminal
Per-step screenshots were one step behind under Windows Terminal because a GDI screen-grab reads a stale composited frame of its GPU rendering. The Windows capture now uses PrintWindow(PW_RENDERFULLCONTENT) on the terminal window, which asks it to render its current content into the capture — so the screenshot matches its step. Falls back to the full-screen grab if PrintWindow is unavailable.
Full Changelog: v1.8.0...v1.8.1
v1.8.0
New: choose how screenshots are captured
- You're now asked up front whether to capture screenshots. If yes, each per-step screenshot is taken automatically ~2 seconds after the step finishes (or press ENTER to grab it sooner) — you don't have to babysit it, and the short pause lets the screen settle, which helps sidestep the Windows Terminal render lag. If no, the run just produces the audit reports (the HTML report leaves out the screenshots section).
- macOS is now supported via the built-in
screencapture(your terminal needs Screen Recording permission in System Settings → Privacy). - Headless / unsupported environments are detected — on Azure Cloud Shell, SSH, or any host with no graphical desktop, the tool tells you screenshots aren't available and continues with the audit reports (plus a text transcript where supported).
Full Changelog: v1.7.3...v1.8.0
v1.7.3
Screenshots under Windows Terminal
A GDI screen-capture of Windows Terminal is structurally about one step behind the actual content — its GPU rendering is asynchronous, and no in-script delay fixes it. So:
- The tool no longer waits an extra 2 seconds per step trying (and failing) to beat it.
- It now detects Windows Terminal and warns once, pointing to the exact fix: set the default terminal to "Windows Console Host" (Terminal Settings → Startup), where the per-step screenshots are exact.
- The
audit.json/AUDIT.md/audit.htmlrecords are built from API results and are exact regardless of the screenshots.
Full Changelog: v1.7.2...v1.7.3
v1.7.2
Tweak
- Per-step screenshot timing on Windows Terminal. The per-step screenshot could capture the previous step's frame because Windows Terminal renders on the GPU asynchronously and its viewport can lag. Before each grab the tool now scrolls the viewport to the cursor (forcing a re-render of the latest output) and waits a bit longer. This is a best-effort improvement — the
audit.json/AUDIT.md/audit.htmlrecords are exact regardless of the screenshots.
Full Changelog: v1.7.1...v1.7.2
v1.7.1
Fix
- The "[M] create it manually" option now works even when the policy can't be read back. Reading a Conditional Access policy needs the same
Policy.ReadWrite.ConditionalAccesspermission that may be missing, so after you created the policy by hand the tool couldn't verify it and looped back to the same menu. It now re-checks once: if it can read the policy it confirms; if reading is denied, it trusts that you created it and continues. Step 10 then just adds the user to the group and no longer tries to recreate the policy.
Full Changelog: v1.7.0...v1.7.1
v1.7.0
Conditional Access is now handled up front
Previously, Step 10 (the Conditional Access sign-in block) could fail at the very END of an offboarding — after the mailbox was already converted to shared and the license removed — if the admin-restricted Policy.ReadWrite.ConditionalAccess permission wasn't consented. That's the worst place for a failure.
Now the CA group + report-only policy are set up as a pre-step, before anything destructive runs. If it can't be set up, you choose while nothing has changed yet:
- [R] Retry the consent prompt (tick "consent on behalf of your organization")
- [M] Manual — create the policy in Entra yourself (steps shown), then re-check
- [C] Continue offboarding without the CA policy (the user still joins the group)
- [A] Abort — stop now and run no offboarding steps
Unattended / automated runs continue without the policy on failure (logged), so they never hang. Step 10 then simply adds the user to the group.
Hardening
- A missing
Group.ReadWrite.All(or a transient error) in the pre-step no longer aborts the whole lockout — the CA block is optional, report-only defense in depth. - The pre-step's group is reused by Step 10, so there's no risk of creating a duplicate same-named group that the policy doesn't target.
- An abort exits cleanly with an audit record instead of a red stack trace.
- The pre-step honors
-WhatIf, and Step 6 no longer removes the user from the offboarded-users group on a re-run.
Full Changelog: v1.6.1...v1.7.0
v1.6.1
Fixes
- The tool now obtains missing permissions itself — no portal step. If a required Microsoft Graph scope isn't in your sign-in token (most often the admin-restricted
Policy.ReadWrite.ConditionalAccessthat Step 10 needs), the tool re-opens the consent window automatically and asks you to consent on behalf of the organization. Just accept the dialog (tick "Consent on behalf of your organization"). - Step 10 no longer fails the whole offboarding. The Conditional Access policy is optional, report-only defense-in-depth. The "Offboarded Users" group membership — the actual mechanism — is always created; if the report-only policy still can't be created, the step records a clear warning with remediation instead of a red failure, so a fully-completed offboarding is reported as successful.
Full Changelog: v1.6.0...v1.6.1