Windows Autopilot

Supercharge the Hybrid Azure AD Join device registration process

I’ve written a few blogs about Hybrid Azure AD Join, and I’ve explained that there are two major pieces to this:

  • What Windows Autopilot and Intune do to orchestrate the process of getting a new device joined to Active Directory.  You can read more about that process in this blog post, and more troubleshooting details can be found here.
  • What happens in the background after the device is joined to Active Directory to complete the Hybrid Azure AD Join device registration process.  You can read more about that process here.

Certainly those two pieces intersect, especially if you want to leverage user ESP or anything else that requires actually communicating with an Azure AD-secured service (e.g. Intune, Teams, OneDrive for Business, Outlook, Conditional Access) using the user’s Azure AD credentials.  The key problem is how long it takes for the background Hybrid Azure AD Join device registration process.  If you’re using ADFS (and you have the needed claims rules defined – if you don’t, it behaves just like the non-ADFS scenario), this process is pretty quick.  But if you aren’t using ADFS (e.g. you have a managed Azure AD tenant, synced with AAD Connect, leveraging passthrough or password hash authentication), this process can take up to 30 minutes, since that’s the frequency of the AAD Connect sync process that synchronizes the newly-created AD computer object for a device into Azure AD.

But that process can be sped up:  AAD Connect includes a PowerShell cmdlet that can initial a delta sync at any time.  You can monitor the OU or container where your new devices are added in Active Directory, and initiate a delta sync when you see changes have been made (e.g. new device added).  Steve Prentice has published an example script on GitHub:

The script is called SyncNewAutopilotComputersAndUsersToAAD.ps1 and can be set up to run as a scheduled task on the server in your environment running AAD Connect.  Customize it as needed for your environment, e.g. by specifying the OU to monitor (I used “CN=Computers,DC=contosocm,DC=com” to match my AD environment) and the time period (default of five minutes).  Schedule it to run on that time period (again, every five minutes).

That’s the first piece of the puzzle, getting the device object into Azure AD.  But as you may have noticed in my Hybrid Azure AD Join blog, there are more steps that the device needs to complete even after that happens – and those steps require connectivity because the device needs to talk to Active Directory to find the SCP (to know what AAD tenant to communicate with) and to update the userCertificate property on the AD computer object.  Once those are done, there’s a scheduled task on the device called “Automatic-Device-Join” that completes the device registration process, so it’s good to actively “encourage” that task to run.  By default, it runs any time a user signs into Windows, as well as once after each time the device reboots (at a variable time, depending on the Windows 10 release), but it can be started at any time – and assuming the device has been synced from AD to AAD (after the userCertificate property has been updated), it should cause the device registration to quickly complete.

That brings us to script #2 from the same GitHub location.  The WaitForUserDeviceRegistration.ps1 script can be deployed as a Win32 app, triggering the scheduled task, checking if the device is registered, and repeating as necessary.  This can handle two main scenarios:

  • The device is on the corporate network, so it has connectivity to the AD domain controller.
  • The device is configured with an auto-connecting VPN configuration prior to this app running, establishing connectivity.

There’s one scenario that won’t work:

  • The device is configured with a VPN configuration that requires the user to initiate the connection from the Windows logon screen.  (Since this app would wait until the registration completes, and the registration can’t complete without connectivity, it would eventually cause a timeout.)

So take that into account.  All you can do in that case is hope that the AAD Connect sync has happened and the triggered Automatic-Device-Join task takes care of the device registration fast enough.  (There is some logic in Autopilot to force the equivalent of an “Add work account” wizard, to have the user re-enter their AAD credentials if they sign on before the Hybrid AADJ process completes, so if you see that prompt, that’s what’s going on.)

Here’s a video showing the end-to-end user-driven Hybrid Azure AD Join process on a VM that is connected to the internet and using an Intune-delivered Always On VPN device tunnel connection (read about that setup here and here) to establish connectivity to the corporate network:

At the end, I executed the Get-AutopilotDiagnostics.ps1 script (described here) which I’ve enhance to show key Hybrid Azure AD device registration events:


So you can see the provisioning process started at 00:25:33, completed the AD join (ODJ) process at 00:26:50, had corporate network connectivity by 00:27:40, and had finished the Hybrid Azure AD Join device registration at 00:31:41.  So, it took about six minutes to complete that process.  The entire device ESP process completed at 00:39:10 when Office finished installing.  User ESP then took about a few minutes after the user signed in, finishing up at 00:48:22.  So the complete provisioning process took just under 23 minutes to complete everything.  That’s not too shabby overall.  (Prior to doing all of this, I had disabled user ESP via a custom OMA-URI policy, so I had to undo that just to try this.)

Note that I did have to make a slight change to the RenameComputer script that I published to GitHub to ensure that it forces a reboot after the rename is completed.  This avoids an interesting problem:  The scheduled task on the AAD Connect server could run and sync the renamed AD computer object, while the device hasn’t yet been rebooted.  Since the RenameComputer script did a soft reboot (return code 3010), the reboot would happen after device ESP completed – severely delayed by the WaitForUserDeviceRegistration script that can’t coax the device registration to complete because the device can’t find itself in AAD using the old name.  Ugh.  But by changing the RenameComputer script to do a hard reboot (return code 1641), that problem is avoided.

