Classic Windows Autopilot has one structural weakness that everyone who has run it at scale has felt: the device has to be known before it can be provisioned. You collect a hardware hash, upload it, wait for the Autopilot service to materialize a device object, assign a profile, and only then does OOBE behave. That registration dependency is the source of most “the laptop isn’t picking up the profile” tickets – a stale hash, an OEM upload that never landed, a device reset before the object synced.
Autopilot device preparation (Autopilot v2) removes the registration step. No hardware hash, no Autopilot device object, no profile-to-device assignment race. The device is steered entirely by Entra group membership and an Intune policy evaluated after the user authenticates. This guide stands up that experience for Entra-joined devices, maps the new status screen against the classic Enrollment Status Page (ESP), and lays out a coexistence and migration plan so you can move rings off hardware-hash Autopilot without a flag day.
Scope note: device preparation supports Entra join and user-driven provisioning. There is no self-deploying / pre-provisioning (white glove) mode and no Hybrid Entra join. If you need either, classic Autopilot stays in the picture – see the migration section.
1. Device preparation vs original Autopilot: registration-free provisioning
The mental model shift is the whole point, so pin it down before touching the portal.
| Dimension | Classic Autopilot | Device preparation (v2) |
|---|---|---|
| Device identity | Hardware hash uploaded ahead of time | None – no hash, no pre-registration |
| What targets the device | Autopilot profile assigned to the device object | Provisioning policy assigned to a device security group |
| When config is decided | At OOBE, from the pre-staged profile | After user sign-in, the device is auto-added to the group |
| OOBE gate | Enrollment Status Page (ESP) | Provisioning status experience (device + account phase) |
| Join types | Entra join, Hybrid join, self-deploying, pre-provision | Entra join, user-driven only |
| Failure granularity | ESP blocks on app/profile failures | Time-boxed phases with explicit pass/fail and a 1-time retry |
The sequence is: user powers on, picks region/keyboard, signs in with their work account, and the device is automatically added to a designated security group. Intune sees the membership, hands down the provisioning policy, installs the targeted app and script set inside a fixed time budget, and shows a progress UI. Nothing is keyed to the serial number, so “did the profile reach this serial” never matters.
That auto-add is the load-bearing mechanism: the policy nominates a security group, and during provisioning the device object is dropped into it so the rest of Intune targeting resolves. Get the group wrong and nothing works, so we build it first.
2. Prerequisites: provisioning policy, device security group, and Graph permissions
You need the following in place. None are exotic, but the group and the role assignment trip people up.
- Licensing: Intune Plan 1 plus Entra ID (the same Microsoft 365 E3/E5 or standalone Intune entitlement you already use for MDM).
- Automatic MDM enrollment scoped to the users who will provision: Entra admin center -> Devices -> Mobile (MDM) -> Microsoft Intune -> MDM user scope = All (or a group).
- An assigned, security-enabled Entra group that the provisioning policy will populate. It must be a direct-membership group, not dynamic – the platform adds device objects to it during provisioning, and dynamic membership rules will fight that.
- Permission to add devices to that group. This is the subtle one. The Intune service principal needs ownership of the group so it can add devices to it. In the device preparation policy wizard, Intune offers to set itself as owner of the chosen group; accept it, or add the
Intune Provisioning Clientservice principal as a group owner yourself. - Enrollment device limit headroom and a device platform restriction that permits Windows for these users.
The tenant-side configuration is reachable through Microsoft Graph (beta). The least-privilege application permissions for the enrollment-time policies and targeted apps are:
DeviceManagementConfiguration.ReadWrite.All # policies / settings
DeviceManagementServiceConfig.ReadWrite.All # enrollment configuration
DeviceManagementApps.ReadWrite.All # app assignments
Group.ReadWrite.All # manage the provisioning group + ownership
Create the group up front and capture its object ID – you will reference it in the policy and in diagnostics:
Connect-MgGraph -Scopes "Group.ReadWrite.All"
$grp = New-MgGroup -DisplayName "AP-DevicePrep-Ring0" `
-MailEnabled:$false -MailNickname "ap-deviceprep-ring0" `
-SecurityEnabled:$true `
-Description "Devices auto-added during Autopilot device preparation (Ring 0)"
$grp.Id # record this object ID
3. Building the device preparation policy: app and script payload and timeout budget
The policy lives in the Intune admin center under Devices -> Windows -> Enrollment -> Windows Autopilot -> Device preparation policies (the wizard is titled “Create a device preparation policy”). It has a small, deliberate surface.
Deployment settings
- Deployment mode: Supervised (locked-down, IT-driven) or Standard. Supervised increases the security posture of the provisioning session; use it unless you have a reason not to.
- Join type: Microsoft Entra join.
- Account type: Standard User or Administrator. Default to Standard User – making the primary user a local admin is a posture decision, not a default.
Configuration
- Allow non-failure restart attempts before timing out: how many extra reboots the platform tolerates during provisioning without declaring failure.
- Timeout for the apps/scripts phase. The key design constraint: this is a fixed budget, not “install everything no matter how long it takes.” Anything not finished inside the budget fails the phase. The default is generous (on the order of an hour), but you size it to your payload, not the other way around.
- Allowed apps and allowed scripts: the explicit list of Win32 / Microsoft Store apps and PowerShell scripts that must complete during provisioning.
This is the most important operational difference from the classic ESP: you nominate an exact app and script set, by name, in the policy, and the provisioning experience tracks that specific list to completion – not a blocking app count.
The corollary is a hard rule:
Every app and script you list in the policy must also be assigned (to the device group, as Required) and added to the policy’s allowed list. Listing without assigning means the device waits on something that will never arrive; assigning without listing means it installs later but does not gate provisioning. Both ends must agree.
Keep the provisioning payload minimal – the security agent, the management/compliance baseline tooling, and at most one or two genuinely day-one applications. Office, line-of-business apps, and anything large belong in normal Intune Required assignments that flow in after the desktop is up. A lean payload is the single biggest lever on both provisioning time and success rate. A sane Ring 0 policy is therefore: Supervised, Entra join, Standard User, group AP-DevicePrep-Ring0 (Intune as owner), a 60-minute timeout, and an allowed list of just the EDR agent plus one Set-Baseline.ps1.
Assign the policy itself to a user group (the people who will provision). The device group is the one the policy populates – do not confuse the two assignments.
4. The provisioning status experience and how it differs from the classic ESP
After sign-in, device preparation shows a status UI with three named stages. It looks like the ESP but behaves differently:
- Security – the device sets up its managed identity and security posture.
- Device preparation – it joins, enrolls, lands the provisioning policy, and is added to the security group.
- Device setup – the allowed apps and scripts install within the timeout budget.
Differences that matter operationally:
- It is time-boxed. The classic ESP can sit “Identifying…” or “Installing apps (3 of 7)” effectively forever if an app never reports. Device preparation declares failure when the budget expires – a definite failure with a retry beats an indefinite spinner.
- No device-vs-user ESP split. Classic Autopilot has a device ESP and a separate user ESP, each with its own blocking-app list and tunables. Device preparation collapses this into one policy-defined list and the staged UI above.
- Explicit allowed set, not a count. The ESP’s “block until N required apps install” is replaced by the named app/script list from section 3.
- One retry on the device. On failure the experience offers a single “Try again” before a hard error – design for the one retry, there is no infinite reset loop.
5. Account-driven user-driven flow and assigning the right app set
Device preparation is a user-driven flow: the corporate identity is established when the user authenticates in OOBE, and that identity triggers group membership, policy delivery, and the primary-user association. There is no no-user scenario – if you need that, you need classic self-deploying mode (see migration).
Implications for how you assign things:
- Provisioning-critical apps -> the device group, Required, and listed in the policy. These gate the status experience. Target the device security group the policy populates.
- Everything else -> normal Required/Available assignments to user or device groups, delivered after the desktop is interactive. This is where Office, browsers, and LOB apps go. They install in the background; they do not extend provisioning.
- Configuration profiles, compliance, Conditional Access apply on the normal MDM cadence. Device preparation does not change how settings catalog, compliance, or CA work – it only governs the provisioning gate.
So: EDR/security agent, compliance prerequisite tooling, and a single day-one baseline script gate provisioning (device group, Required, policy allowed list); Microsoft 365 Apps, browsers, Teams, LOB apps, and printer/drive polish are delivered after via normal Required/Available assignments. If your “minimum viable desktop” requires ten apps before a user can work, that is an organizational decision to revisit – inflating the list inflates the timeout and the failure surface.
6. Failure modes, retry behavior, and reading provisioning diagnostics
Most device preparation failures fall into four buckets:
- Group ownership / auto-add failed. The device authenticated but was never added to the security group, so the policy never targeted it. Cause: the group is dynamic, or Intune/
Intune Provisioning Clientis not an owner. This is the number-one root cause. - An allowed app or script never completed in budget. Either it was listed but not assigned, or it genuinely takes longer than the timeout, or it failed its own detection rule. Same Win32 honesty rules as any Intune deployment apply – detection is the arbiter, not exit code.
- Enrollment restriction or license gap. The user lacks an Intune license, or a device platform restriction blocks Windows enrollment for them.
- Connectivity to the required Autopilot/Intune/Entra endpoints is blocked by a proxy or firewall during OOBE.
When it fails, the experience offers one retry. After that you collect diagnostics. From the failed device:
Shift+F10 # open a command prompt during OOBE
MdmDiagnosticsTool.exe -area Autopilot -cab C:\diag.cab
For the registry-level enrollment state and the autopilot diagnostics page on a booted device:
# Reachable post-OOBE from Settings -> Accounts -> Access work or school
# -> (your account) -> Info, or via the diagnostics export:
Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Provisioning\Diagnostics\Autopilot" -Recurse
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Enrollments\*" |
Select-Object EnrollmentState, ProviderID
Cross-reference with the server side. In the Intune admin center, the provisioning policy has a per-device status; and the standard IME logs on the device carry the app/script truth:
C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\IntuneManagementExtension.log
C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\AppWorkload.log
The triage order that saves the most time: confirm group membership first (did the device land in AP-DevicePrep-Ring0? – see the Verify section for the query), then check whether each allowed app reached “Installed” in AppWorkload.log, and only then chase OOBE networking. Membership and app completion explain the overwhelming majority of cases.
7. Coexistence and migration strategy from hardware-hash Autopilot profiles
You do not rip out classic Autopilot. The two coexist on the same tenant, and the correct migration is ring-based.
They run side by side. A device already registered in classic Autopilot (it has a hardware hash / Autopilot object) and in scope for an assigned classic profile keeps following the classic path on reset. A new or de-registered device with no Autopilot object, whose user is targeted by a device preparation policy, follows the v2 path. Decide which population each governs and avoid ambiguous scope overlap.
Migration order:
- Stand up device preparation for a Ring 0 group (section 2-3) without touching any classic profiles.
- Move new-buy / unregistered devices to v2 first – they have no hardware hash dependency to unwind, so they are the cheapest population to switch.
- Stop uploading new hardware hashes for populations you intend to run on v2; the whole point is to not maintain a hash inventory.
- For already-registered devices, deregistration flips them to the v2 path on next reset. Pull the Autopilot object only after the user/device is in scope for device preparation, so a reset in between does not fall into an unprovisioned gap.
- Keep classic Autopilot for what v2 cannot do: self-deploying (kiosks, Teams Rooms, no-user devices), pre-provisioning / white glove, and Hybrid Entra join – explicit non-goals of device preparation today.
A guarded deregistration, by serial, so a single ring move is auditable:
Connect-MgGraph -Scopes "DeviceManagementServiceConfig.ReadWrite.All"
# Find the classic Autopilot device object by serial, then delete it.
# Deletion removes the v1 registration so the device follows the v2 path on next reset.
$serial = "0123456789"
$apDev = Get-MgBetaDeviceManagementWindowsAutopilotDeviceIdentity -All |
Where-Object { $_.SerialNumber -eq $serial }
if ($apDev) {
Remove-MgBetaDeviceManagementWindowsAutopilotDeviceIdentity `
-WindowsAutopilotDeviceIdentityId $apDev.Id
"Deregistered $serial from classic Autopilot."
} else {
"No classic Autopilot object for $serial -- already v2-eligible."
}
Do not deregister in bulk on day one. Deregistration is the irreversible step; treat each batch as a ring promotion you can point to, not a one-shot cutover.
8. Validation: building a clean test ring before broad rollout
Treat Ring 0 as a real, isolated proof, not a smoke test on your own laptop.
- Dedicated users and a dedicated
AP-DevicePrep-Ring0group. Do not point the policy’s user assignment at a broad group “just to see” – assigned too widely, it starts auto-adding production devices to a security group with downstream targeting effects. - A throwaway VM or spare hardware, reset to OOBE between attempts so you exercise the full sign-in -> auto-add -> install path, not a half state.
- Time the budget honestly. Provision once with the real payload, measure the device-setup phase, and set the timeout from that measurement plus headroom – do not leave it at the default and hope.
- Force the failure cases on purpose. Remove Intune ownership of the group and confirm the auto-add failure; list an app you have not assigned and confirm it hangs the phase to timeout. Knowing each symptom before production is what makes the help desk fast.
- Promote by ring, widening the user and device groups in stages, and only deregister classic objects (section 7) once the corresponding ring is proven.
Enterprise scenario
A platform team running roughly 22,000 Windows endpoints across EMEA + APAC had a chronic classic-Autopilot pain point: their three regional OEM resellers were inconsistent about uploading hardware hashes. Roughly 4-6% of new laptops arrived with no Autopilot object – the device booted into a generic OOBE, the user got a consumer-flavored setup, and the help desk had to wipe and manually re-register. The real cost was that every regional desk maintained its own ad-hoc hash-collection process to paper over the resellers.
The constraint that made a naive “just switch to v2” plan dangerous: the same tenant also provisioned about 900 shared/kiosk devices via classic self-deploying mode, which has no equivalent in device preparation. A blanket cutover would have stranded every kiosk.
The solution was scoped coexistence by device population, not a flag day. They created a dedicated provisioning group and a Supervised, Entra-join, Standard-User policy with a deliberately tiny allowed list – EDR agent plus one baseline script – assigned only to a “new hire / new device” user group. Kiosks stayed entirely on classic self-deploying, untouched, identified by their existing Autopilot group. New corporate laptops were simply not registered with a hardware hash anymore, so they fell to the v2 path by absence; the resellers’ inconsistency stopped mattering because there was nothing for them to get wrong.
Population Path Trigger
-------------------- ------------------ ----------------------------------
New corporate laptop Device prep (v2) No HW hash + user in AP-DevicePrep group
Shared / kiosk Classic self-deploy Existing Autopilot object + group
Already-registered Classic, then v2 Deregister per ring, then v2 on reset
The 4-6% “generic OOBE” failure class went to effectively zero for new buys, because the registration step that used to fail no longer existed – while the kiosk scenario that genuinely needed self-deploying kept working because they did not try to force it onto a mode that cannot do it.
Verify
Run these checks before declaring a ring healthy:
- Provisioning policy status (server side). Intune admin center -> Devices -> Windows -> Enrollment -> Windows Autopilot -> Device preparation policies -> [policy] -> Device status. Every Ring 0 device should show a terminal success, not “in progress.”
- Group auto-add worked. Confirm each provisioned device is a member of the provisioning security group:
Get-MgGroupMember -GroupId "<AP-DevicePrep-Ring0 object id>" -All |
Measure-Object | Select-Object Count
- Allowed apps reached Installed. On a provisioned device, grep the IME log for each app in the policy:
Select-String -Path "C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\AppWorkload.log" `
-Pattern "ApplicationName|Detection|Result" | Select-Object -Last 40
- Enrollment state is healthy.
dsregcmd /statusshowsAzureAdJoined : YESand a validTenantName. - The negative tests fire. With Intune ownership removed from the group, a provisioning attempt should fail at the auto-add stage and surface in
MdmDiagnosticsTool.exe -area Autopilotoutput – not hang silently.