Back to script library
Entra / Microsoft 365 · Users & guests

Get users with phone MFA method

Find user accounts with a phone-based MFA method so administrators can email them to register a stronger authentication method.

Connect & set up

Run these once per session. All scopes are read-only unless the script makes changes.

Connect-MgGraph -NoWelcome -AppId $AppId -TenantId $TenantId -CertificateThumbprint $Thumbprint

Run it

The main script. Copy it, or download the .ps1 and run it from your console.

param(
[string] $TenantId = "",
[string] $AppId = ""
)
$Thumbprint = '32C9529B1FFD08BCD483A5D98807E47A472C5318'
Connect-MgGraph -NoWelcome -AppId $AppId -TenantId $TenantId -CertificateThumbprint $Thumbprint
# Find licensed user accounts
[array]$Users = Get-MgUser -Filter "assignedLicenses/`$count ne 0 and userType eq 'Member'" `
-ConsistencyLevel eventual -CountVariable UsersFound -Sort "displayName" `
-Property Id, DisplayName, GivenName , UserPrincipalName, UserType, Mail
If (!$Users) {
Write-Host "No user accounts found"
Exit
}
Write-Output ("Checking MFA methods for {0} user accounts" -f $UsersFound)
$Report = [System.Collections.Generic.List[Object]]::new()
ForEach ($User in $Users) {
Write-Host ("Checking MFA methods for {0}" -f $User.UserPrincipalName)
$Method = $null; $SystemPreferred = $false
$Methods = Get-MgBetaUserAuthenticationSignInPreference -UserId $User.Id
If ($Methods.IsSystemPreferredAuthenticationMethodEnabled) {
Write-Host ("User {0} has system preferred method enabled" -f $User.UserPrincipalName)
$SystemPreferred = $true
}
# Figure out what secondary method the account uses
Switch ($Methods.UserPreferredMethodForSecondaryAuthentication) {
'push' {
Write-Host ("User {0} uses the Authenticator app for their MFA method" -f $User.UserPrincipalName)
$Method = "App"
}
'oauth' {
Write-Host ("User {0} uses OAuth Token MFA method" -f $User.UserPrincipalName)
$Method = "Oauth Token"
}
'voiceMobile' {
Write-Host ("User {0} uses Voice to Mobile for their MFA method" -f $User.UserPrincipalName)
$Method = "Voice Mobile"
}
'voiceAlternateMobile' {
Write-Host ("User {0} uses Voice to Alternate Mobile their MFA method" -f $User.UserPrincipalName)
$Method = "Voice Mobile Alternate"
}
'voiceOffice' {
Write-Host ("User {0} uses Voice to Office Phone for their MFA method" -f $User.UserPrincipalName)
$Method = "Voice Office"
}
'sms' {
Write-Host ("User {0} uses a phone for their MFA method" -f $User.UserPrincipalName)
$Method = "SMS"
}
}
If ($null -eq $Methods.UserPreferredMethodForSecondaryAuthentication) {
Write-Host ("User {0} has no MFA method" -f $User.UserPrincipalName)
$Method = "None"
}
$DataLine = [PSCustomObject][Ordered]@{
UserPrincipalName = $User.UserPrincipalName
DisplayName = $User.DisplayName
GivenName = $User.GivenName
Method = $Method
Mail = $User.Mail
'System Preferred' = $SystemPreferred
}
$Report.Add($DataLine)
}
# Define domains and specific users that we don't want to send nagging emails to
[array]$UserNoNag = 'Azure.Management.Account@office365itpros.com'
[array]$DomainsNoNag = 'office365itpros.org','contoso.com'
# Find people using SMS as the authentication method that aren't in the excluded list of accounts or domains
[array]$UsersToNag = $Report | Where-Object {
($_.Method -eq 'SMS') -and ($_.UserPrincipalName -notin $UserNoNag) -and `
($_.UserPrincipalName.Split('@')[1] -notin $DomainsNoNag)
}
# Do the same for users who have no MFA method
[array]$UsersNoMFA = $Report | Where-Object {
($_.Method -eq 'None') -and ($_.UserPrincipalName -notin $UserNoNag) -and `
($_.UserPrincipalName.Split('@')[1] -notin $DomainsNoNag)
}
Write-Host ("{0} users selected for nagging because they use the SMS MFA method" -f $UsersToNag.Count)
Write-Host ("{0} users selected for nagging because their account has no MFA method" -f $UsersNoMFA.Count)
# Send Email to the users with SMS MFA method - first define the message sender, which can be the SMTP address for a user or shared mailbox
$MsgFrom = 'Customer.Services@office365itpros.com'
# Define some variables used to construct the HTML content in the message body
#HTML header with styles
$HtmlHead="<html>
<style>
BODY{font-family: Arial; font-size: 10pt;}
H1{font-size: 22px;}
H2{font-size: 18px; padding-top: 10px;}
H3{font-size: 16px; padding-top: 8px;}
H4{font-size: 8px; padding-top: 4px;}
</style>"
$MsgSubject = "Important: Please upgrade your MFA method"
ForEach ($User in $UsersToNag) {
Write-Host ("Sending email to {0} to ask them to change their MFA method" -f $User.UserPrincipalName)
$ToRecipients = @{}
$ToRecipients.Add("emailAddress",@{'address'=$User.Mail})
[array]$MsgTo = $ToRecipients
# Customize the message
$HtmlHeaderUser = "<h2>"+ $User.DisplayName + ": It's time to say goodbye to SMS authentications</h2>"
#Content for the message - obviously, this is very customizable and should reflect what you want to say to new users
$HtmlBody = "<body>
<h1>SMS responses to Multifactor Challenges are no longer secure enough!</h1>
<h2><u>We need you to increase the strength of your multifactor authentication</u></h2>
<p><b>Dear $($User.GivenName),</b></p>
<p>Our records show that you use SMS to respond to multifactor authentication challenges. In other words, you receive a code via SMS and enter that number when prompted by Entra ID.</p>
<p>SMS was a great method some years ago, but now it's prone to compromise. We need you to upgrade to a more secure authentication method, such as the Microsoft Authenticator app, which is free and easy to use.</p>
<p>To learn more about the Authenticator app, please <a href=https://support.microsoft.com/en-us/account-billing/about-microsoft-authenticator-9783c865-0308-42fb-a519-8cf666fe0acc>click here</a> </p>
<p>Have a great time and be sure to call the help desk if you need assistance. And please read all the great articles about Microsoft 365 published on <a href=https://Practical365.com>Practical365.com</a>.</p>
<p><p>
<p><h4>Generated:</strong> $(Get-Date -Format g)</h4></p>"
$HtmlMsg = "</body></html>" + $HtmlHead + $Htmlheaderuser + $HtmlBody + "<p>"
# Construct the message body
$MsgBody = @{}
$MsgBody.Add('Content', "$($HtmlMsg)")
$MsgBody.Add('ContentType','html')
$Message = @{}
$Message.Add('subject', $MsgSubject)
$Message.Add('toRecipients', $MsgTo)
$Message.Add('body', $MsgBody)
$Params = @{}
$Params.Add('message', $Message)
$Params.Add('saveToSentItems', $true)
$Params.Add('isDeliveryReceiptRequested', $true)
Send-MgUserMail -UserId $MsgFrom -BodyParameter $Params
}
Write-Host ""
Write-Host ("All done - nagging emails sent to {0} users" -f $UsersToNag.Count)
$UsersToNag | Format-Table DisplayName, Mail -AutoSize

Parameters

ParameterDefaultNotes
-TenantId""Microsoft Entra tenant ID for app-only Graph authentication.
-AppId""Application (client) ID for the app registration used to connect.
Attribution