Scenario: AVD — Privileged Admin Workstation
The Problem This Solves
Several Microsoft PowerShell admin modules do not support FIDO2 passkey or Windows Hello for Business authentication. Microsoft's own documentation confirms this:
"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."
For organizations enforcing phishing-resistant MFA as a Conditional Access requirement — which CMMC Level 2 effectively mandates — this creates a gap: admins who need to run Teams PowerShell, SharePoint Online PowerShell, or other legacy modules cannot authenticate with their phishing-resistant credentials. The common workaround is to exempt these admin accounts from the phishing-resistant MFA requirement, which defeats the purpose.
The solution: Run admin PowerShell sessions inside an AVD session host that is secured with phishing-resistant authentication. The admin authenticates to the AVD broker with FIDO2 or WHfB. Inside the session, PowerShell modules authenticate using a managed identity assigned to the session host VM — no passwords, no certificates, no FIDO2 prompts, zero credentials stored or typed.
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-MicrosoftTeams -Identity, Connect-MgGraph -Identity, etc. |
The phishing-resistant authentication happens at the session boundary. The managed identity provides zero-credential access to the API. The admin never types a password or handles a certificate.
Which PowerShell Modules Support Managed Identity
| Module | Managed identity support | Connection command |
|---|---|---|
| Microsoft Teams | Yes | Connect-MicrosoftTeams -Identity |
| Microsoft Graph | Yes | Connect-MgGraph -Identity |
| Exchange Online | Yes | Connect-ExchangeOnline -ManagedIdentity -Organization contoso.onmicrosoft.us |
| SharePoint Online (PnP) | Yes | Connect-PnPOnline -Url https://contoso.sharepoint.us -ManagedIdentity |
| SharePoint Online Management Shell | No — use PnP or Graph instead | N/A |
| Azure Az module | Yes | Connect-AzAccount -Identity |
| Security & Compliance | No native managed identity — use Connect-IPPSSession with certificate-based auth as fallback | Certificate on session host |
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. This is still zero-password — the certificate is bound to the machine, not typed by the user.
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. You must grant the necessary Graph API application permissions to each session host's managed identity.
Example: Teams admin session host
# Connect to Graph with admin credentials (one-time setup)
Connect-MgGraph -Environment USGov -Scopes "AppRoleAssignment.ReadWrite.All"
# Get the managed identity's service principal
$miObjectId = (Get-MgServicePrincipal -Filter "displayName eq 'avd-admin-teams-01'").Id
# Get the Microsoft Graph service principal
$graphSP = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'"
# Find the Teams admin app role (example: Organization.ReadWrite.All)
$appRole = $graphSP.AppRoles | Where-Object { $_.Value -eq "Organization.ReadWrite.All" }
# Grant the permission to the managed identity
New-MgServicePrincipalAppRoleAssignment `
-ServicePrincipalId $miObjectId `
-PrincipalId $miObjectId `
-ResourceId $graphSP.Id `
-AppRoleId $appRole.Id
Repeat for each Graph permission the admin role requires. Follow least privilege — grant only the specific app roles needed for the admin's function, not broad directory-wide 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 session host per admin role (Teams admin, Exchange admin) with only the permissions that role needs
- 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 administration
Connect-MicrosoftTeams -Identity
# Graph API operations
Connect-MgGraph -Identity
# Exchange Online administration
Connect-ExchangeOnline -ManagedIdentity -Organization contoso.onmicrosoft.us
# SharePoint administration (via PnP)
Connect-PnPOnline -Url https://contoso.sharepoint.us -ManagedIdentity
No passwords typed. No certificates managed. No FIDO2 compatibility issues. The phishing-resistant authentication happened at the AVD broker; the managed identity provides the API access.
Beyond PowerShell: Managed Identities as Zero-Credential 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 any stored or transmitted credential. This eliminates an entire category of secret management — no Key Vault entries to rotate, no certificates to renew, no passwords to store.
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.