Verifying User Phone Numbers Against MFA Settings with Microsoft Graph PowerShell
Verifying User Phone Numbers Against MFA Settings with Microsoft Graph PowerShell
Section titled “Verifying User Phone Numbers Against MFA Settings with Microsoft Graph PowerShell”Overview
Section titled “Overview”Ensuring that user phone numbers are accurately configured in both their profile and multi-factor authentication (MFA) settings is critical for maintaining robust security in an organization. This article details how to use a PowerShell script leveraging the Microsoft Graph API to verify that users’ primary phone numbers match their MFA phone numbers.
The script automates the process of comparing phone numbers, checking for any discrepancies that could potentially lead to authentication issues or security risks. This can be especially useful for IT administrators who need to audit and clean up user phone number configurations across the organization.
Key Features
Section titled “Key Features”| Feature | Capability | Business Value |
|---|---|---|
| Automated Phone Number Verification | Compare user profile phone numbers with MFA authentication methods | Identifies authentication configuration issues before they cause access problems |
| Smart Number Matching | Uses 6-digit matching algorithm to account for formatting differences | Reduces false positives from phone number formatting variations |
| Comprehensive User Coverage | Processes all enabled member users in the organization | Ensures complete security audit coverage across the user base |
| Detailed Reporting | Provides clear output for each user’s phone number status | Enables targeted remediation of configuration issues |
Implementation Script
Section titled “Implementation Script”# Install the Microsoft Graph PowerShell SDK (if not already installed)if (-not (Get-Module -ListAvailable -Name "Microsoft.Graph")) { Install-Module Microsoft.Graph -Scope CurrentUser -Force}
# Connect to Microsoft GraphConnect-MgGraph -Scopes "User.Read.All", "UserAuthenticationMethod.Read.All"
# Function to get user phone numberfunction Get-UserPhoneNumber { param ( [string]$userId )
$user = Get-MgUser -UserId $userId return $user.MobilePhone}
# Function to get MFA phone numbersfunction Get-MfaPhoneNumbers { param ( [string]$userId )
# Get all phone authentication methods for the user $phoneMethods = Get-MgUserAuthenticationPhoneMethod -UserId $userId return $phoneMethods}
# Function to clean phone numbers (remove hyphens)function Clean-PhoneNumber { param ( [string]$phoneNumber )
return $phoneNumber -replace '-', ''}
# Function to check if at least 6 digits matchfunction Check-PhoneNumberMatch { param ( [string]$primaryNumber, [string[]]$mfaNumbers )
$primaryDigits = ($primaryNumber -replace '\D', '') # Remove all non-digit characters
foreach ($mfaNumber in $mfaNumbers) { $mfaDigits = ($mfaNumber -replace '\D', '') # Remove all non-digit characters
$matchCount = ($primaryDigits.ToCharArray() | Where-Object { $mfaDigits.Contains($_) }).Count if ($matchCount -ge 6) { return $true } } return $false}
# Get a list of users (excluding guest users)$users = Get-MgUser -Filter "accountEnabled eq true and userType eq 'Member'"
# Iterate over each user and compare phone numbersforeach ($user in $users) { $userId = $user.Id $userPhoneNumber = Get-UserPhoneNumber -userId $userId $mfaPhoneNumbers = Get-MfaPhoneNumbers -userId $userId
if (-not [string]::IsNullOrWhiteSpace($userPhoneNumber)) { $cleanUserPhoneNumber = Clean-PhoneNumber -phoneNumber $userPhoneNumber
$cleanMfaPhoneNumbers = @() if ($mfaPhoneNumbers) { foreach ($mfaPhone in $mfaPhoneNumbers) { $cleanMfaPhoneNumbers += Clean-PhoneNumber -phoneNumber $mfaPhone.PhoneNumber }
$isMatching = Check-PhoneNumberMatch -primaryNumber $cleanUserPhoneNumber -mfaNumbers $cleanMfaPhoneNumbers
Write-Output "User: $($user.DisplayName)" Write-Output "User Phone Number: $cleanUserPhoneNumber"
if ($isMatching) { Write-Output "At least 6 digits match with MFA phone numbers." } else { Write-Output "No match with MFA phone numbers." } } else { Write-Output "No MFA phone numbers found." }
Write-Output "-------------------------------------------" } else { Write-Output "User: $($user.DisplayName) - No primary phone number found." }}Script Logic
Section titled “Script Logic”Matching Algorithm
Section titled “Matching Algorithm”The script uses a 6-digit matching algorithm to determine if phone numbers are equivalent:
- Removes all non-digit characters from both numbers
- Compares digit sequences to find at least 6 matching digits
- Accounts for formatting differences (hyphens, spaces, parentheses)
Processing Flow
Section titled “Processing Flow”- User Enumeration: Retrieves all enabled member users
- Phone Number Extraction: Gets primary phone number from user profile
- MFA Method Retrieval: Fetches all phone-based authentication methods
- Comparison: Applies matching algorithm to determine equivalence
- Reporting: Outputs detailed results for each user
Security Benefits
Section titled “Security Benefits”Key Takeaway: Regular phone number verification prevents authentication failures and ensures users can successfully complete MFA challenges, reducing helpdesk tickets and maintaining security posture.
Troubleshooting
Section titled “Troubleshooting”- Missing MFA Phone Numbers: Users may have alternative MFA methods (app, email) configured
- Format Differences: The cleaning function handles common formatting variations
- Permission Issues: Ensure proper Graph API permissions are granted for user and authentication method reading