Granting a user local administrator rights on their Windows 365 Cloud PC used to have exactly one home: User settings. That has now changed. The same capability is available in the newer Cloud PC configurations policy type under Cloud PC Settings, and Microsoft recommends using it for all new local-admin assignments.
Both options produce the same end result – the targeted user becomes a member of the local Administrators group on their own Cloud PC. The differences are in the policy framework: how conflicts are resolved, how settings are expressed, and which one Microsoft is investing in going forward.
Naturally, instead of only clicking through the Intune portal, I wanted to see what the portal actually sends to Microsoft Graph when you create one of these policies – and then reproduce it with PowerShell. So I captured a HAR trace while creating the policy and worked backwards from there.
In this post I’ll cover:
- Why there are now two places to enable local admin
- A few important things to understand
- Cloud PC configurations vs User settings
- What the Intune portal actually sends to Graph (HAR capture)
- Creating the Cloud PC configuration with PowerShell
- Validating the policy – and the overlap I found
- Migrating existing User settings policies
Why are there two places to enable local admin?
Windows 365 has been moving settings that can change after provisioning into the new Cloud PC Settings model. Cloud PC configurations is one template inside that model, alongside capabilities such as AI-enabled Cloud PCs and business continuity / disaster recovery controls.
Local admin is the setting that overlaps both worlds:
- User settings (legacy) – a checkbox, Enable local admin, sitting next to user reset, user-initiated restore and cross-region disaster recovery.
- Cloud PC configurations (new) – a setting called Enable local admin with the values Enabled, Disabled or Not configured.
Existing User settings policies keep working for now, but support for managing local admin through User settings is being phased out. The User settings object itself isn’t going away – it still owns user reset, restore and other user-facing controls.
My mental model: Cloud PC configurations replaces User settings only for the overlapping local-admin capability. It does not make the entire User settings object obsolete.
A few important things to understand
There are several caveats worth highlighting before anyone starts moving local-admin assignments around.
1. User settings is legacy for local admin
Microsoft explicitly recommends Cloud PC configurations for new local-admin assignments and advises migrating existing ones. Nothing breaks today, but I would not build anything new on the User settings checkbox.
2. Disabled is not the same as Not configured
This is the one that will catch people out.
- Enabled – Windows 365 grants the targeted user local-admin rights.
- Disabled – the policy explicitly requires local admin to be off.
- Not configured – the policy doesn’t manage the setting and doesn’t take part in conflict resolution for it.
If you build a Cloud PC configuration purely for another feature (AI-enabled Cloud PCs, for example), leave local admin as Not configured. Set it to Disabled and that policy can now compete with the one that intentionally enables local admin.
Rule of thumb: only touch the settings you mean to manage. Everything else stays Not configured.
3. Conflict resolution works differently
- Cloud PC configurations use a global policy rank. Rank 1 has the highest priority and you can rerank policies. Conflicts are evaluated per configured setting.
- User settings use the older rule – the most recently created policy wins, regardless of which was most recently updated. The other policies are ignored.
4. Both are user-scoped, not device-scoped
Although the permission lands on a Cloud PC, both policies are assigned to user groups. The targeted user becomes admin only on the Cloud PCs assigned to them – not on every Cloud PC in the tenant.
5. Changes apply at sign-in
A user who is already signed in must sign out and sign back in to see the change. Keep that in mind when you validate.
6. This is not just-in-time elevation
Neither method gives task-specific or time-bound elevation. It is persistent local Administrators membership for as long as the policy applies. Use a dedicated group, keep membership to approved exceptions, and consider whether app packaging or endpoint privilege management could meet the need instead.
Cloud PC configurations vs User settings
| Area | Cloud PC configurations | User settings |
|---|---|---|
| Local-admin result | User becomes local admin on their own Cloud PC | Same |
| Recommended for new deployments | Yes | No – legacy for local admin |
| Lifecycle | Current, strategic policy model | Supported for now; local-admin support being phased out |
| Setting values | Enabled / Disabled / Not configured | Checkbox |
| Conflict handling | Policy rank (1 = highest), rerankable | Most recently created policy wins |
| Granularity | Per configured setting; Not configured doesn’t participate | Winning policy used, others ignored |
| Other capabilities | AI-enabled features, BCDR controls | User reset, user-initiated restore, cross-region DR |
| Assignment target | User groups | User groups |
| Scope tags | Supported in the create workflow | Not shown in the create workflow |
| Graph endpoint (beta) | virtualEndpoint/settingProfiles | virtualEndpoint/userSettings |
| Note | – | Doesn’t apply to Windows 365 Flex Cloud PCs in Shared mode |
For most organisations I suspect the end state will be:
Local admin → Cloud PC configurations. Reset, restore and DR → User settings.
What the Intune portal actually sends to Graph
In the Intune admin center I went to:
Devices → Windows 365 → Settings → Create → Cloud PC configurations
Then I set Enable local admin = Enabled, assigned my test user group, left the default scope tag and clicked Create – with the browser developer tools recording a HAR file.

Three Graph calls tell the whole story.
Call 1 – Creating the policy (POST)
POST https://graph.microsoft.com/beta/deviceManagement/virtualEndpoint/settingProfiles
The request body (group ID replaced with a placeholder):
{ "displayName": "EnableLocal-Admin-01", "description": "The new Cloud PC Config to enable local admin", "profileType": "template", "templateId": "W365.CloudPCConfiguration", "settings": [ { "@odata.type": "#microsoft.graph.cloudPcBooleanSetting", "dataType": "boolean", "settingDefinitionId": "W365.CloudPCConfiguration.LocalAdmin.IsEnabled", "platform": "all", "isEnabled": true } ], "assignments": [ { "groupId": "<your-group-object-id>", "assignType": "group" } ], "roleScopeTagIds": [ "0" ]}
A few things stood out:
templateId=W365.CloudPCConfiguration– this is what makes the profile a Cloud PC configuration rather than another Cloud PC Settings template.- Only one setting is sent. The portal doesn’t send local admin as Not configured for anything else – unconfigured settings are simply absent from the
settingsarray. settingDefinitionId=W365.CloudPCConfiguration.LocalAdmin.IsEnabledwith acloudPcBooleanSetting. SettingisEnabledtofalseis how you would express Disabled.- Assignments are inline. Unlike provisioning policies, where I used a separate
/assigncall, the group assignment goes straight into the create body. roleScopeTagIds–"0"is the built-in Default scope tag.
Graph returned 200 OK in under 400 ms.
Call 2 – Reading the legacy User settings (GET)
The same page also loads the legacy policies:
GET https://graph.microsoft.com/beta/deviceManagement/virtualEndpoint/userSettings?$expand=assignments
This returned my existing CPC-PowerUsers policy with "localAdminEnabled": true, assigned to three groups.
The response headers are also telling. Graph returned Deprecation and Sunset headers plus Link headers pointing to change-log entries for properties on this resource – including selfServiceEnabled, crossRegionDisasterRecoveryEnabled, frequencyInHours and notificationSetting. These relate to individual properties rather than the whole endpoint, but they are a clear signal that the userSettings object keeps evolving underneath you.
Beta caveat: everything here is on the Graph beta endpoint and was captured from the portal. Beta APIs can change and shouldn’t be treated as production-stable.
Creating the Cloud PC configuration with PowerShell
With the request body from the HAR trace, reproducing it in PowerShell is straightforward. I didn’t want a script that simply fires a POST, though. Before creating anything it:
- lists the existing Cloud PC configurations with their rank
- lists any legacy User settings policies that still have local admin enabled
- warns if the target group is already covered by one of those legacy policies
- creates the Cloud PC configuration with the group assigned inline
- reads the policy back from Graph to confirm it landed
My policy is called:
W365-CPC-LocalAdmin
and the key setting is:
settingDefinitionId : W365.CloudPCConfiguration.LocalAdmin.IsEnabledisEnabled : true