It’s also worth noting that Intune Management Extensions (Sidecar) runs apps in the order that they were created/assigned, so the new WaitForUserDeviceRegistration app ran last, found that the device registration was already complete, and exited fairly quickly.  But if it would have run earlier, it could have introduced a delay.  That’s not a big deal overall.  Worst case, it might add a few minutes to the process.

There’s one other enhancement in the Get-AutopilotDiagnostics script that would be good to mention too:


I added Delivery Optimization statistics, showing the percentage of downloads (at least those that use Delivery Optimization:  Office, Intune Win32 apps, Microsoft Store apps, Windows updates) that pulled from a Connected Cache server.  It shows 49%, which sounds respectable, but that’s also showing a deceptive “total bytes” number of 2.8GB, when I know that the actual download size was only 1.4GB.  So it should have been 98%.  I’m still debating that oddity (which doesn’t happen all the time – some machines do properly show 1.4GB downloads instead of 2.8GB) with the Delivery Optimization team.

Also, think about that number:  The device is connected via Always On VPN.  So how did it get to the Connected Cache server (running on a ConfigMgr DP on my private network)?  It did it over the Always On VPN connection.  That’s no big deal in this lab environment (the networks are just separate virtual switches on my Hyper-V server, so they are actually well-connected), but in the “real world” you might want to block access to the Connected Cache server over the VPN connection and have the devices get content from the internet directly instead (assuming you are using split tunneling, which I would highly recommend).

Categories: Windows Autopilot

9 replies »

  1. Very helpful article, thanks!
    It’s actually the first time I read about the point that Autopilot forces the user to re-enter the AAD credentials for the scheduled taks to finish the Hybrid AD join. I always wondered why I get another prompt and thought that this might be a wrongly configured conditional access policy or something about the Intune enrollment.
    Is this anywhere else described in the docs?

    Also on my Hybrid AD over VPN testing, from looking into the User Device Registration log in the event viewer when the machine is waiting for the Hybrid AD join to finish, it looks like the Automatic-Device-Join scheduled task is running every 5 minutes to check if the machine has been synced already and only then asks to provide the logon credentials again when the machine has been synced.
    From what you wrote, I would understand the task only runs once whenever a user logs on or a device has been rebooted?


    • I haven’t seen the prompting behavior documented, but will look at adding that somewhere. The Autopilot-Device-Join task on the Windows 10 2004 device is definitely not running every 5 minutes; it’s being triggered by logon of any user (including SYSTEM and defaultUser0, so during OOBE) as well as by the starting of the Workstation service (after each reboot). Prior to Windows 10 2004, the Workstation service would wait five minutes; with Windows 10 2004, that timing is randomized so it can be much longer.


  2. Deleted a device from Intune that was BYOD enrolled. This locked the user out of the device and they can no longer log in. Tried running the Get-WindowsAutoPilotInfo.ps1 but that requires powershell, which you cannot do from Windows boot options. So I tried opening up a CMD shell and running the script from there, but I cannot run the script anyways without administrator privileges

    It got stuck on this row:
    C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Unrestricted -Command Enable-PSRemoting -SkipNetworkProfileCheck -Force

    It says I need admin so I’m stuck.

    Restarted and failsafe mode and that created a local account on the machine.

    So my question is, how can you enroll a device again if I’ve deleted the device from Intune…

    Were also using Jamf Pro with Macs and I can say right away that the ease of use and management of devices is so easy that anyone can do it. With Intune I guess you have to read each of your blog posts and be a certified MS technician..


    • My idea was to upload the device hash to Intune (as it was a company owned device anyways). But without formatting the drive I can never get to the installation screen to run the script, which a hassle (unless there is some other way I don’t know of). Then my plan was to assign the user to the device and hopefully authenticate sucessfully into the locked profile.

      What ticks me off is that the user wasn’t given any option to create a local account. Neither any explanation as to what is wrong when trying to sign in.

      Is there any communication at all internally at MS?


    • If you deleted it from Intune, the device will not know that. I don’t know if there is a simple way to solve that, short of resetting the device and starting over. If that’s not an acceptable answer, open a support case via the Intune “Help and support” node.


  3. I’m trying to use the your Autopilot Branding app to implement my Start Layout, but the Company Portal won’t get pinned. Is there a way to get that pinned that I can’t figure out? I assume it’s due to it being a UWP app, but I was hoping there’s a trick to still have it pinned. I’ve read it works when using the Start Menu config profile setting, but not the copy-paste method used by your app. Thanks.


  4. Hi Michael

    How many devices an intune administrator can enroll? I see DEM 1000 and user according device enrollement restrictions. I guess that Global admin and Intune admin without DEM are just like “normal” user with the limits in policy, right?



    • Hi Dan… feel free to ignore / remove that bit.. we had a use case where we wanted a faster sync of new users from AD to AAD if they were in a particular OU so it just dealt with that… nothing to do with autopilot in this blog’s scenario though, so you can ignore it. 🙂