PowerShell Basics: How to check if MFA is enabled in Azure and Office 365
Published Jun 25 2020 12:01 AM 54.8K Views
Microsoft

Security governance has been top of mind for most since the onslaught of human malware has the masses working from home.  This comes with new concerns surrounding identity protection and actually proving that remote users are who they say they are in order to be allowed access to organizational data.  Multi-factor Authentication (MFA) is a great tool to ensure this however the task of knowing which user has it enabled can be tedious. 

 

Enter PowerShell to the rescue to automate reporting of this process.

 

The following script will report on your organizations MFA status per user and report on which users are admins.  The latter being even more crucial that MFA is enabled.

 

Function Get-AzureMFAStatus {

    [CmdletBinding()]
    param(
        [Parameter(
            Position=0,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true
            )]

        [string[]]   $UserPrincipalName,         
        [int]        $MaxResults = 4000,
        [bool]       $isLicensed = $true,
        [switch]     $SkipAdminCheck
    )
 
    BEGIN {
        if ($SkipAdminCheck.IsPresent) {
            $AdminUsers = Get-MsolRole -ErrorAction Stop | foreach {Get-MsolRoleMember -RoleObjectId $_.ObjectID} | Where-Object {$_.EmailAddress -ne $null} | Select EmailAddress -Unique | Sort-Object EmailAddress
        }
    }
 
    PROCESS {
        if ($UserPrincipalName) {
            foreach ($User in $UserPrincipalName) {
                try {
                    Get-MsolUser -UserPrincipalName $User -ErrorAction Stop | select DisplayName, UserPrincipalName, `
                        @{Name = 'isAdmin'; Expression = {if ($SkipAdminCheck) {Write-Output "-"} else {if ($AdminUsers -match $_.UserPrincipalName) {Write-Output $true} else {Write-Output $false}}}}, `
                        @{Name = 'MFAEnabled'; Expression={if ($_.StrongAuthenticationMethods) {Write-Output $true} else {Write-Output $false}}}
                              
                } catch {
                    $Object = [pscustomobject]@{
                        DisplayName       = '_NotSynced'
                        UserPrincipalName = $User
                        isAdmin           = '-'
                        MFAEnabled        = '-' 
                    }
                    Write-Output $Object
                }
            }
        } else {
            $AllUsers = Get-MsolUser -MaxResults $MaxResults | Where-Object {$_.IsLicensed -eq $isLicensed} | select DisplayName, UserPrincipalName, `
                @{Name = 'isAdmin'; Expression = {if ($SkipAdminCheck) {Write-Output "-"} else {if ($AdminUsers -match $_.UserPrincipalName) {Write-Output $true} else {Write-Output $false}}}}, `
                @{Name = 'MFAEnabled'; Expression={if ($_.StrongAuthenticationMethods) {Write-Output $true} else {Write-Output $false}}}
 
            Write-Output $AllUsers | Sort-Object isAdmin, MFAEnabled -Descending
        }
    }
    END {}
}

As always, please share your comments below on bettering the above script or any questions you may have.

 

8 Comments
Copper Contributor

Very useful script!

 

A small thing you might want to fix is regarding checking if [switch] parameters are used: the "correct" way is 

if ($SkipAdminCheck.IsPresent) { .. }
Microsoft

Thank you @Anders Rask.

Copper Contributor

Thank you for the useful script.

 

It really helped !

Copper Contributor

This way is easier:

How to get a list of users without MFA enabled:
$UserCredential = Get-Credential Connect-MsolService -Credential $UserCredential
Get-MsolUser -All | where {$_.StrongAuthenticationMethods.Count -eq 0} | Select-Object -Property UserPrincipalName | Sort-Object userprincipalname

Copper Contributor

I stumbled upon this article and this script is wrong in the core of it.


There is a difference between having StrongAuthenticationMethods configured and enabling MFA. You can register an alternate email or phonenumber without MFA being enforced or enabled.


To know if a user is MFA enabled or not is stored in StrongAuthenticationRequirements their state.


f.e.:

$Req = (Get-MsolUser -UserPrincipalName $UserObject.UserPrincipalName).StrongAuthenticationRequirements
if (($Req.State -eq "Enabled") -or ($Req.State -eq "Enforced")){
      Write-Host "MFA Enabled or Enforced"
}

I even suspect that this bug is present in the Extension for Azure MFA v1.0.1.35 (8/17/2020) because we see the same behavior when we use the NPS extension. It sends an MFA challenge even if MFA isn't enabled/enforced.
(https://www.microsoft.com/en-us/download/details.aspx?id=54688)

Copper Contributor

Hi @D0mp13 

If MFA, Enabled via Conditional Access, then the state can be shown as Disabled too. 

Seems to me better to check the StrongAuthenticationMethods set or not and get the default one to know the MFA method

Get-MsolUser -UserPrincipalName <<upn@domain.com>> | select DisplayName,UserPrincipalName,@{Name="MFA Status"; Expression={ if( $_.StrongAuthenticationMethods.IsDefault -eq $true) {($_.StrongAuthenticationMethods | Where IsDefault -eq $True).MethodType} else { "Disabled"}}}

 

Copper Contributor

With the MSOnline Powershell module now deprecated, how can this be done with the Azure AD module?

Copper Contributor

Hi Guys, good day.
@Anthony Bartolo 
You try the following script below. It takes into consideration the actual status of the user from the legacy portal.

$AllUsers = Get-MsolUser -All:$True | Sort-Object DisplayName #-ErrorAction SilentlyContinue
 
# Check if a UserPrincipalName is given
# Get the MFA status for the given user(s) if they exist
 
 
$AllMFAData =@()
$Methods = @{
  "OneWaySMS"="SMS token"
  "TwoWayVoiceMobile"="Phone call verification" 
  "PhoneAppOTP" = "Hardware token or authenticator app" 
  "PhoneAppNotification" = "Authenticator app" 
}
 
foreach ($MsolUser in $AllUsers) {
 
  try {
      $MFAResults =  [PSCustomObject]@{
          DisplayName       = $MsolUser.DisplayName
          UserPrincipalName = $MsolUser.UserPrincipalName
          DefualtMFAMethod  = ($MsolUser.StrongAuthenticationMethods | ? {$_.isDefault -eq $true}).MethodType
          MFAEnforced       = if($MsolUser.StrongAuthenticationRequirements) {$MsolUser.StrongAuthenticationRequirements.State } else {"Diabled"}
          MFAMethods        = if($MsolUser.StrongAuthenticationMethods){($MsolUser.StrongAuthenticationMethods.MethodType | % { $Methods[$_]}) -join ","}else{"No Methods"}
        }
   }
   catch {
    $MFAResults = [PSCustomObject]@{
       DisplayName       = " - Not found"
       UserPrincipalName = $MsolUser
       DefualtMFAMethod  = $null
       MFAEnforced       = $null
       MFAMethods        = $null
     }
   }
   $AllMFAData += $MFAResults
 
}
 
$AllMFAData | Export-Csv $Home\Downloads\MFAResultsReport.csv -NoTypeInformation

 

Co-Authors
Version history
Last update:
‎Apr 27 2021 07:28 AM
Updated by: