Scripting Azure AD Authentication Methods

Removing All Authentication Methods for an Azure AD Account with PowerShell

Microsoft product manager Merill Fernando (of Graph X-Ray fame) posted an interesting tweet about a script he wrote to remove all the authentication methods from an Azure AD account. Azure AD supports a wide range of authentication methods (Figure 1) ranging from the classic username/password combination to using the Microsoft Authenticator app.

Azure AD Authentication Methods (source: Microsoft)
Figure 1: Azure AD Authentication Methods (source: Microsoft)

At the recent TEC conference, Microsoft VP for Identity Security Alex Weinert made a passionate plea for more Microsoft 365 tenants to secure their accounts with MFA. It’s shocking that only 26.64% of all Azure AD accounts use MFA. The figure for accounts holding an administrative role is higher at 34.15%, but that’s still poor. We need to do a better job of moving accounts to the right-hand methods shown in Figure 1.

Scripting Authentication Methods

Merill acknowledges that the script “is not pretty” because the Microsoft Graph does not currently support a way to find the default authentication method for an account. In short, the script attempts to delete an authentication method and if it fails it assumes that the method (like the Microsoft Authenticator app) is the default and leaves it to the last. You can only remove the default authentication method from an account if it’s the last and only method.

In any case, it’s a good script to have around just in case you need to reset an account. I’m not sure how often you’d want to do this, but I guess you might. All contributions to the admin toolbox are gratefully received.

Authentication Methods and the Microsoft Graph PowerShell SDK

