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