Scenario: AVD Privileged Admin Workstation
The Problem This Solves
Some Microsoft PowerShell admin modules do not prompt for FIDO2 passkeys or Windows Hello for Business. Microsoft's passkey compatibility matrix states it:
"Some PowerShell modules that use Internet Explorer instead of Edge aren't capable of performing FIDO2 authentication. For example, PowerShell modules for SharePoint Online or Teams, or any PowerShell scripts that require admin credentials, don't prompt for FIDO2."
Support changes by module version and cloud (the Teams module moved its interactive sign-in to Web Account Manager in 7.8.1-preview), so test the current module before building around the gap. CMMC Level 2 requires MFA (IA.L2-3.5.3) and replay-resistant authentication (IA.L2-3.5.4); it does not prescribe phishing-resistant MFA. This guide recommends phishing resistance as the stronger design, and an exemption for administrators is the wrong way to close the module gap.
An AVD workstation can host narrowly scoped administrative automation using its managed identity. The administrator authenticates to AVD with phishing-resistant MFA; supported tools acquire application tokens from the VM identity without an operator-managed password or certificate. This does not preserve the administrator's delegated identity or just-in-time user permissions.
Any code or user able to run on the VM can request tokens for its managed identity. User Conditional Access and PIM activation for the administrator do not govern these application-token calls. A compromised host can use its standing application grants even without an active administrator session. Prefer delegated user authentication for human administration where supported; reserve managed identities for explicitly approved, narrowly scoped operations. See Microsoft's managed identity security boundary.
Architecture
| Layer | What it does |
|---|---|
| User → AVD broker | Admin authenticates with phishing-resistant MFA (FIDO2 / WHfB). Conditional Access enforces this. |
| AVD session host | Has a system-assigned managed identity with the necessary admin Graph API permissions |
| PowerShell module → Graph API | Module authenticates via managed identity: Connect-MgGraph -Environment USGov -Identity, for example |
Which PowerShell Modules Support Managed Identity
| Module | Managed identity support | Connection command |
|---|---|---|
| Microsoft Teams | -Identity exists but is Commercial-only (Learn: "currently only supported in commercial environments") | GCC High: certificate-based application authentication, Connect-MicrosoftTeams -CertificateThumbprint "<thumbprint>" -ApplicationId "<appId>" -TenantId "<tenantId>" (module 5.0.1-preview or later; the app needs Organization.Read.All plus a Teams Entra role; New-Team, *PolicyPackage*, and the other cmdlets on Learn's exclusion list are not supported) |
| Microsoft Graph | Yes | Connect-MgGraph -Environment USGov -Identity |
| Exchange Online | Yes | Connect-ExchangeOnline -ExchangeEnvironmentName O365USGovGCCHigh -ManagedIdentity -Organization contoso.onmicrosoft.us |
| SharePoint Online (PnP) | Yes | Connect-PnPOnline -Url https://contoso.sharepoint.us -AzureEnvironment USGovernmentHigh -ManagedIdentity |
| SharePoint Online Management Shell | No: use PnP or Graph instead | N/A |
| Azure Az module | Yes | Connect-AzAccount -Environment AzureUSGovernment -Identity |
| Security & Compliance | No native managed identity: use Connect-IPPSSession with certificate-based auth as fallback | Certificate on session host |
The connection examples target GCC High/Azure Government. Authentication alone does not authorize cmdlets: grant each service's documented API permissions and RBAC roles, and validate the installed module in the target cloud. See Teams connection syntax, Teams application authentication, Exchange managed identity, and PnP connection environments.
For modules that do not support managed identity authentication, use certificate-based authentication as the fallback. Install a certificate on the session host and configure the app registration to accept certificate credentials. Protect the private key with appropriate storage and ACLs, restrict application permissions, and manage rotation. Installing a certificate does not automatically make its key non-exportable or hardware-bound.
Prerequisites
Session Host VM
Use a personal host pool with one VM per admin. Each VM has its own system-assigned managed identity with permissions scoped to that admin's role.
| Requirement | Configuration |
|---|---|
| VM type | Personal pool: each admin gets a dedicated session host |
| OS | Windows 11 Enterprise (single-session) |
| Managed identity | System-assigned: enabled on each session host VM |
| PowerShell modules | Pre-installed on the session host image (Teams, Graph, Exchange Online, PnP, Az) |
| Network | Session hosts can reach Microsoft Graph and M365 service endpoints |
App Registration and Permissions
The managed identity authenticates as the VM's service principal. Resolve it by its object ID, then grant only the target service's documented permissions. Graph application roles, Entra directory roles, Azure RBAC, and Exchange application authorization are different permission systems.
Example: Exchange admin session host
# One-time setup, run as an administrator with the right to grant app roles and directory roles
Connect-MgGraph -Environment USGov -Scopes "AppRoleAssignment.ReadWrite.All,Application.Read.All,RoleManagement.ReadWrite.Directory"
# The session host's system-assigned managed identity (display name = VM name)
$mi = Get-MgServicePrincipal -Filter "displayName eq 'avd-admin-exo-01'"
# The Office 365 Exchange Online resource (AppId is the same in every tenant)
$exo = Get-MgServicePrincipal -Filter "appId eq '00000002-0000-0ff1-ce00-000000000000'"
# Exchange.ManageAsApp (dc50a0fb-09a3-484d-be87-e023b12c6440 in every tenant)
$role = $exo.AppRoles | Where-Object { $_.Value -eq "Exchange.ManageAsApp" }
New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $mi.Id -PrincipalId $mi.Id -ResourceId $exo.Id -AppRoleId $role.Id
# Then assign an Entra role (Exchange Administrator, or Exchange Recipient Administrator for less)
$roleDef = Get-MgRoleManagementDirectoryRoleDefinition -Filter "DisplayName eq 'Exchange Recipient Administrator'"
New-MgRoleManagementDirectoryRoleAssignment -PrincipalId $mi.Id -RoleDefinitionId $roleDef.Id -DirectoryScopeId "/"
Repeat the app-role step for each resource the host must call (for Graph, the Microsoft Graph service principal and the specific application permission). The API permission authorizes the connection; the Entra role decides which cmdlets run. Learn lists the supported Entra roles for the Exchange managed identity (Exchange Administrator, Exchange Recipient Administrator, Security Administrator, Global Reader, and others).
Do not grant Organization.ReadWrite.All as a shortcut for Teams administration: it permits organization-level Graph changes and is not a Teams administrator role. Follow the module-specific application-authentication procedure and verify the exact commands required before granting write permissions.
Managed identities authenticate as the application, not as a user. This means:
- There is no user context: actions are performed as the service principal, not as "admin@contoso.us"
- Audit logs show the managed identity's service principal name, not the admin's UPN
- Permissions granted are application permissions, which are typically broader than delegated permissions
Mitigate by:
- Using one personal session host per administrator, restricting VM access, and limiting its application grants to approved operations
- Logging which user was signed into the AVD session when the managed identity was used (AVD sign-in logs correlate the user to the session host)
- Reviewing managed identity permission grants in recurring access reviews
Conditional Access
Create a CA policy requiring phishing-resistant MFA for admin access to the AVD broker:
Users:
- Include: Admin security group (e.g.,
AVD-Admin-Workstation-Users)
Target resources: Azure Virtual Desktop, Azure Virtual Desktop Client, Windows Cloud Login
Grant: Require authentication strength: Phishing-resistant MFA
This ensures the admin authenticates with FIDO2 or WHfB before reaching the session host. Once inside the session, the managed identity handles API authentication: no second authentication prompt.
Usage
Once configured, the admin workflow is:
- Open AVD client and connect to the admin session host
- Authenticate with FIDO2 key (or WHfB) at the Entra login prompt
- Open PowerShell inside the AVD session
- Connect using managed identity:
# Teams: certificate-based app authentication (managed identity is Commercial-only)
Connect-MicrosoftTeams -CertificateThumbprint "<thumbprint>" -ApplicationId "<appId>" -TenantId "<tenantId>"
# Graph API operations
Connect-MgGraph -Environment USGov -Identity
# Exchange Online administration
Connect-ExchangeOnline -ExchangeEnvironmentName O365USGovGCCHigh -ManagedIdentity -Organization contoso.onmicrosoft.us
# SharePoint administration (via PnP)
Connect-PnPOnline -Url https://contoso.sharepoint.us -AzureEnvironment USGovernmentHigh -ManagedIdentity
Beyond PowerShell: Managed Identities as Secretless Infrastructure
Managed identities are not limited to PowerShell admin sessions. They can replace stored credentials anywhere an Azure-hosted workload needs to access Microsoft APIs:
| Use case | What managed identity replaces |
|---|---|
| PowerShell admin modules (this scenario) | Passwords, certificates, FIDO2 workarounds |
| Azure Automation runbooks | Stored credentials or Run As accounts (deprecated) |
| Azure Functions calling Graph API | Client secrets in app settings |
| Logic Apps connecting to M365 | OAuth connection credentials |
| Key Vault access from VMs | Access policies based on service principal secrets |
| Azure DevOps / GitHub Actions | Workload identity federation replaces long-lived client secrets |
The principle is the same: the Azure resource has an identity issued by Entra, and that identity authenticates to APIs without an operator-managed long-lived secret. Access tokens are still issued and transmitted and must be protected.
Key Vault is often deployed to store secrets that managed identities make unnecessary. If the workload consuming the secret runs on Azure (VMs, App Service, Functions, AKS), evaluate whether a managed identity can authenticate directly to the target API instead of retrieving a secret from Key Vault. This removes a dependency, reduces latency, and eliminates the secret lifecycle entirely.
📩 Don't Miss the Next Solution
Join the list to see the real-time solutions I'm delivering to my GCC High clients.