PowerShell Script
Link GitHub – avdwin365mem/CloudPC-Config-LocalAdmin.ps1 at main · askaresh/avdwin365mem
############################################################################################## Windows 365 - Enable Local Admin via Cloud PC Configurations (Cloud PC Settings)# PowerShell + Microsoft Graph REST API (beta)## - Inventories existing Cloud PC configurations (with policy rank)# - Inventories legacy User settings policies that still grant local admin# - Warns if the target group is already covered by a legacy local-admin policy# - Creates a Cloud PC configuration with "Enable local admin = Enabled" and assigns it## Request body shape was captured from the Intune admin center (HAR trace).# Only requires the Microsoft.Graph.Authentication module - all work is done with raw# Graph calls so the heavier SDK sub-modules are never loaded.#############################################################################################$ErrorActionPreference = "Stop"#---------------------------------------------------------------------------------------------# STEP 0 - Module + Authentication#---------------------------------------------------------------------------------------------# Install once if needed:# Install-Module Microsoft.Graph.Authentication -Scope CurrentUser -ForceImport-Module Microsoft.Graph.Authentication# Set your tenant explicitly - avoids home-tenant guessing and some consent failures$TenantId = "dXXXXX-4XXX-4XXX-8XXX-fe7XXXXXXX"Connect-MgGraph -TenantId $TenantId -Scopes "CloudPC.ReadWrite.All","Group.Read.All"# Hard stop if we are not actually connected - prevents the rest of the script running blind$ctx = Get-MgContextif (-not $ctx) { throw "Not connected to Microsoft Graph. Resolve the sign-in error before continuing." }Write-Host "Connected as $($ctx.Account) to tenant $($ctx.TenantId)" -ForegroundColor Cyan$baseUri = "https://graph.microsoft.com/beta/deviceManagement/virtualEndpoint"# Confirm you hold the Cloud PC RBAC permissions before you startInvoke-MgGraphRequest -Method GET -OutputType PSObject -Uri "$baseUri/getEffectivePermissions"#---------------------------------------------------------------------------------------------# STEP 1 - Variables#---------------------------------------------------------------------------------------------$policyName = "W365-CPC-LocalAdmin-02"$policyDescription = "Cloud PC configuration - enable local admin for approved users"$groupName = "W365-CPC-Grp" # dedicated, tightly controlled group$enableLocalAdmin = $true # $true = Enabled, $false = Disabled # (Not configured = leave the setting out)#---------------------------------------------------------------------------------------------# STEP 2 - Discovery: existing Cloud PC configurations and their rank#---------------------------------------------------------------------------------------------# Same filter the Intune portal uses on the Cloud PC Settings page$filter = "templateId in ('W365.CloudPCConfiguration','W365.WindowsApp','W365.RemoteConnectionExperience')"$settingProfilesUri = "$baseUri/settingProfiles?`$filter=$([uri]::EscapeDataString($filter))"$cpcConfigs = (Invoke-MgGraphRequest -Method GET -OutputType PSObject -Uri $settingProfilesUri).value | Where-Object { $_.templateId -eq "W365.CloudPCConfiguration" }Write-Host "`nExisting Cloud PC configurations (rank 1 = highest priority):" -ForegroundColor Cyan$cpcConfigs | Sort-Object { $_.priorityMetaData.priority } | Format-Table @{n = "Rank"; e = { $_.priorityMetaData.priority } }, displayName, isAssigned, lastModifiedDateTime -AutoSizeif ($cpcConfigs.displayName -contains $policyName) { throw "A Cloud PC configuration named '$policyName' already exists - stopping to avoid a duplicate."}#---------------------------------------------------------------------------------------------# STEP 3 - Discovery: legacy User settings policies that still grant local admin#---------------------------------------------------------------------------------------------$userSettings = (Invoke-MgGraphRequest -Method GET -OutputType PSObject ` -Uri "$baseUri/userSettings?`$expand=assignments").value$legacyLocalAdmin = $userSettings | Where-Object { $_.localAdminEnabled -eq $true }Write-Host "`nLegacy User settings policies with local admin enabled:" -ForegroundColor Yellow$legacyLocalAdmin | ForEach-Object { [pscustomobject]@{ Policy = $_.displayName Created = $_.createdDateTime Groups = ($_.assignments.target.groupId -join ", ") }} | Format-Table -AutoSize -Wrap#---------------------------------------------------------------------------------------------# STEP 4 - Resolve the assignment group#---------------------------------------------------------------------------------------------$filterEnc = [uri]::EscapeDataString("displayName eq '$groupName'")$group = (Invoke-MgGraphRequest -Method GET -OutputType PSObject ` -Uri "https://graph.microsoft.com/v1.0/groups?`$filter=$filterEnc&`$select=id,displayName,securityEnabled").value | Select-Object -First 1# Or hard-code the object ID instead:# $group = Invoke-MgGraphRequest -Method GET -OutputType PSObject `# -Uri "https://graph.microsoft.com/v1.0/groups/<group-object-id>?`$select=id,displayName,securityEnabled"if (-not $group) { throw "Group '$groupName' not found in tenant $($ctx.TenantId)." }if (-not $group.securityEnabled) { throw "Group '$($group.displayName)' is not security-enabled." }Write-Host "`nAssignment target: $($group.displayName) [$($group.id)]" -ForegroundColor Cyan# Overlap check - is this group already getting local admin from a legacy policy?$overlap = $legacyLocalAdmin | Where-Object { $_.assignments.target.groupId -contains $group.id }if ($overlap) { Write-Warning ("Group '$($group.displayName)' is already assigned to legacy User settings " + "policy '$($overlap.displayName -join "', '")' with local admin enabled. " + "Plan to remove it from the legacy policy after validation.")}#---------------------------------------------------------------------------------------------# STEP 5 - Build the Cloud PC configuration body (matches the Intune portal request)#---------------------------------------------------------------------------------------------$params = @{ displayName = $policyName description = $policyDescription profileType = "template" templateId = "W365.CloudPCConfiguration" # Only include the settings you intend to manage. # Anything not in this array is "Not configured" and does not take part in conflicts. settings = @( @{ "@odata.type" = "#microsoft.graph.cloudPcBooleanSetting" dataType = "boolean" settingDefinitionId = "W365.CloudPCConfiguration.LocalAdmin.IsEnabled" platform = "all" isEnabled = $enableLocalAdmin } ) # Assignments go inline - no separate /assign call needed assignments = @( @{ groupId = $group.id assignType = "group" } ) # "0" is the built-in Default scope tag roleScopeTagIds = @("0")}#---------------------------------------------------------------------------------------------# STEP 6 - Create the policy#---------------------------------------------------------------------------------------------$settingProfile = Invoke-MgGraphRequest -Method POST -OutputType PSObject ` -Uri "$baseUri/settingProfiles" ` -Body ($params | ConvertTo-Json -Depth 10) -ContentType "application/json"#---------------------------------------------------------------------------------------------# STEP 7 - Verify (read it back rather than trusting the POST)#---------------------------------------------------------------------------------------------# Use the ID from the POST response; if it isn't returned, look the policy up by nameif (-not $settingProfile.id) { Start-Sleep -Seconds 3 $settingProfile = (Invoke-MgGraphRequest -Method GET -OutputType PSObject -Uri $settingProfilesUri).value | Where-Object { $_.displayName -eq $policyName } | Select-Object -First 1}if (-not $settingProfile.id) { throw "Policy '$policyName' not returned by Graph - check the portal." }Write-Host "`nCreated Cloud PC configuration: $policyName [$($settingProfile.id)]" -ForegroundColor Green# Full read-back of the policy (settings, assignments, rank) as JSONtry { Invoke-MgGraphRequest -Method GET -OutputType PSObject -Uri "$baseUri/settingProfiles/$($settingProfile.id)" | ConvertTo-Json -Depth 10}catch { Write-Warning "Read by ID failed ($($_.Exception.Message)) - showing the list entry instead." $settingProfile | Select-Object id, displayName, templateId, isAssigned, roleScopeTagIds, @{n = "Rank"; e = { $_.priorityMetaData.priority } }, lastModifiedDateTime | Format-List}Write-Host ("New policies are added at the bottom of the rank. Rerank in Intune if another " + "Cloud PC configuration manages local admin.") -ForegroundColor Yellow# Disconnect-MgGraph#---------------------------------------------------------------------------------------------# Troubleshooting#---------------------------------------------------------------------------------------------# AADSTS650051 on Connect-MgGraph: the Microsoft Graph Command Line Tools enterprise app# can't be consented in this tenant as requested. Ask a Global Administrator to grant admin# consent for CloudPC.ReadWrite.All and Group.Read.All, then sign in again.## 403 on settingProfiles / userSettings: check the getEffectivePermissions output above -# you need a Windows 365 Administrator (or equivalent Cloud PC RBAC) role.
Two small but important details in the body:
- To express Disabled, set
$enableLocalAdmin = $false. To express Not configured, don’t include the setting at all. - The script uses the same
$filteras the portal. I deliberately kept it identical so the results match what you see in Intune.
Validating on the Cloud PC
After the user signs out and back in, confirm the membership on the Cloud PC itself:
Get-LocalGroupMember -Group "Administrators"

