Boost your AVD and Windows 365 SSO deployment for hybrid devices

By | November 9, 2024

Introduction

For end users to have a good experience interacting with any IT systems these days, Single Sign-On (SSO) is a must-have. I can’t emphasize enough how annoying and non-productive it is to log in multiple times to access corporate resources or systems. When using Azure Virtual Desktop (AVD) or Windows 365, there is no exception configuring SSO is a must.

SSO for Entra hybrid joined AVD hosts and Cloud PCs

Configuring SSO for Entra joined devices is straightforward for AVD and Windows 365. Entra hybrid joined devices have some more requirements that need to be in place such as Kerberos server object in Active Directory and Microsoft Entra authentication for RDP. As an optional setting, we can hide the consent prompt dialog this is however highly recommended if you ask me.

To boost the deployment of SSO for Entra hybrid joined AVD and Windows 365 devices, I’m using a script I created to optimize configuration time and avoid mistakes when setting up Microsoft Entra authentication for RDP and hide the consent prompt dialog. To be fair, my script isn’t revolutionary compared to what you can find in Microsoft’s documentation deployment steps. I have, however, combined a few steps, such as including the creation and specification of the required dynamic group and the installation of Microsoft Graph modules.

Running the script

First, edit the parameters $EntraIDGroup and $DynamicDeviceRule to whatever fits your environment and needs.

$EntraIDGroup: This is what the dynamic group name will be in Entra ID. If you specify a group that already exists it will use that throughout the deployment.

$DynamicDeviceRule: Specify the dynamic device rule that will “catch” either AVD hosts and/or Cloud PCs.

As an example, I will call my dynamic group All AVD Hybrid Devices with the following rule device.displayName -startsWith “avd-“.

When running the script it will first install and import the required modules and you will then receive an authentication prompt to login to Microsoft Graph.

It will then set the RemoteDesktopProtocolEnabled to True for Windows Cloud Login and Microsoft Remote Desktop. When that is completed it will check if the group name that is provided already exists if not it will create a new group in Entra ID.

In the end, it will map the dynamic group to the Remote Desktop Security Configuration.

 [CmdletBinding()]
Param (
    [Parameter(Mandatory=$false)]    
    [array]$modulename = @("Microsoft.Graph.Authentication" 
                           "Microsoft.Graph.Applications"
                           "Microsoft.Graph.Groups"),
    [Parameter(Mandatory=$false)]    
    [String]$EntraIDGroup = "",
    [Parameter(Mandatory=$false)]    
    [String]$DynamicDeviceRule = ''
 )


#Search for required modules and install them if they are not present on the system.
try {
        if ($modulename) {
        foreach ($module in $modulename){
            $checkmodule = Get-Module -ListAvailable | Where-Object { $_.Name -eq $module } -Verbose
            if($checkmodule) {
            Write-Host "$module is already installed" -ForegroundColor Cyan
            Import-Module $checkmodule.Name -Force
            } Else{
            Write-Host "$module is not installed, installing $module module" -ForegroundColor Green
            Install-Module $module -AllowClobber -Verbose -Force
            Import-Module $module -Force
            }

        }
            
          }else {
            Write-Host "No module requirements is specificed in variables" -ForegroundColor Cyan
      }           

}
catch {
                Write-Output "Unable to locate installed modules"
                write-output $_.Exception.Message
                Break
}



#Connect to Microsoft Graph.
try {
        
       Connect-MgGraph -Scopes "Application.Read.All","Application-RemoteDesktopConfig.ReadWrite.All", "Group.ReadWrite.All"

}
catch {
                Write-Output "Unable to connect to Microsoft Graph"
                write-output $_.Exception.Message
                Break
}

#Get Microsoft Graph Service Principals for SSO.
try {
        
       $MSRDspId = (Get-MgServicePrincipal -Filter "AppId eq 'a4a365df-50f1-4397-bc59-1a1564b8bb9c'").Id
        $WCLspId = (Get-MgServicePrincipal -Filter "AppId eq '270efc09-cd0d-444b-a71f-39af4910ec45'").Id

}
catch {
                Write-Output "Unable to get Graph Service Principal"
                write-output $_.Exception.Message
                Break
}


#Set SSO property on Microsoft Graph Service Principals
try {
        
       If ((Get-MgServicePrincipalRemoteDesktopSecurityConfiguration -ServicePrincipalId $MSRDspId) -ne $true) {
        Update-MgServicePrincipalRemoteDesktopSecurityConfiguration -ServicePrincipalId $MSRDspId -IsRemoteDesktopProtocolEnabled
        }

       If ((Get-MgServicePrincipalRemoteDesktopSecurityConfiguration -ServicePrincipalId $WCLspId) -ne $true) {
            Update-MgServicePrincipalRemoteDesktopSecurityConfiguration -ServicePrincipalId $WCLspId -IsRemoteDesktopProtocolEnabled
        }

}
catch {
                Write-Output "Unable to set property on Service Principal"
                write-output $_.Exception.Message
                Break
}


# Get property information on Service Principals
try {
        
       Get-MgServicePrincipalRemoteDesktopSecurityConfiguration -ServicePrincipalId $MSRDspId
       Get-MgServicePrincipalRemoteDesktopSecurityConfiguration -ServicePrincipalId $WCLspId

}
catch {
                Write-Output "Unable to Get property on Service Principal"
                write-output $_.Exception.Message
                Break
}



#Check if group name is being used
try {
        
       $Groupinformation = Get-MgGroup | Where-Object {$_.Name -eq $EntraIDGroup}
           If($Groupinformation){
           write-output "Group already exist"       
           }else{
           
           write-output "Group does not exist"
           write-output "Creating group" 

           $params = @{
	        description = "Group used for Azure Virtual Desktop SSO configuration"
	        displayName = $EntraIDGroup
	        groupTypes = @(
            "DynamicMembership"
            )
            mailEnabled = $false
            mailNickname = "NotSet"
            securityEnabled = $true
            membershipRule = $DynamicDeviceRule
            membershipRuleProcessingState = "on"
        }

            New-MgGroup -BodyParameter $params

        }

}
catch {
                Write-Output "Unable to gather information about Entra ID Groups"
                write-output $_.Exception.Message
                Break
}



#Assign group to Service Principals
try {
        
        $Groupinformation = Get-MgGroup -Filter "DisplayName eq '$EntraIDGroup'"
        
        $tdg = New-Object -TypeName Microsoft.Graph.PowerShell.Models.MicrosoftGraphTargetDeviceGroup
        $tdg.Id = $Groupinformation.Id
        $tdg.DisplayName = $Groupinformation.DisplayName

        New-MgServicePrincipalRemoteDesktopSecurityConfigurationTargetDeviceGroup -ServicePrincipalId $MSRDspId -BodyParameter $tdg
        New-MgServicePrincipalRemoteDesktopSecurityConfigurationTargetDeviceGroup -ServicePrincipalId $WCLspId -BodyParameter $tdg
      

}
catch {
                Write-Output "Unable to assign group membership to Service principals"
                write-output $_.Exception.Message
                Break
}

Closing words

I hope this script gives you a small boost with the configuration of SSO for Entra hybrid joined AVD hosts or Cloud PCs, especially if you are a consultant and regularly are helping organizations with setting up AVD and Windows 365 environments.

Leave a Reply

Your email address will not be published.