Enrolling Windows Devices into Intune – A definitive guide

There are many ways to enrol Windows devices into Intune, each works slightly differently and some work better than others depending on your situation. This post aims to run through each, how to use them and when to use them. We all know how often the Entra and Intune portals change so if you are hitting this page and things have moved, drop a message below and I’ll update!

Pre-Reqs

Let’s start with the pre-requisites before attempting any enrollments:

User licensing

Your users need to have an Intune license which can be found in (amongst others):
EMS E3, Business Premium, M365 E3, E5, A3, A5, F3, F5. This is a valuable resource for licensing: https://m365maps.com/

MDM Enrollment scopes

Within Entra, click “Show More”, Expand Settings and click Mobility:

Click on Microsoft.Intune

Make sure the MDM scope it set to either All, or Some and the group selected contains the users enrolling devices. If the boxes below are blank, click the restore text

You can also do this via Graph:

##Get policies
$policiesuri = "https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies"
$policies = getallpagination -url $policiesuri
#$policies = (Invoke-RestMethod -Method GET -Uri $policiesuri -UseBasicParsing -Headers @{Authorization = "Bearer $($Tokenresponse.access_token)"}).value

##If only one, convert to array
if ($policies -isnot [System.Collections.ArrayList]) {
    $policies = @($policies)
}

foreach ($policy in $policies) {
    $policyid = $policy.Id
    $json = @"
    {
        "appliesTo":  "all"
    }
"@
    $uri = "https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/$policyid"
    Invoke-MgGraphRequest -Method PATCH -Uri $uri -Body $json -ContentType "application/json"
}

MDM is set to Intune

This is more for really old tenants, but worth checking. Sometimes the MDM is set to O365 so will block device enrollment. It’s an easy fix, but needs digging into Graph:

After connecting to Graph, this script will check the MDM provider and fix if needed:

