Skip to main content
Dark green background, "Weak Application Security Can Cost You Millions," 3 slanted images of fingers pointing to digital locks, and a "Learn the Basics" button
Passkey Enrollment Script for Microsoft Entra IDIdentity & Access Management
4 min readFor CISOs

Passkey Enrollment Script for Microsoft Entra ID

Starting September 1, 2026, Microsoft will make passkeys the default authentication method. To avoid a help desk crisis, you'll need a systematic way to transition users from SMS and voice authentication. Here's a practical enrollment campaign template to help your team manage this change effectively.

What This Template Does

This PowerShell script automates the passkey enrollment process in Microsoft Entra ID. It identifies users still relying on SMS or voice authentication, enables them for passkey registration, and prompts them during their next multifactor authentication attempt. The script includes checks to ensure users who haven't registered alternative methods aren't locked out.

Use this script before September 1, 2026, to control the transition timeline and avoid being caught unprepared by Microsoft's automatic rollout.

Prerequisites

Before running this script, ensure:

  • Microsoft Entra ID P1 or P2 licensing for the registration campaign feature
  • Global Administrator or Authentication Policy Administrator role in your tenant
  • Microsoft Graph PowerShell SDK installed (Install-Module Microsoft.Graph -Scope CurrentUser)
  • Audit of current authentication methods to identify users who might lose access if SMS/voice is discontinued without a replacement
  • User communication plan ready to inform users about the change

Your communication plan is crucial. Microsoft Threat Intelligence reports AI-enabled phishing campaigns have click-through rates as high as 54%, compared to 12% for traditional campaigns. Users need to understand why this change is necessary, not just how to complete it.

The Enrollment Campaign Script

# Connect to Microsoft Graph with required permissions
Connect-MgGraph -Scopes "Policy.ReadWrite.AuthenticationMethod", "UserAuthenticationMethod.ReadWrite.All", "User.Read.All"

# Step 1: Identify users currently using SMS or voice authentication
$smsVoiceUsers = Get-MgUser -All | Where-Object {
    $userId = $_.Id
    $authMethods = Get-MgUserAuthenticationMethod -UserId $userId
    $authMethods.AdditionalProperties.'@odata.type' -contains '#microsoft.graph.phoneAuthenticationMethod'
}

Write-Host "Found $($smsVoiceUsers.Count) users with SMS/voice authentication enabled"

# Step 2: Create a security group for targeted passkey rollout
$groupParams = @{
    DisplayName = "Passkey Enrollment Wave 1"
    MailEnabled = $false
    MailNickname = "PasskeyWave1"
    SecurityEnabled = $true
    Description = "Users targeted for initial passkey enrollment campaign"
}

$enrollmentGroup = New-MgGroup -BodyParameter $groupParams

# Step 3: Add users to the enrollment group (start with pilot users)
$pilotUsers = $smsVoiceUsers | Select-Object -First 50

foreach ($user in $pilotUsers) {
    New-MgGroupMember -GroupId $enrollmentGroup.Id -DirectoryObjectId $user.Id
    Write-Host "Added $($user.UserPrincipalName) to enrollment group"
}

# Step 4: Configure the authentication method policy for passkeys
$passkeyPolicy = @{
    "@odata.type" = "#microsoft.graph.fido2AuthenticationMethodConfiguration"
    state = "enabled"
    isSelfServiceRegistrationAllowed = $true
    isAttestationEnforced = $false
    includeTargets = @(
        @{
            targetType = "group"
            id = $enrollmentGroup.Id
            isRegistrationRequired = $false
        }
    )
}

Update-MgPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration `
    -AuthenticationMethodConfigurationId "Fido2" `
    -BodyParameter $passkeyPolicy

# Step 5: Enable registration campaign
$campaignConfig = @{
    state = "enabled"
    excludeTargets = @()
    includeTargets = @(
        @{
            targetedAuthenticationMethod = "microsoftAuthenticator"
            targetType = "group"
            id = $enrollmentGroup.Id
        }
    )
    snoozeDurationInDays = 3
}

Update-MgPolicyAuthenticationMethodPolicyRegistrationEnforcement `
    -BodyParameter $campaignConfig

Write-Host "Passkey enrollment campaign configured for $($pilotUsers.Count) pilot users"
Write-Host "Users will be prompted to register a passkey at next MFA sign-in"

How to Customize It

Adjust the pilot group size: Change Select-Object -First 50 to suit your organization's risk tolerance. Start with technical users or a single department.

Target specific user attributes: Replace the pilot selection logic with filters based on department, location, or authentication method strength. For example:

$pilotUsers = $smsVoiceUsers | Where-Object {
    $_.Department -eq "IT" -or $_.JobTitle -like "*Security*"
}

Configure attestation requirements: Set isAttestationEnforced = $true if you need cryptographic proof that passkeys come from trusted authenticators. This is important for regulated environments.

Modify snooze duration: The snoozeDurationInDays = 3 parameter controls how often users see the registration prompt if they dismiss it. Shorter durations increase pressure but may also increase help desk calls.

Add exclusion groups: If certain users must keep SMS/voice past February 1, 2027, create an exclusion group:

excludeTargets = @(
    @{
        targetType = "group"
        id = "your-exclusion-group-id"
    }
)

Validation Steps

After running the script, verify the configuration:

Check the authentication method policy:

Get-MgPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration `
    -AuthenticationMethodConfigurationId "Fido2"

Ensure the state shows "enabled" and your target group appears in includeTargets.

Test with a pilot user account: Sign in as a member of the enrollment group and trigger multifactor authentication. You should see a prompt to register a passkey. If not, check that the user has an MFA-triggering policy applied.

Monitor registration progress:

$enrolledUsers = Get-MgUser -All | Where-Object {
    $userId = $_.Id
    $authMethods = Get-MgUserAuthenticationMethod -UserId $userId
    $authMethods.AdditionalProperties.'@odata.type' -contains '#microsoft.graph.fido2AuthenticationMethod'
}

Write-Host "$($enrolledUsers.Count) users have registered passkeys"

Run this weekly to track adoption rates. If fewer than 60% of targeted users register within two weeks, review your user communication or help desk readiness.

Verify fallback authentication: Before expanding beyond your pilot group, confirm users who dismiss the passkey prompt can still authenticate with existing methods. Microsoft's automatic rollout won't lock users out, but your custom campaign might if misconfigured.

Review sign-in logs for errors:

Get-MgAuditLogSignIn -Filter "status/errorCode ne 0" -Top 100

Look for authentication failures tied to your pilot group. Common issues include unsupported browsers or devices without biometric capabilities.

This script gives you control over the transition timeline and user experience. Waiting for Microsoft's automatic rollout could overwhelm your help desk when users encounter the passkey prompt. By February 1, 2027, aim to have most users on phishing-resistant methods.

Promotional banner graphic asking if you are ready for PCI DSS 4.0 with a call-to-action to get the guide

You Might Also Like