Automating AVD Context-Based Redirections


What Are Context-Based Redirections?

Context-Based Redirections is a Preview feature in Azure Virtual Desktop that lets you control peripheral and device redirection — clipboard, drives, printers, USB — based on the compliance state of the connecting device, rather than applying a blanket allow or deny for all users.

Instead of a binary on/off toggle on the host pool, you map an Entra ID Authentication Context to a redirection type. A Conditional Access policy then evaluates whether the connecting device is Intune-compliant. Compliant devices get the redirection; non-compliant or BYOD devices do not.

Why this matters

Clipboard and drive redirection are the most common data exfiltration vectors in VDI environments.

Traditional AVD policies apply equally to corporate laptops and personal BYOD devices.

Context-Based Redirections lets you allow clipboard on a managed device while blocking it on the same session from a personal machine — without creating separate host pools.

The feature works across three separate Azure / Microsoft 365 control planes, each configured independently:

LayerServiceWhat you configure
1Entra IDAuthentication Context Class Reference (c1–c25)
2Conditional AccessPolicy: target auth context → require compliant device
3AVD Host PoolcustomRdpProperty: map context ID to redirection types
RequirementDetail
Azure SubscriptionWith an AVD host pool already deployed
Entra ID P1 or P2Required for Conditional Access policies
Microsoft IntuneDevices must be enrolled and compliance policies in place
Entra RoleConditional Access Administrator or Global Administrator
Azure RBAC RoleDesktop Virtualization Contributor (on the host pool)
PowerShell ModulesMicrosoft.Graph, Az.DesktopVirtualization
# Install required modules (one-time)

Install-Module Microsoft.Graph -Scope CurrentUser -Force

Install-Module Az.DesktopVirtualization -Scope CurrentUser -Force

An Authentication Context is a named signal within Entra ID (ID c1 through c25) that Conditional Access policies can target. Think of it as a label you attach to a resource request, which CA then evaluates against your policies.

Script: New-AVDAuthenticationContext.ps1

What the script does

  • Connects to Microsoft Graph with Policy.ReadWrite.ConditionalAccess scope
  • Checks if the context ID is already in use and offers to update it
  • Creates the authentication context with IsAvailable = $true (equivalent to checking Publish to apps in the portal)
  • Disconnects cleanly on exit

Key Graph API call

$params = @{

Id = $ContextId

DisplayName = $DisplayName

Description = $Description

IsAvailable = $true # Publishes the context to apps

}

New-MgIdentityConditionalAccessAuthenticationContextClassReference `

-BodyParameter $params

Usage

.New-AVDAuthenticationContext.ps1 `

-DisplayName "AVD Compliant Device" `

-Description "Requires compliant device for AVD clipboard/drive/USB/printer redirection" `

-ContextId "c1" `

-TenantId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Context ID allocation tip

IDs c1–c25 are tenant-wide. Keep a register of which ID maps to which purpose.

Example: c1 = AVD Compliant Device, c2 = AVD Privileged Admin, c3 = Sensitive App MFA.

Once used in a CA policy, changing a context ID will break the policy silently.

The CA policy is what enforces the compliance requirement. It watches for authentication attempts that carry the context ID from Step 1 and grants access only if the device is marked compliant by Intune.

Script: New-AVDConditionalAccessPolicy.ps1

What the script does

  • Connects to Microsoft Graph with Policy.ReadWrite.ConditionalAccess and Group.Read.All
  • Validates the authentication context from Step 1 exists and is published
  • Resolves Entra group display names to Object IDs automatically — no manual GUID lookup
  • Builds the policy body targeting the auth context (not a cloud app)
  • Defaults to enabledForReportingButNotEnforced — safe for initial testing
  • Detects duplicate policy names and warns before creating

Key CA policy structure

$policyBody = @{

displayName = $PolicyName

state = $PolicyState

conditions = @{

applications = @{

includeAuthenticationContextClassReferences = @($ContextId)

}

}

grantControls = @{

operator = "OR"

builtInControls = @("compliantDevice")

}

}

New-MgIdentityConditionalAccessPolicy -BodyParameter $policyBody

Usage

.New-AVDConditionalAccessPolicy.ps1 `

-TenantId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" `

-PolicyName "AVD - Require Compliant Device for Redirection" `

-ContextId "c1" `

-TargetGroupName "AVD-Users" `

-ExcludeGroupName "CA-BreakGlass-Exclusion" `

-PolicyState "enabledForReportingButNotEnforced"
Report-only mode — start here

The -PolicyState parameter defaults to enabledForReportingButNotEnforced.

In this mode, the policy evaluates but does not enforce. Sign-in logs show what WOULD have been blocked.

Review Entra > Monitoring > Sign-in logs for at least 48 hours before switching to enabled.

Always include a break-glass group in ExcludeGroupName to prevent admin lockout.

The final step writes the dynamic context mapping into the host pool’s customRdpProperty string. This is what tells the AVD gateway to trigger the CA evaluation using the auth context when a user connects and attempts a redirection.

Script: Set-AVDHostPoolRdpAuthContext.ps1

RDP property format

The dynamic context RDP properties follow this format:

