Creating Windows 365 Groups and assigning licenses using Graph and PowerShell

With the exciting release of Windows 365 Frontline, you might now find yourself juggling multiple different SKUs.

Fortunately now we can nest groups in Azure AD, we can create groups for each SKU and then nest them into central groups for management (in this post I’m using one for Frontline and one for non-frontline as they will need different assignments).

As with all of my scripts, this supports automation with an app reg and each group creation/assignment has logic so it can be run multiple times without issue.

This script can be downloaded from GitHub here

Or from PowerShell Gallery

Install-Script -Name create-w365-groups

After installing modules and authenticating, it then creates a Windows 365 Users Group which is the main group you use for user assignments as well as a dynamic Windows 365 devices group which will capture all of your devices (after checking they don’t already exist):

##Create AAD Group
write-host "Creating Azure AD Groups"
##Create W365 Groups for W365 users, manually assigned

##Check if group exists first
$w365users = Get-MgGroup -Filter "DisplayName eq 'W365-Users'"
if ($null -eq $w365users) {
    write-host "Creating W365 Users Group"
    $w365users = New-MGGroup -DisplayName "W365-Users" -Description "Windows 365 Users" -MailEnabled:$False -MailNickName "W365Users" -SecurityEnabled -IsAssignableToRole:$false
    write-host "W365 Users Group Created"
else {
    write-host "W365 Users Group Already Exists"

##Check if device group exists
$w365devices = Get-MgGroup -Filter "DisplayName eq 'W365 Devices'"
if ($null -eq $w365devices) {
##Create Devices Group with dynamic membership based on Cloud PC model type
write-host "Creating W365 Devices Group - Dynamically Assigned"
$w365devices = New-MGGroup -DisplayName "W365 Devices" -Description "Dynamic group for all Windows 365 Single User devices" -MailEnabled:$False -MailNickName "w365devices" -SecurityEnabled -GroupTypes "DynamicMembership" -MembershipRule "(device.deviceModel -startsWith ""Cloud"")" -MembershipRuleProcessingState "On" -IsAssignableToRole:$false
write-host "W365 Devices Group Created"
else {
    write-host "W365 Devices Group Already Exists"

It then loops through your purchased licenses to find any Windows 365 ones and grabs the details:

write-host "Getting SKUs"
$sku2 = ((Invoke-MgGraphRequest -uri "" -method get -OutputType PSObject).value)
##Loop through looking for W365 enterprise non-frontline SKUs (currently start with either CPC_E)
$skuids = @()
foreach ($sku in $sku2) {
    $part = $sku.skuPartNumber
    if ($part -like "*CPC_E*") {
        $skuidsobject = [pscustomobject]@{
            sid = $sku.skuid
            part = $part
        $skuids += $skuidsobject
        write-host "SKU Found - $part"

Finally, it creates a group for each SKU, assigns the license to it and then nests it within our main W365 users group:

$i = 1
foreach ($skuiditem in $skuids) {

    $skuid = $skuiditem.sid
    $skupart = $skuiditem.part
##Check if this group already exists
$w365userssku = Get-MgGroup -Filter "DisplayName eq 'W365-Users-$skupart'"
if ($null -eq $w365userssku) {

##Create W365 Groups for W365 users of each sku, manually assigned
write-host "Creating W365 Users Group for SKU $skupart"
$w365userssku = New-MGGroup -DisplayName "W365-Users-$skupart" -Description "Windows 365 Users $skupart" -MailEnabled:$False -MailNickName "W365Users_$i" -SecurityEnabled -IsAssignableToRole:$false
write-host "W365 Users Group Created for SKU $skupart"

$skugroupid = $w365userssku.Id
##Assign the license to the group
write-host "Assigning License to Group - W365 Users $skupart"
$uri = "$skugroupid/assignLicense"
$body = @"
	"addLicenses": [{
		"disabledPlans": [],
		"skuId": "$skuid"
	"removeLicenses": []
Invoke-MgGraphRequest -Uri $uri -Method POST -Body $body -ContentType "application/json"
write-host "License Assigned to Group W365 Users $skupart"

##Add to main group
write-host "Nesting Group $skugroupid in $groupid"
New-MgGroupMember -GroupId "$groupid" -DirectoryObjectId "$skugroupid"
write-host "Group $skugroupid nested in $groupid"

else {
    write-host "Group W365-Users-$skupart already exists, skipping"

Once that’s done, it does the same thing for your Frontline licenses.

Happy deploying!

Leave a Comment