%3CLINGO-SUB%20id%3D%22lingo-sub-1488814%22%20slang%3D%22en-US%22%3ERe%3A%20PowerShell%20Basics%3A%20How%20to%20check%20if%20MFA%20is%20enabled%20in%20Azure%20and%20Office%20365%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1488814%22%20slang%3D%22en-US%22%3E%3CP%3EVery%20useful%20script!%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EA%20small%20thing%20you%20might%20want%20to%20fix%20is%20regarding%20checking%20if%20%5Bswitch%5D%20parameters%20are%20used%3A%20the%20%22correct%22%20way%20is%26nbsp%3B%3C%2FP%3E%3CDIV%3E%3CPRE%3Eif%20(%24SkipAdminCheck.IsPresent)%20%7B%20..%20%7D%3C%2FPRE%3E%3C%2FDIV%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1486045%22%20slang%3D%22en-US%22%3EPowerShell%20Basics%3A%20How%20to%20check%20if%20MFA%20is%20enabled%20in%20Azure%20and%20Office%20365%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1486045%22%20slang%3D%22en-US%22%3E%3CP%3ESecurity%20governance%20has%20been%20top%20of%20mind%20for%20most%20since%20the%20onslaught%20of%20human%20malware%20has%20the%20masses%20working%20from%20home.%26nbsp%3B%20This%20comes%20with%20new%20concerns%20surrounding%20identity%20protection%20and%20actually%20proving%20that%20remote%20users%20are%20who%20they%20say%20they%20are%20in%20order%20to%20be%20allowed%20access%20to%20organizational%20data.%26nbsp%3B%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Factive-directory%2Fauthentication%2Fhowto-mfa-getstarted%3FWT.mc_id%3Ddocs-ITOPSTALK-abartolo%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3EMulti-factor%20Authentication%20(MFA)%3C%2FA%3E%20is%20a%20great%20tool%20to%20ensure%20this%20however%20the%20task%20of%20knowing%20which%20user%20has%20it%20enabled%20can%20be%20tedious.%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EEnter%20PowerShell%20to%20the%20rescue%20to%20automate%20reporting%20of%20this%20process.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%3EThe%20following%20script%20will%20report%20on%20your%20organizations%20MFA%20status%20per%20user%20and%20report%20on%20which%20users%20are%20admins.%26nbsp%3B%20The%20latter%20being%20even%20more%20crucial%20that%20MFA%20is%20enabled.%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%3EFunction%20Get-AzureMFAStatus%20%7B%0A%0A%20%20%20%20%5BCmdletBinding()%5D%0A%20%20%20%20param(%0A%20%20%20%20%20%20%20%20%5BParameter(%0A%20%20%20%20%20%20%20%20%20%20%20%20Position%3D0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20ValueFromPipeline%3D%24true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20ValueFromPipelineByPropertyName%3D%24true%0A%20%20%20%20%20%20%20%20%20%20%20%20)%5D%0A%0A%20%20%20%20%20%20%20%20%5Bstring%5B%5D%5D%20%20%20%24UserPrincipalName%2C%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%5Bint%5D%20%20%20%20%20%20%20%20%24MaxResults%20%3D%204000%2C%0A%20%20%20%20%20%20%20%20%5Bbool%5D%20%20%20%20%20%20%20%24isLicensed%20%3D%20%24true%2C%0A%20%20%20%20%20%20%20%20%5Bswitch%5D%20%20%20%20%20%24SkipAdminCheck%0A%20%20%20%20)%0A%20%0A%20%20%20%20BEGIN%20%7B%0A%20%20%20%20%20%20%20%20if%20(%24SkipAdminCheck.IsPresent)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24AdminUsers%20%3D%20Get-MsolRole%20-ErrorAction%20Stop%20%7C%20foreach%20%7BGet-MsolRoleMember%20-RoleObjectId%20%24_.ObjectID%7D%20%7C%20Where-Object%20%7B%24_.EmailAddress%20-ne%20%24null%7D%20%7C%20Select%20EmailAddress%20-Unique%20%7C%20Sort-Object%20EmailAddress%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%0A%20%20%20%20PROCESS%20%7B%0A%20%20%20%20%20%20%20%20if%20(%24UserPrincipalName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20foreach%20(%24User%20in%20%24UserPrincipalName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Get-MsolUser%20-UserPrincipalName%20%24User%20-ErrorAction%20Stop%20%7C%20select%20DisplayName%2C%20UserPrincipalName%2C%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%40%7BName%20%3D%20'isAdmin'%3B%20Expression%20%3D%20%7Bif%20(%24SkipAdminCheck)%20%7BWrite-Output%20%22-%22%7D%20else%20%7Bif%20(%24AdminUsers%20-match%20%24_.UserPrincipalName)%20%7BWrite-Output%20%24true%7D%20else%20%7BWrite-Output%20%24false%7D%7D%7D%7D%2C%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%40%7BName%20%3D%20'MFAEnabled'%3B%20Expression%3D%7Bif%20(%24_.StrongAuthenticationMethods)%20%7BWrite-Output%20%24true%7D%20else%20%7BWrite-Output%20%24false%7D%7D%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24Object%20%3D%20%5Bpscustomobject%5D%40%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20DisplayName%20%20%20%20%20%20%20%3D%20'_NotSynced'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20UserPrincipalName%20%3D%20%24User%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20isAdmin%20%20%20%20%20%20%20%20%20%20%20%3D%20'-'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20MFAEnabled%20%20%20%20%20%20%20%20%3D%20'-'%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Write-Output%20%24Object%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24AllUsers%20%3D%20Get-MsolUser%20-MaxResults%20%24MaxResults%20%7C%20Where-Object%20%7B%24_.IsLicensed%20-eq%20%24isLicensed%7D%20%7C%20select%20DisplayName%2C%20UserPrincipalName%2C%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%40%7BName%20%3D%20'isAdmin'%3B%20Expression%20%3D%20%7Bif%20(%24SkipAdminCheck)%20%7BWrite-Output%20%22-%22%7D%20else%20%7Bif%20(%24AdminUsers%20-match%20%24_.UserPrincipalName)%20%7BWrite-Output%20%24true%7D%20else%20%7BWrite-Output%20%24false%7D%7D%7D%7D%2C%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%40%7BName%20%3D%20'MFAEnabled'%3B%20Expression%3D%7Bif%20(%24_.StrongAuthenticationMethods)%20%7BWrite-Output%20%24true%7D%20else%20%7BWrite-Output%20%24false%7D%7D%7D%0A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20Write-Output%20%24AllUsers%20%7C%20Sort-Object%20isAdmin%2C%20MFAEnabled%20-Descending%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20END%20%7B%7D%0A%7D%0A%3C%2FPRE%3E%0A%3CP%3E%3CSPAN%3EAs%20always%2C%20please%20share%20your%20comments%20below%20on%20bettering%20the%20above%20script%20or%20any%20questions%20you%20may%20have.%3C%2FSPAN%3E%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-1486045%22%20slang%3D%22en-US%22%3E%3CP%3ESecurity%20governance%20has%20been%20top%20of%20mind%20for%20most%20since%20the%20onslaught%20of%20human%20malware%20has%20the%20masses%20working%20from%20home.%26nbsp%3B%20This%20comes%20with%20new%20concerns%20surrounding%20identity%20protection%20and%20actually%20proving%20that%20remote%20users%20are%20who%20they%20say%20they%20are%20in%20order%20to%20be%20allowed%20access%20to%20organizational%20data.%26nbsp%3B%20Multi-factor%20Authentication%20(MFA)%20is%20a%20great%20tool%20to%20ensure%20this%20however%20the%20task%20of%20knowing%20which%20user%20has%20it%20enabled%20can%20be%20tedious.%26nbsp%3B%20Enter%20PowerShell%20to%20the%20rescue%20to%20automate%20reporting%20of%20this%20process.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22PowerShell_Basics.jpg%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F134944iD72B3B0B8F4E0886%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%22PowerShell_Basics.jpg%22%20alt%3D%22PowerShell%20Basics%3A%20How%20to%20check%20if%20MFA%20is%20Enabled%20in%20Azure%20and%20Office%20365%20via%20PowerShell%22%20%2F%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EPowerShell%20Basics%3A%20How%20to%20check%20if%20MFA%20is%20Enabled%20in%20Azure%20and%20Office%20365%20via%20PowerShell%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-1486045%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EAnthony%20Bartolo%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EAzure%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EPowerShell%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3ESecurity%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1489066%22%20slang%3D%22en-US%22%3ERe%3A%20PowerShell%20Basics%3A%20How%20to%20check%20if%20MFA%20is%20enabled%20in%20Azure%20and%20Office%20365%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1489066%22%20slang%3D%22en-US%22%3E%3CP%3EThank%20you%26nbsp%3B%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F1745%22%20target%3D%22_blank%22%3E%40Anders%20Rask%3C%2FA%3E.%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1493522%22%20slang%3D%22en-US%22%3ERe%3A%20PowerShell%20Basics%3A%20How%20to%20check%20if%20MFA%20is%20enabled%20in%20Azure%20and%20Office%20365%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1493522%22%20slang%3D%22en-US%22%3E%3CP%3EThank%20you%20for%20the%20useful%20script.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EIt%20really%20helped%20!%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1502403%22%20slang%3D%22en-US%22%3ERe%3A%20PowerShell%20Basics%3A%20How%20to%20check%20if%20MFA%20is%20enabled%20in%20Azure%20and%20Office%20365%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1502403%22%20slang%3D%22en-US%22%3E%3CP%3EThis%20way%20is%20easier%3A%3C%2FP%3E%3CP%3EHow%20to%20get%20a%20list%20of%20users%20without%20MFA%20enabled%3A%3CBR%20%2F%3E%24UserCredential%20%3D%20Get-Credential%20Connect-MsolService%20-Credential%20%24UserCredential%3CBR%20%2F%3EGet-MsolUser%20-All%20%7C%20where%20%7B%24_.StrongAuthenticationMethods.Count%20-eq%200%7D%20%7C%20Select-Object%20-Property%20UserPrincipalName%20%7C%20Sort-Object%20userprincipalname%3C%2FP%3E%3C%2FLINGO-BODY%3E
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.

4 Comments
New 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.

Regular Visitor

Thank you for the useful script.

 

It really helped !

Occasional 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