
YubiKey Bio with Microsoft Entra ID Conditional Access
Portal Configuration and Full PowerShell Setup
Practical deployment guide for Phishing-Resistant MFA using passkey (FIDO2) Security Keys
|
This document covers the portal workflow and a PowerShell-First deployment model. YubiKey Bio is used in Entra ID as a Passkey (FIDO2) Security Key. The Fingerprint Match occurs on the Key, and Conditional Access Enforces the required Authentication Strength. |
1. What Does This Solution Do?
This design enables Administrators or Selected Users to Sign in with a YubiKey Bio and satisfy a Phishing-Resistant Conditional Access requirement. The overall flow is straightforward: Enable Passkey (FIDO2) as an Authentication Method, Register the Key to the User Account, then create a Conditional Access Policy that requires the Built-In Phishing-Resistant MFA Authentication Strength for the chosen Cloud Apps.
For a Controlled Rollout, the recommended sequence is Pilot Group First, Report-Only Conditional Access Second, Enforcement Third, and Emergency Access Exclusions Throughout.
2. Prerequisites And Deployment Decisions
|
Requirement |
Details |
|
Licensing |
Conditional Access requires Microsoft Entra ID P1 or higher. Use P2 if you also need PIM and Identity Protection. |
|
Supported method |
YubiKey Bio is used as a passkey (FIDO2) security key. It is appropriate for phishing-resistant MFA. |
|
Admin roles |
At minimum, use roles that can manage Authentication methods policy and Conditional Access. In practice, Authentication Policy Administrator and Conditional Access Administrator are typical; Global Administrator also works. |
|
Pilot scope |
Use a dedicated security group for the first rollout. Do not start with All users. |
|
Emergency access |
Maintain at least two excluded break-glass accounts that are tested and documented before enforcing the policy. |
|
Browsers and clients |
Current Edge and Chrome support the registration and sign-in flow well. Keep users on modern authentication clients only. |
Recommended operational decision: Exclude Emergency Accounts, Pilot with a small Admin Group, and switch the Conditional Access Policy from Report-Only to On only after successful Sign-In testing.
3. Portal Configuration
3.1 Enable passkey (FIDO2) in Authentication methods
In the Microsoft Entra admin center, browse to Entra ID, Authentication methods, Policies, then open Passkey (FIDO2). Enable the method for the pilot group first. Allow self-service setup. If your organization wants to require only attested hardware keys, enable attestation and limit the scope to approved keys after validation.
3.2 Register the YubiKey Bio
The user opens Security info, adds a new sign-in method, selects Passkey, and then chooses the security key option in the browser flow. The user sets or confirms the key PIN if required and performs the biometric gesture on the key. After registration, the passkey becomes available as a sign-in method for that account.
3.3 Create the Conditional Access policy
Create a new Conditional Access policy and target the pilot security group. Choose the cloud apps you want to protect, typically Microsoft Admin Portals, Azure Management, Microsoft 365, or a selected set of sensitive applications. Under Grant, select Require authentication strength and choose Phishing-resistant MFA. Start in Report-only mode, test sign-ins, review logs, and then turn the policy On.
3.4 Recommended first rollout settings
· Assignments: Pilot security group only
· Cloud apps: Microsoft Admin Portals or another sensitive app set
· Exclusions: Break-glass accounts
· Grant: Require authentication strength = Phishing-resistant MFA
· Enable policy: Report-only first, then On after validation
4. Full PowerShell Setup
The most reliable PowerShell approach today is to use the Microsoft Graph PowerShell SDK for authentication and lookup operations, and use Invoke-MgGraphRequest for the policy payloads. This avoids schema drift between portal labels and cmdlet object models. The script below is structured for a pilot deployment and can be adapted to production.
4.1 Install modules and connect to Microsoft Graph
Install-Module Microsoft.Graph -Scope CurrentUser
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Identity.SignIns
Import-Module Microsoft.Graph.Groups
Import-Module Microsoft.Graph.Users
Connect-MgGraph -Scopes \
"Policy.ReadWrite.AuthenticationMethod", \
"Policy.ReadWrite.ConditionalAccess", \
"Policy.Read.All", \
"Group.Read.All", \
"Directory.Read.All", \
"UserAuthenticationMethod.Read.All"
Get-MgContext
4.2 Define your rollout variables
$PilotGroupDisplayName = "SG-Entra-YubiKeyBio-Pilot"
$BreakGlassDisplayName1 = "Emergency Access 1"
$BreakGlassDisplayName2 = "Emergency Access 2"
$PolicyName = "Require phishing-resistant MFA for YubiKey Bio pilot"
$State = "enabledForReportingButNotEnforced" # change later to enabled
$IncludeApplications = @(
"MicrosoftAdminPortals"
)
# Optional named location IDs can be added later if you want location-based scoping.
4.3 Resolve group and emergency account identifiers
$PilotGroup = Get-MgGroup -Filter "displayName eq '$PilotGroupDisplayName'"
if (-not $PilotGroup) { throw "Pilot group not found: $PilotGroupDisplayName" }
$BreakGlass1 = Get-MgUser -Filter "displayName eq '$BreakGlassDisplayName1'"
$BreakGlass2 = Get-MgUser -Filter "displayName eq '$BreakGlassDisplayName2'"
if (-not $BreakGlass1 -or -not $BreakGlass2) {
throw "One or more emergency access accounts were not found."
}
$ExcludeUserIds = @($BreakGlass1.Id, $BreakGlass2.Id)
4.4 Inspect the built-in authentication strengths and capture the Phishing-resistant MFA ID
$AuthStrengths = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/policies/authenticationStrengthPolicies"
$PhishResistant = $AuthStrengths.value | Where-Object { $_.displayName -eq "Phishing-resistant MFA" }
if (-not $PhishResistant) {
throw "Built-in authentication strength 'Phishing-resistant MFA' was not found."
}
$PhishResistant.id
$PhishResistant.allowedCombinations
4.5 Review the current passkey (FIDO2) method policy
Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/Fido2" | ConvertTo-Json -Depth 10
4.6 Enable passkey (FIDO2) for the pilot group
This example enables the passkey method, allows self-service registration, scopes the method to the pilot group, and keeps the configuration simple. If you later want to enforce only approved hardware keys, you can extend the configuration with attestation or a custom authentication strength restricted by AAGUID.
$Fido2Body = @{
state = "enabled"
isSelfServiceRegistrationAllowed = $true
keyRestrictions = @{
isEnforced = $false
aaGuids = @()
enforcementType = "allow"
}
includeTargets = @(
@{
id = $PilotGroup.Id
targetType = "group"
isRegistrationRequired = $false
}
)
excludeTargets = @()
} | ConvertTo-Json -Depth 10
Invoke-MgGraphRequest -Method PATCH \
-Uri "https://graph.microsoft.com/v1.0/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/Fido2" \
-Body $Fido2Body \
-ContentType "application/json"
4.7 Create the Conditional Access policy that requires phishing-resistant MFA
This policy targets the pilot group, excludes the emergency access accounts, protects Microsoft Admin Portals, and starts in report-only mode. After testing, change the state variable to enabled and update the policy.
$CaBody = @{
displayName = $PolicyName
state = $State
conditions = @{
users = @{
includeGroups = @($PilotGroup.Id)
excludeUsers = $ExcludeUserIds
}
applications = @{
includeApplications = $IncludeApplications
}
clientAppTypes = @(
"all"
)
}
grantControls = @{
operator = "AND"
authenticationStrength = @{
id = $PhishResistant.id
}
}
} | ConvertTo-Json -Depth 20
$NewPolicy = Invoke-MgGraphRequest -Method POST \
-Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" \
-Body $CaBody \
-ContentType "application/json"
$NewPolicy | ConvertTo-Json -Depth 10
4.8 Validate the deployed policy
Get-MgIdentityConditionalAccessPolicy | Where-Object DisplayName -eq $PolicyName | Format-List Id,DisplayName,State
Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/Fido2" | ConvertTo-Json -Depth 10
4.9 Change report-only to enforced after validation
$ExistingPolicy = Get-MgIdentityConditionalAccessPolicy | Where-Object DisplayName -eq $PolicyName
$UpdateBody = @{
state = "enabled"
} | ConvertTo-Json
Invoke-MgGraphRequest -Method PATCH \
-Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies/$($ExistingPolicy.Id)" \
-Body $UpdateBody \
-ContentType "application/json"
4.10 Rollback examples
# Put the Conditional Access policy back into report-only
$RollbackBody = @{ state = "enabledForReportingButNotEnforced" } | ConvertTo-Json
Invoke-MgGraphRequest -Method PATCH \
-Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies/$($ExistingPolicy.Id)" \
-Body $RollbackBody \
-ContentType "application/json"
# Disable the passkey (FIDO2) method if you need to back out the pilot
$DisableFido2Body = @{
state = "disabled"
} | ConvertTo-Json
Invoke-MgGraphRequest -Method PATCH \
-Uri "https://graph.microsoft.com/v1.0/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/Fido2" \
-Body $DisableFido2Body \
-ContentType "application/json"
5. User Registration And Verification
After the method is enabled and before the Conditional Access policy is enforced, have pilot users register their YubiKey Bio through Security info. Once complete, verify that the passkey is visible as a registered method for the account.
$UserPrincipalName = "admin1@contoso.com"
$Methods = Get-MgUserAuthenticationMethod -UserId $UserPrincipalName
$Methods | Format-Table Id,AdditionalProperties
The exact registration experience is interactive and user-driven. PowerShell is used primarily to enable policy, verify scope, and audit what methods are registered.
6. Recommended Production Hardening
· Keep at least two emergency access accounts excluded from this policy and protect them with separate strong controls.
· Use a dedicated pilot group first. Do not target all users until you validate browser, device, and application behavior.
· Prefer report-only mode before enforcement and review sign-in logs to confirm the authentication strength result.
· For highly sensitive resources, consider a custom authentication strength restricted to approved FIDO2 AAGUIDs after testing.
· Keep legacy authentication blocked and avoid weaker MFA fallback for privileged roles whenever possible.
7. Troubleshooting Notes
|
Symptom |
What to check |
|
User cannot add the key |
Confirm that Passkey (FIDO2) is enabled for the user or group in Authentication methods policy and that self-service registration is allowed. |
|
Conditional Access blocks the user unexpectedly |
Check whether the user is in scope of the policy, whether a break-glass exclusion is missing, and whether the policy was switched from report-only to enabled earlier than intended. |
|
Browser does not present security key option |
Use a current version of Edge or Chrome and verify that the sign-in is using a modern authentication flow. |
|
A nonapproved key is accepted |
Move from the built-in Phishing-resistant MFA strength to a custom authentication strength and restrict passkeys by AAGUID after validation. |
|
Admin lockout concern |
Validate exclusions first and test emergency access accounts before enabling enforcement for privileged roles. |
8. Operational Summary
The clean enterprise pattern is simple: enable Passkey (FIDO2), register the YubiKey Bio, require the built-in Phishing-resistant MFA authentication strength with Conditional Access, and pilot in report-only mode before enforcement. The PowerShell workflow in this document is designed to keep the deployment controlled, reversible, and suitable for privileged access scenarios.
0 comments