On this blog, and in several other places, I’ve shared my experiences with Azure Multi-Factor Authentication. While this information meanly focuses on the on-premises Azure Multi-Factor Authentication Server, I did encounter the occasional implementation of the cloud-based Azure Multi-Factor Authentication.
For one such implementation, I had the pleasure of migrating it from the cloud to the on-premises Azure Multi-Factor Authentication Server. Without proper monitoring, an overview of who was using it with what method was completely missing. So we decided to create a report to get snapshots of the Azure Multi-Factor Authentication configuration, using Windows PowerShell.
About Azure Multi-Factor Authentication
As I’ve described over on 4Sysops, several flavors of Multi-Factor Authentication exist. They are targeted at different use cases, but all share Microsofts cloud-based Multi-Factor Authentication engine.
- Office 365 Multi-Factor Authentication is aimed at colleagues consuming Office 365 resources and works through the enabled-means-enforced model.
- Azure Multi-Factor Authentication is aimed at colleagues authenticating towards Azure Active Directory and can be granularly applied to any Azure Active Directory-integrated resource.
- Azure Multi-Factor Authentication Server is the on-premises endpoint for all Multi-Factor Authentication needs enterprises and large organizations might have. It supports multi-factor authentication on all common protocols and extensive exception management, like one-time bypasses and admin delegation.
For a comparison of the features per solution, take a look at the Azure Multi-Factor Authentication features per license and implementation.
About the Azure MFA Inventory script
The script below performs two functions:
- It provides a total of the amount of user objects in an Azure Active Directory tenant that have Azure Multi-Factor Authentication configured, compared to the total amount of user objects in the Azure Active Directory tenant. The script saves this information in a .txt file.
- It provides a table of the user objects in an Azure Active Directory tenant that have Azure Multi-Factor Authentication configured, with their preferred method, their configured phone numbers, and all the other Azure Multi-Factor Authentication information available as part of the strongauthenticationdetails array for the object. The script saves this information in a .csv file.
Note:
The script fetches information on people from Azure Active Directory. This information is sensitive. The script should be run by an administrator with proper clearance within your information and only shared with the right people within the organization. Information you don’t want to see, can be omitted from the output by commenting the lines for the property in the script, twice.
Requirements
- Running the script requires the Global Admin role in the Azure Active Directory tenant.
- The script requires the Azure AD PowerShell Module to be installed.
Putting the script to good use
You can use this script in several ways.
What we did, is we took the .csv file and opened it in Microsoft Excel. This way, we were quick in providing several graphs on the Multi-Factor Authentication method distribution (pie-chart), the amount of people enrolled in Azure Multi-Factor Authentication without being enforced (pie-chart) and the last enrollment date.
The graphs we ended up with, look like this:
(click for larger screenshots)
Additionally, the phone numbers in the file gave us an opportunity to contact the colleagues and in some cases walk them through the migration from Azure Multi-Factor Authentication to Azure Multi-Factor Authentication Server, for instance deleting their mobile app registration in Azure Active Directory and reregistering at the Azure Multi-Factor Authentication Servers Mobile Portal.
Another use we’re seeing for this script is to avoid the challenge we’ve come to refer to as the ‘double prompt’ challenge.
Azure MFA Inventory script
The script is displayed below for your review:
#Connect to Azure AD environment
Import-Module MSOnline
$Credential = Get-Credential
Connect-MSOLService –credential $Credential
#Create new object with requested information of the users.
$Data = New-Object PSObject
$Data | Add-Member -MemberType NoteProperty -name UserPrincipalName -value NotSet
$Data | Add-Member -MemberType NoteProperty -name Enforced -value NotSet
$Data | Add-Member -MemberType NoteProperty -name Default -value NotSet
$Data | Add-Member -MemberType NoteProperty -name AlternativePhoneNumber
–value NotSet
$Data | Add-Member -MemberType NoteProperty -name Email –value NotSet
$Data | Add-Member -MemberType NoteProperty -name PhoneNumber –value NotSet
$Data | Add-Member -MemberType NoteProperty -name ProofupTime –value NotSet
#Get all users total
$AllUsers = Get-MSOLuser –all | Measure
$AllUsers = $AllUsers.Count
#Retrieve all enabled MFA users
$RawData = Get-MsolUser | Where{$_.StrongAuthenticationMethods -ne $null} | select UserPrincipalName,StrongAuthenticationMethods,
StrongAuthenticationPhoneAppDetails,StrongAuthenticationRequirements,
StrongAuthenticationUserDetails
#Get MFA User Total
$AllAzureMFAUsers = $Rawdata | Measure
$AllAzureMFAUsers = $AllAzureMFAUsers.Count
#Fill results object $Data with requested information
$Data = ForEach($User in $RawData){
#Create new object for passing back the required information
$Result = New-Object PSObject
$Result | Add-Member -MemberType NoteProperty –name UserPrincipalName
–value Notset
$Result | Add-Member -MemberType NoteProperty –name Enforced –value
NotSet
$Result | Add-Member -MemberType NoteProperty –name Default –value NotSet
$Result | Add-Member -MemberType NoteProperty –name
AlternativePhoneNumber –value NotSet
$Result | Add-Member -MemberType NoteProperty –name Email –value NotSet
$Result | Add-Member -MemberType NoteProperty –name PhoneNumber –value
NotSet
$Result | Add-Member -MemberType NoteProperty –name ProofupTime –value
NotSet
#Fill the UserPrincipalName
$Result.UserPrincipalName = $User.UserPrincipalName
#Move object information one level up.
$Temp = $User.StrongAuthenticationRequirements
#Fill the value if the MFA is enforced.
$Result.Enforced = $Temp.State
#Move object information one level up.
$Temp = $User.StrongAuthenticationMethods
#Get preferred method and place it in $Temp.
$Temp = $Temp | Where{$_.IsDefault -eq "True"} | Select MethodType
#Fill the Preferred method to value Default
$Result.Default = $Temp.MethodType
#Move object information one level up.
$Temp = $User.StrongAuthenticationUserDetails
#Fill the values with retrieved information.
$Result.AlternativePhoneNumber = $Temp.AlternativePhoneNumber
$Result.Email = $Temp.Email
$Result.PhoneNumber = $Temp.PhoneNumber
#Convert last enrollment date
$Result.Proofuptime = [datetime]($User.StrongAuthenticationProofupTime)
#Passback the object to data
$Result
}
#Create output string with user totals
$OutputUsers = "Total users in AzureAD: $AllUsers
Total users enabled for Azure MFA: $AllAzureMFAUsers "
#Output information to file
$OutputUsers | Out-File -FilePath ".\Result_Enabled_AzureMFA_Users.log"
$Data | export-csv -Path ".\Result_Enabled_AzureMFA_Users.csv" -delimiter ";"
Alternatively, you can download the Query_AAD_AzureMFA_Users script here (zipped).
Have fun!
Hat tip
My colleague Bas wrote the script, updated it several times to meet my creeping scope, and made it work like a charm!
This a great script, but I am having difficulty getting the desired results. It only provides me with users that are Enforced. I need a report that can show me users that are Enabled, Enforced, and Disabled. Your assistance is greatly appreciated.
Enjoy!
The *.txt file, that is part of the output provides a view on the amount of accounts that are disabled vs. enabled for Azure Multi-Factor Authentication. We didn't really want to list all the user objects in the Azure AD tenant, because that's what you'll basically end up with. If a user object is not listed in the *.csv file, it's not enabled or enforced, hence disabled for Azure Multi-Factor Authentication.
In one of our testcases, we found a couple of user objects in the Azure AD tenant, that were enabled, but not enforced. Plus, their Proofup time was blank. This meant these accounts were charged a license by Microsoft, but never actually used the Azure MFA functionality (because they didn't meet a Conditional Access condition or AD FS Claims Issuance Rule to do so). We considered that an undesirable outcome and choose to implement it as part of the script. When all the user objects in the *.csv are enforced, that I feel you're doing the right things.
Hi
This is indeed a great script and is very helpful. Shall we run for few users from Excel? If so, can you please share the steps to do so. Thank you so much for your help.
This is nice but only for Azure AD and MFA in a Cloud.
Do you know how to get the same information about users in Azure MFA on-premise? I need to automate export of users with their details from Azure MFA server and I don't see a way to do that.
Why is proofuptime blank for all my users ? Alot of them are using MFA ?
Hi Magnus,
Unfortunately, the information in this blogpost is no longer valid.
Due to the General Data Protection Regulation (GDPR), that Microsoft has chosen to implement globally to all its services, the way multi-factor authentication is stored in Azure Active Directory has changed around Mid-April 2018.
Although the General Data Protection Regulation (GDPR) has been implemented, I still think this script is extremely useful. It's great for knowing knowing what people have set as their default, contact methods, and just general reporting that's hard to find elsewhere.
So, thank for your work on this, regardless of the GDPR. Just this morning we depended on this script to return some needed report data.
I found some bugs in the script, if no method is enabled/enforced, but still methods is online (for SSPR).