write-output "Getting Organisation ID"
$OrgId = (Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/organization" -Method Get -OutputType PSObject).value.id
write-output "Org ID is $orgid"
    #Check if Intune already is MDM Authority
write-output "Checking if Intune is MDM"
 $mdmAuth = (Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/beta/organization('$OrgId')?`$select=mobiledevicemanagementauthority" -Method Get -OutputType PSObject).mobileDeviceManagementAuthority
 #Sets Intune as MDM Authority if not already set
 write-output "MDMAuth is $mdmAuth"
 if($mdmAuth -notlike "intune")
  {
  write-output "Setting MDM org to Intune"
  Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/organization/$OrgID/setMobileDeviceManagementAuthority" -Method POST
 write-output "MDM set"
 } 

Enrollment Restrictions

Within Intune, just check Corporate devices are allowed (and ideally block personal devices although that will break some options below):

Devices – Enrollment – Device Platform Restriction.
Edit the default All Users policy

Or via Graph:

Write-Output "Getting Device Restrictions Policy ID"
$policyid = (((Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/beta/deviceManagement/deviceEnrollmentConfigurations?`$filter=priority eq 0" -OutputType PSObject).value) | where-object '@odata.type' -eq "#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration").id
Write-Output "Policy ID: $policyid"

##Set URL
$url = "https://graph.microsoft.com/beta/deviceManagement/deviceEnrollmentConfigurations/$policyid"


##Populate JSON
$json = @"
{
	"@odata.type": "#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration",
	"androidForWorkRestriction": {
		"blockedManufacturers": [],
		"osMaximumVersion": "",
		"osMinimumVersion": "",
		"personalDeviceEnrollmentBlocked": true,
		"platformBlocked": false
	},
	"androidRestriction": {
		"blockedManufacturers": [],
		"osMaximumVersion": "",
		"osMinimumVersion": "",
		"personalDeviceEnrollmentBlocked": false,
		"platformBlocked": true
	},
	"macOSRestriction": {
		"blockedManufacturers": [],
		"osMaximumVersion": null,
		"osMinimumVersion": null,
		"personalDeviceEnrollmentBlocked": true,
		"platformBlocked": false
	},
	"windowsHomeSkuRestriction": {
		"blockedManufacturers": [],
		"osMaximumVersion": null,
		"osMinimumVersion": null,
		"personalDeviceEnrollmentBlocked": true,
		"platformBlocked": false
	},
	"windowsRestriction": {
		"blockedManufacturers": [],
		"osMaximumVersion": "",
		"osMinimumVersion": "",
		"personalDeviceEnrollmentBlocked": true,
		"platformBlocked": false
	}
}
"@

##Update Policy
write-output "Updating Device Restrictions Policy"
Invoke-MgGraphRequest -Uri $url -Method PATCH -Body $json -ContentType "application/json"
Write-Output "Device Restrictions Policy updated"

Now we can start looking at enrollment

GPO

If your devices are currently domain joined, this is the easiest way to get them into Intune (and Autopilot)

Simply create a new GPO and set this:

Computer Configuration > Administrative Templates > Windows Components > MDM > Enable automatic MDM enrollment using default Microsoft Entra credentials.

Convert Existing Devices

If you also want these devices to show in Autopilot Devices, in your Autopilot Profile, assign to all devices and set “Convert all targeted devices to Autopilot” to Yes:

This method adds devices to Intune and Autopilot but doesn’t give them admin rights or anything unusual. I usually suggest creating an OU with Inheritence Disabled to avoid any clashes between GPOs and Intune Policies.

More importantly, no device wipe is needed.

Further info: https://learn.microsoft.com/en-us/windows/client-management/enroll-a-windows-10-device-automatically-using-group-policy

Autopilot – Online and CSV

This is probably the most used approach to enrol devices into Intune via Autopilot during OOBE and is done by enrolling the device hash into the Autopilot service. Then when the device is wiped, during OOBE, it checks in and applies Intune policies etc. as per your ESP.

Starting with the quicker online method, this can be run either interactively, or if your enrolling staff do not have permissions, can be used with an Entra App reg:

set-executionpolicy Unrestricted
install-script get-windowsautopilotinfocommunity

get-windowsautopilotinfocommunity.ps1 -online -tenantID xxx -AppID xxx -AppSecret xxx

Optionally you can add “-assign” to wait for assignment to complete and “-sysprep” to kick off a sysprep and re-enrol when complete (amongst other option)

Alternatively, you can run the script to extract the hash into CSV format to then add manually into Autopilot:

set-executionpolicy Unrestricted
install-script get-windowsautopilotinfocommunity

get-windowsautopilotinfocommunity.ps1 -outputfile c:\temp\autopilot.csv

In Intune, navigate to Devices – Enrollment – Autopilot Devices

Click Import

Upload the CSV file

This is an excellent way to add new devices, or rebuild existing devices to cloud native Entra Joined. You have full control over the device and it follows your profile and ESP.

If you want an Entra group to target Autopilot enrolled devices, use this device query:

(device.devicePhysicalIDs -any (_ -startswith "[ZTDid]"))

Further information:

https://learn.microsoft.com/en-us/autopilot/add-devices

Autopilot Device Prep

Known in the community as Autopilot v2, it makes the enrollment easier for the user, but is a little more tricky to configure.

NOTE: If a device is enrolled into Autopilot with device hash (or convert existing devices), this will win over Device Prep so you’ll need to remove the device from Autopilot Devices first.

The first thing we need to do is create an Entra group with a specific application set as the owner. This is what Autopilot users to populate devices into the group (no more ztid dynamic group needed)

Create a new static assigned group with whatever name you choose:

Click Owners

Search for this ID: “f1346770-5b25-470b-88bd-d5744ab7952c” which should find “Intune Autopilot ConfidentialClient”:

If it doesn’t, run this script:

$spid = "f1346770-5b25-470b-88bd-d5744ab7952c"
write-output "Checking if Enterprise App exists"
$lookforsp = get-mgserviceprincipal -filter "AppID eq '$spid'"

if (!$lookforsp) {
    write-output "Enterprise App does not exist, creating"
    $ServicePrincipalId = @{
        "AppId" = "$spid"
    }
   $appregid = New-MgServicePrincipal -BodyParameter $ServicePrincipalId
    write-output "Enterprise App created"
}

We also need a second User group which allows users to enrol devices. This can be static or dynamic and called anything as long as it is a user group as it’s pre-device.

Now in Intune click Devices – Enrollment – Device Preparation Policies

Create a new profile and after filling in the basic details, select the device group we created earlier (with the owner)

The Configuration Settings are the new ESP, set which scripts and apps MUST be available before a user logs in and any other required settings (please don’t make them admins)

When you reach assignments, select the user group created which holds the users allowed to enrol.

Technically this is all you need BUT you will need to allow Personal Device enrollment which is always risky. Therefore, we can add device details so Autopilot knows it’s a corporate device, similar to the hash, but simpler.

We can grab the details with a one-liner and output to a CSV (source)

(Get-CimInstance Win32_ComputerSystem).Manufacturer+','+(Get-CimInstance Win32_ComputerSystem).Model+','+(Get-CimInstance Win32_BIOS).SerialNumber

Or you can use the same script as for v1 and either add directly online, or export to csv:

set-executionpolicy Unrestricted
install-script get-windowsautopilotinfocommunity

get-windowsautopilotinfocommunity.ps1 -online -identifier

Offline:

set-executionpolicy Unrestricted
install-script get-windowsautopilotinfocommunity

get-windowsautopilotinfocommunity.ps1 -identifier -outputfile c:\temp\device.csv

Then in the Intune portal, navigate to Devices – Enrollment and click the Corporate Device Identifiers tab:

Click Add – Upload CSV file and in the drop-down select “Manufacturer, Model and Serial number (windows only)”

That’s it, now simply enrol via OOBE and away you go.

There are currently some limitations though to device prep:

  • Windows 11 only
  • Entra ID join only (not a bad thing)
  • No pre-provisioning
  • No kiosk style self-deployment
  • No grouptags

More info:

https://learn.microsoft.com/en-us/autopilot/device-preparation/overview

Provisioning Package

What about a non-domain joined device where you don’t want to wipe and reload? There are some options for that, they aren’t quite as fluid, but they are still an option.

The first is to deploy a provisioning package to devices. For this you will need Windows Configuration Designer from the ADK to create a package.

Rather than re-write the whole process, there is an end-to-end process here:

https://techcommunity.microsoft.com/t5/intune-customer-success/bulk-join-a-windows-device-to-azure-ad-and-microsoft-endpoint/ba-p/2381400

It’s worth noting that an administrator will need to run the package on each machine so it will need some effort on the IT side and if they had admin rights before, they will still have them afterwards (you can remove with an Intune policy). You’re obviously also inheriting any of the previous rubbish left on the device. It works in a pinch, but isn’t ideal.

As with GPO, you will probably then want to convert these to Autopilot devices so you don’t have to do this again.

PS Script

If you have RMM access to these devices, you can deploy a PowerShell script to enrol them into Intune.

Fortunately Rudy has saved me a job here and written a selection of scripts which you can find here:

Running this script in the system context will sort the enrollment:

# Set MDM Enrollment URL's
$key = 'SYSTEM\CurrentControlSet\Control\CloudDomainJoin\TenantInfo\*'

try{
    $keyinfo = Get-Item "HKLM:\$key"
}
catch{
    Write-Host "Tenant ID is not found!"
    exit 1001
}

$url = $keyinfo.name
$url = $url.Split("\")[-1]
$path = "HKLM:\SYSTEM\CurrentControlSet\Control\CloudDomainJoin\TenantInfo\$url"
if(!(Test-Path $path)){
    Write-Host "KEY $path not found!"
    exit 1001
}else{
    try{
        Get-ItemProperty $path -Name MdmEnrollmentUrl
    }
    catch{
        Write_Host "MDM Enrollment registry keys not found. Registering now..."
        New-ItemProperty -LiteralPath $path -Name 'MdmEnrollmentUrl' -Value 'https://enrollment.manage.microsoft.com/enrollmentserver/discovery.svc' -PropertyType String -Force -ea SilentlyContinue;
        New-ItemProperty -LiteralPath $path -Name 'MdmTermsOfUseUrl' -Value 'https://portal.manage.microsoft.com/TermsofUse.aspx' -PropertyType String -Force -ea SilentlyContinue;
        New-ItemProperty -LiteralPath $path -Name 'MdmComplianceUrl' -Value 'https://portal.manage.microsoft.com/?portalAction=Compliance' -PropertyType String -Force -ea SilentlyContinue;
    }
    finally{
    # Trigger AutoEnroll with the deviceenroller
        try{
            C:\Windows\system32\deviceenroller.exe /c /AutoEnrollMDM
            Write-Host "Device is performing the MDM enrollment!"
           exit 0
        }
        catch{
            Write-Host "Something went wrong (C:\Windows\system32\deviceenroller.exe)"
           exit 1001          
        }

    }
}
exit 0

The same catches apply as with the provisioning package, it isn’t a clean build and you need to watch for any lingering admin rights. The devices will also need to already be listed in Entra, but that usually happens when they sign into M365 apps.

Work or School

Users can navigate to Settings – Accounts – Access Work or School – Connect

It technically works, but devices will be registered as personal and if you have that blocked your users will get this error:

Not to mention expecting your users to fill in the settings properly…

Probably best avoided

Company Portal

For this you’ll need to somehow deploy the Company Portal MS Store app, tell the users to sign in and make sure this box is ticked:

As with the method above, you will need Personal Devices enabled and they will enrol as personal and not corporate so you’ll need to change them within Intune. They’ll also retain admin settings and anything else on the device.

When signing into M365 apps

When signing into M365 apps, your users could tick the box to Allow my organisation to manage my device (the same as when installing company portal), but the same applies, you’ll need to unblock personal device enrollment which means they could sign in to these apps from any device and enrol into the tenant.

I’ve looked at these options here:

JSON

This used to be an excellent approach for use with MDT or SCCM. You could create a JSON containing the Autopilot details and inject during the task sequence which would add the device for you automatically.

Sadly it was discovered that anyone could easily create the JSON and enrol non-managed devices into a tenant so to avoid this issue, to use JSON injection you need to allow Personal Devices to be enrolled. It isn’t ideal, but it does still work.

To generate the JSON use this command:

$graphApiVersion = "beta"
$Resource = "deviceManagement/windowsAutopilotDeploymentProfiles"

$uri = "https://graph.microsoft.com/$graphApiVersion/$Resource"
$response = Invoke-MGGraphRequest -Uri $uri -Method Get -OutputType PSObject

    $profiles = $response.value

    $profilesNextLink = $response."@odata.nextLink"

    while ($null -ne $profilesNextLink) {
        $profilesResponse = (Invoke-MGGraphRequest -Uri $profilesNextLink -Method Get -outputType PSObject)
        $profilesNextLink = $profilesResponse."@odata.nextLink"
        $profiles += $profilesResponse.value
    }

    $selectedprofile = $profiles | out-gridview -passthru -title "Select a profile"

Make a note of the ID and export it with this:

        $graphApiVersion = "beta"
    $Resource = "deviceManagement/windowsAutopilotDeploymentProfiles"

$uri = "https://graph.microsoft.com/$graphApiVersion/$Resource/$id"
$approfile = Invoke-MGGraphRequest -Uri $uri -Method Get -OutputType PSObject

I have a tool here to automatically create an ISO with the JSON injected:

You can also use the excellent OSDCloud for this:

https://www.osdcloud.com

More information:

https://learn.microsoft.com/en-us/autopilot/existing-devices

Conclusion

There is no “best” approach, it is whatever suits your environment. Ideally a fresh start with Autopilot (v1 or 2), but if that isn’t an option, GPO or PS Script depending on domain join status are perfectly acceptable options.

Hopefully this has been useful, if I’ve missed anything, add it in the comments below

5 thoughts on “Enrolling Windows Devices into Intune – A definitive guide”

      • I second this. During the OOBE the user just presses cntrl + shift + D and the serial Number, manufacturer and model is all presented for them to pass to the IT manager to update Intune corporate identifiers. Just performed this process today, for an employee and it worked.

        Unfortunately, I had to also add the steps of upgrading to win 11 pro and updating via the CMD line before it could work. but should be less of an issue as device prep becomes more mainstream and assuming they buy laptops already set to win 11 pro or above.

        Reply

Leave a Comment