# Dynamic context RDP property format

redirectclipboard:dynamicContext:c1:

redirectdrives:dynamicContext:c1:

redirectprinters:dynamicContext:c1:

usbdevicestoredirect:dynamicContext:c1:

What the script does

  • Fetches the current customRdpProperty string from the host pool
  • Backs it up to a timestamped .txt file before touching anything
  • Parses the existing RDP string into a hashtable — never overwrites unrelated RDP properties
  • Removes conflicting static properties (e.g. redirectclipboard:i:1) that would conflict with dynamic mode
  • Adds or updates only the targeted redirection types
  • Detects if no changes are needed and exits cleanly
  • Supports -WhatIf to preview changes without applying

Usage

# All four redirections

.Set-AVDHostPoolRdpAuthContext.ps1 `

-SubscriptionId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" `

-ResourceGroupName "rg-avd-prod" `

-HostPoolName "hp-avd-prod-01" `

-ContextId "c1"

# Selective redirections only

.Set-AVDHostPoolRdpAuthContext.ps1 `

-SubscriptionId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" `

-ResourceGroupName "rg-avd-prod" `

-HostPoolName "hp-avd-prod-01" `

-ContextId "c1" `

-Redirections Clipboard, Drive

# Preview changes without applying

.Set-AVDHostPoolRdpAuthContext.ps1 ... -WhatIf
Conflict handling

If the host pool already has redirectclipboard:i:1 or redirectdrives:i:0 set, the script automatically removes these before adding the dynamic context version.

Static and dynamic context properties for the same redirection type cannot coexist — the last one wins in the RDP evaluation, which is undefined behaviour.

Rather than running three scripts independently and managing dependencies between them, the orchestrator drives all three steps from a single JSON parameter file. It handles module checks, connections, step dependencies, and prints a final pass/fail summary.

Script: Invoke-AVDContextBasedRedirections.ps1

Parameter file — avd-cbr-params.json

{
  "TenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "SubscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "AuthContext": {
    "ContextId": "c1",
    "DisplayName": "AVD Compliant Device",
    "Description": "Requires compliant device for redirection"
  },
  "ConditionalAccessPolicy": {
    "PolicyName": "AVD - Require Compliant Device for Redirection",
    "TargetGroupName": "AVD-Users",
    "ExcludeGroupName": "CA-BreakGlass-Exclusion",
    "PolicyState": "enabledForReportingButNotEnforced"
  },
  "HostPool": {
    "ResourceGroupName": "rg-avd-prod",
    "HostPoolName": "hp-avd-prod-01",
    "Redirections": [ "Clipboard", "Drive", "Printer", "USB" ]
  }
}


Orchestrator features

FeatureBehaviour
Pre-flight confirmationPrints a full summary and prompts y/n before any changes
Step dependency logicStep 1 failure stops execution. Step 2 failure warns but Step 3 still runs.
Selective re-runUse -Steps 3 to re-run a single step without touching the others
Idempotent-safeRe-running on a fully configured tenant makes zero changes
-WhatIf supportPreview all three steps without modifying anything
Final summary tableAlways printed — shows ✔ Success / – Skipped / ✘ Failed per step

Orchestrator usage

# Full run — all three steps
.Invoke-AVDContextBasedRedirections.ps1

# Custom parameter file
.Invoke-AVDContextBasedRedirections.ps1 -ParameterFile ".prod-params.json"

# Preview all changes (no modifications applied)
.Invoke-AVDContextBasedRedirections.ps1 -WhatIf

# Retry only Step 3 after a failure
.Invoke-AVDContextBasedRedirections.ps1 -Steps 3

After all three steps complete, validate behaviour from both a compliant and a non-compliant device. This cannot be automated — it requires a live AVD session.

Test scenarioExpected resultWhere to check
Connect from Intune-compliant deviceClipboard / drive / printer availableAVD session — try copy-paste
Connect from non-compliant / BYODRedirections blocked / greyed outAVD session — try copy-paste
Check CA policy evaluationPolicy shows in sign-in log detailsEntra > Monitoring > Sign-in logs
Verify host pool RDP stringcustomRdpProperty contains dynamicContext entries
ScriptCoversPrimary module
New-AVDAuthenticationContext.ps1Step 1Microsoft.Graph.Identity.SignIns
New-AVDConditionalAccessPolicy.ps1Step 2Microsoft.Graph.Identity.SignIns, .Groups
Set-AVDHostPoolRdpAuthContext.ps1Step 3Az.DesktopVirtualization
Invoke-AVDContextBasedRedirections.ps1Steps 1–3All of the above
avd-cbr-params.jsonConfigParameter file for orchestrator
Preview feature — important caveats

Context-Based Redirections is in Public Preview as of June 2026.

The dynamic RDP property syntax (dynamicContext) is not yet fully documented publicly.

Always validate the RDP string the Azure Portal writes after a manual save, then replicate it.

Preview features may change syntax or behaviour before GA — test in a non-production host pool first.

Sign-in log analysis via Graph API is the best automated approach to validate CA policy hits.

Feature in Preview — verify before production use

  This article was originally published by Aavisek Choudhury's Blog. You can find the original article here.