In Azure AD, we all know that telecom, SMS and voice calls, as a MFA factor is less secure than more modern methods like Microsoft Authenticator, Windows Hello for Business, and FIDO2. There have been multiple reports over the years where attackers have tricked users, or the telecom providers, to change SIM, forward calls and SMS, etc, to steal MFA one-time-passcodes from the user. The industry is moving forward and passwordless solutions is the new thing. When you have left the insecure past, let’s clean up the old telecom mess in your Azure AD!

I’ve recently been playing around with the Graph API to do such a cleanup, to remove all registered phone methods from the users authentication methods. Of course, you can (and should) first disable the possibility to authenticate with SMS and voice calls in the MFA portal.
MFA settings: https://account.activedirectory.windowsazure.com/UserManagement/MfaSettings.aspx

Remember to also move to the Authenticator app in SSPR if you use that feature.
Ones these methods are disabled, I also like to clean up all registered phone methods and numbers on the user accounts in Azure AD. And some might say, “shouldn’t we keep them as a fallback?”, and some of you might do just that. But I’m afraid to leave such a tempting fallback solution in front of non-security focused admins. If you should have a major issue with MFA, the new Resilience defaults in Conditional Access will most likely keep your business going during the outage.
The PowerShell Script
This script fetches all Azure AD users with registered phone methods like mobile and office phones, and then deletes those methods from the user. The script can’t delete a phone method if it is set as the default method by the user, and there is currently (as of 7/10 2021) a limit in the Graph API to manage the default method. In those cases you’ll have to ask your users to change the preferred method before running the script, but I bet that if you recently moved to a more modern authentication method for your entire business, most users have already switched the default method automatically to the Authenticator app or FIDO2.
Be aware: By running this script, you will delete all users registered phone methods in your Azure AD. Don’t do this if you’re not fully migrated to the Microsoft Authenticator app or other strong methods. Analyse your current status in this Azure AD report: https://portal.azure.com/#blade/Microsoft_AAD_IAM/AuthenticationMethodsMenuBlade/AuthMethodsActivity

This is the script:
### Clean up phone authentication methods for all Azure AD users ### <# Set the registered applications ClientID and ClientSecret further down. This script requires the following Microsoft Graph permissions: Delegated: UserAuthenticationMethod.ReadWrite.All Reports.Read.All It also requires the DCToolbox PowerShell module: Install-Module -Name DCToolbox -Force Note that this script cannot delete a users phone method if it is set as the default authentication method. Microsoft Graph cannot, as of 7/10 2021, manage the default authentication method for users in Azure AD. Hopefully the users method of choice was changed when he/she switched to the Microsoft Authenticator app or another MFA/passwordless authentication method. If not, ask them to change the default method before running the script. Use the following report to understand how many users are registered for phone authentication (can lag up to 48 hours): https://portal.azure.com/#blade/Microsoft_AAD_IAM/AuthenticationMethodsMenuBlade/AuthMethodsActivity #> # Connect to Microsoft Graph with delegated permissions. Write-Verbose -Verbose -Message 'Connecting to Microsoft Graph...' $Parameters = @{ ClientID = '' ClientSecret = '' } $AccessToken = Connect-DCMsGraphAsDelegated @Parameters # Fetch all users with phone authentication enabled from the Azure AD authentication usage report (we're using this usage report to save time and resources when querying Graph, but their might be a 24 hour delay in the report data). Write-Verbose -Verbose -Message 'Fetching all users with any phone authentication methods registered...' $Parameters = @{ AccessToken = $AccessToken GraphMethod = 'GET' GraphUri = "https://graph.microsoft.com/beta/reports/credentialUserRegistrationDetails?`$filter=authMethods/any(t:t eq microsoft.graph.registrationAuthMethod'mobilePhone') or authMethods/any(t:t eq microsoft.graph.registrationAuthMethod'officePhone')" } $AllUsersWithPhoneAuthentication = Invoke-DCMsGraphQuery @Parameters # Output the number of users found. Write-Verbose -Verbose -Message "Found $($AllUsersWithPhoneAuthentication.Count) users!" # Loop through all those users. $ProgressCounter = 0 foreach ($User in $AllUsersWithPhoneAuthentication) { # Show progress bar. $ProgressCounter += 1 [int]$PercentComplete = ($ProgressCounter / $AllUsersWithPhoneAuthentication.Count) * 100 Write-Progress -PercentComplete $PercentComplete -Activity "Processing user $ProgressCounter of $($AllUsersWithPhoneAuthentication.Count)" -Status "$PercentComplete% Complete" # Retrieve a list of registered phone authentication methods for the user. This will return up to three objects, as a user can have up to three phones usable for authentication. Write-Verbose -Verbose -Message "Fetching phone methods for $($User.userPrincipalName)..." $Parameters = @{ AccessToken = $AccessToken GraphMethod = 'GET' GraphUri = "https://graph.microsoft.com/beta/users/$($User.userPrincipalName)/authentication/phoneMethods" } $phoneMethods = Invoke-DCMsGraphQuery @Parameters <# The value of id corresponding to the phoneType to delete is one of the following: b6332ec1-7057-4abe-9331-3d72feddfe41 to delete the alternateMobile phoneType. e37fc753-ff3b-4958-9484-eaa9425c82bc to delete the office phoneType. 3179e48a-750b-4051-897c-87b9720928f7 to delete the mobile phoneType. #> # Loop through all user phone methods. foreach ($phoneMethod in $phoneMethods) { # Delete the phone method. try { if ($phoneMethod.phoneType) { Write-Verbose -Verbose -Message "Deleting phone method '$($phoneMethod.phoneType)' for $($User.userPrincipalName)..." $Parameters = @{ AccessToken = $AccessToken GraphMethod = 'DELETE' GraphUri = "https://graph.microsoft.com/beta/users/$($User.userPrincipalName)/authentication/phoneMethods/$($phoneMethod.id)" } Invoke-DCMsGraphQuery @Parameters | Out-Null } } catch { Write-Warning -Message "Could not delete phone method '$($phoneMethod.phoneType)' for $($User.userPrincipalName)! Is it the users default authentication method?" } } }
And this is some example output:

Summary
With this post I want to raise awareness of the issue with telecom as a security factor, and inspire you to migrate users to stronger authentication methods and passwordless.
Please follow med here, on LinkedIn, and on Twitter!
The only issue I have with this article is when you say ”remember to also move to the Authenticator app in SSPR if you use that feature”. Whilst that is definitely a good thing and I agree that the SSPR methods should encourage using the Authenticator app for notification or code, it glosses over the challenge of having to have additional methods available in SSPR if you want to include the Authenticator app options.
Basically, if you want app notifications for SSPR, you have to choose to use two methods of verification and then actually have to pick two methods IN ADDITION TO the authenticator options. That second requirement means you are having to choose between email, phone and security questions as the two other options for SSPR, and security questions is the least secure of the three. So you often end up still using phone methods and having that option available in the combined security registration portal when users are registering.
How would you address this challenge?
Valid and interesting point. The best thing would of course be to move away from passwords but most of us aren’t there yet. In that case SSPR can be disabled.
Until then the app as the only method, or in combination with these phone methods might be the one way to go. Also, many orgs use different password reset management solutions than SSPR which might have another solution.