Migrating existing User settings policies
Existing User settings policies don’t need to be ripped out today. I would still plan the move in controlled waves rather than one big switch:
- Inventory all existing User settings policies (Step 3 of the script does this).
- Identify the groups where Enable local admin is selected.
- Check for overlapping group memberships across policies.
- Create the equivalent Cloud PC configuration policies.
- Assign them to a controlled pilot group first.
- Have pilot users sign out and sign back in.
- Verify local Administrators membership and effective access.
- Remove the group from the old User settings policy.
- Repeat by deployment wave.
- Delete the legacy local-admin User settings policy once nothing depends on it.
Careful with step 10: a User settings policy often carries more than local admin. My CPC-PowerUsers policy also controls user reset and restore points every 12 hours. Untick local admin rather than deleting the policy if those capabilities are still needed.
The standard I would put in place:
All new Windows 365 local-admin assignments use Cloud PC configurations. Existing User settings assignments are migrated in waves. User settings remains only for capabilities specific to it, such as reset and restore.
Final thoughts
On the surface this is a small change – one checkbox moving from one policy to another. Underneath, it is a good look at where Windows 365 policy management is heading:
User settings (legacy) +newest-created policy wins
to:
Cloud PC Settings templates +per-setting evaluation + explicit rank
The new model is clearly better – explicit ranking, Enabled / Disabled / Not configured, scope tags and inline assignments. The trade-off is that you now have to think about rank and the difference between Disabled and Not configured, and keep an eye out for the same users being targeted by both models during migration.
The HAR trace also hinted at more Cloud PC Settings templates (W365.WindowsApp and W365.RemoteConnectionExperience), so I suspect this model will keep absorbing more settings over time. Something I will keep an eye on.
Thanks,
Aresh Sarkari















































Recent Comments