Merill’s script uses cmdlets from the Microsoft Graph PowerShell SDK. I like the PowerShell SDK a lot, but sometimes it goes overboard in terms of the number of cmdlets it uses. I think this is due to the way that Microsoft generates the SDK modules and cmdlets from Graph APIs using a process called AutoRest. It’s nice to have a way to generate code automatically, but sometimes human intelligence could do better. Usually, Microsoft generates a new version of the SDK monthly, but sometimes errors creep in and several versions appear in a month (this just happened when versions 1.12 had several minor updates (current version is 1.12.3).

For instance, every authentication method has a separate cmdlet to add (New), update, and remove it from an account. The set of cmdlets used to remove methods in Merill’s script is:

  • Remove-MgUserAuthenticationFido2Method
  • Remove-MgUserAuthenticationEmailMethod
  • Remove-MgUserAuthenticationMicrosoftAuthenticatorMethod
  • Remove-MgUserAuthenticationPhoneMethod
  • Remove-MgUserAuthenticationSoftwareOathMethod
  • Remove-MgUserAuthenticationTemporaryAccessPassMetho
  • Remove-MgUserAuthenticationWindowHelloForBusinessMethod

Seven different cmdlets (you can’t remove the classic password method with one of these cmdlets), or 21 when you add the others for adding and updating methods. It would be simpler all round if the SDK consolidated everything so that we had one cmdlet to add, one to update, and one to remove authentication methods. However, I suspect that because separate API requests exist for each method, we are condemned to work with a confusing mass of cmdlets.

Reporting Authentication Methods

I decided that it would be a good idea to find out what authentication methods are in use. Microsoft makes this information available in the Azure AD admin center, but it’s no fun to simply accept what Microsoft wants to deliver in an admin portal. Instead, if we understand how the technology works, we can adapt it for our own purposes. For instance, I want to focus on tenant accounts rather than including guest accounts in the mix, and I want to extract some information about each authentication method to include in the report.

I already have a script to create an Authentication Method Report for Azure AD and another script to report administrator accounts that aren’t protected with MFA, but there’s always room for another (and this version extracts a little more information about each authentication method, like the phone number used for SMS challenges). Here are the important bits of the code (the full script is available from GitHub):

Write-Host "Finding licensed Azure AD accounts"
[array]$Users = Get-MgUser -Filter "assignedLicenses/`$count ne 0 and userType eq 'Member'" -ConsistencyLevel eventual -CountVariable Records -All
If (!($Users)) { Write-Host "No licensed users found in Azure AD... exiting!"; break }

$i = 0
$Report = [System.Collections.Generic.List[Object]]::new()
ForEach ($User in $Users) {
 Write-Host ("Processing user {0} {1}/{2}." -f $User.DisplayName, $i, $Users.Count)
 $AuthMethods = Get-MgUserAuthenticationMethod -UserId $User.Id
 ForEach ($AuthMethod in $AuthMethods) {
  $P1 = $Null; $P2 = $Null
  $Method = $AuthMethod.AdditionalProperties['@odata.type']
  Switch ($Method) {
     "#microsoft.graph.passwordAuthenticationMethod" {
       $DisplayMethod = "Password"
       $P1 = "Traditional password"
     "#microsoft.graph.microsoftAuthenticatorAuthenticationMethod" {
       $DisplayMethod = "Authenticator" 
       $P1 = $AuthMethod.AdditionalProperties['displayName']
       $P2 = $AuthMethod.AdditionalProperties['deviceTag'] + ": " + $AuthMethod.AdditionalProperties['clientAppName'] 
     "#microsoft.graph.fido2AuthenticationMethod" {
       $DisplayMethod = "Fido 2 Key"
       $P1 = $AuthMethod.AdditionalProperties['displayName']
       $P2 = Get-Date($AuthMethod.AdditionalProperties['creationDateTime']) -format g
     "#microsoft.graph.phoneAuthenticationMethod" {
       $DisplayMethod = "Phone" 
       $P1 = "Number: " + $AuthMethod.AdditionalProperties['phoneNumber']
       $P2 = "Type: " + $AuthMethod.AdditionalProperties['phoneType']
    "#microsoft.graph.emailAuthenticationMethod" {
      $DisplayMethod = "Email"
      $P1 = "Address: " + $AuthMethod.AdditionalProperties['emailAddress']
    "#microsoft.graph.passwordlessMicrosoftAuthenticatorAuthenticationMethod" {
      $DisplayMethod = "Passwordless"
      $P1 = $AuthMethod.AdditionalProperties['displayName']
      $P2 = Get-Date($AuthMethod.AdditionalProperties['creationDateTime']) -format g
  $ReportLine   = [PSCustomObject] @{ 
     User   = $User.DisplayName
     Method = $DisplayMethod
     Id     = $AuthMethod.Id
     P1     = $P1
     P2     = $P2 
     UserId = $User.Id }
 } #End ForEach Authentication Method
} #End ForEach User

The code doesn’t include choices for every possible authentication method because examples aren’t available in my tenant. It’s easy to update the code to handle a method like the temporary pass. Figure 2 shows the output generated by the script.

Listing authentication methods found for Azure AD accounts
Figure 2: Listing authentication methods found for Azure AD accounts

One thing that puzzles me is why my account has multiple methods listed for the Microsoft Authenticator app. Both relate to my iPhone 11, but Azure AD might have created the second record after I renamed the phone. It’s something to look at when the time is available.

You can analyze the data to get further insights. For instance:

Write-Host ""
Write-Host "Authentication Methods found"
Write-Host "----------------------------"
Write-Host ""
$Report | Group-Object Method | Sort-Object Count -Descending | Select Name, Count
Authentication Methods found

Name          Count
----          -----
Password         33
Phone            21
Email            11
Authenticator     5
Fido 2 Key        2
Passwordless      1

The other scripts show how to deal with other aspects of reporting that might be important to you, like checking accounts for administrative roles, date of last sign-in, and so on. The nice thing about PowerShell is its flexibility. Cut and paste from different scripts to create a new take and meet your requirements. That’s a great capability to have.

Learn more about how Azure AD and the Office 365 applications really work on an ongoing basis by subscribing to the Office 365 for IT Pros eBook. Our monthly updates keep subscribers informed about what’s important across the Office 365 ecosystem.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.