Deploying users with pre-registered MFA

Deploying users with pre-registered MFA

A couple of weeks ago a friend of mine asked would it be possible to pre-register MFA for users in Azure AD. For short, yes it is!

In this blog, I’ll show how to pre-register OTP and SMS MFA methods using AADInternalsRegister‑AADIntMFAApp and Set‑AADIntUserMFA.

Introduction

When deploying users to Azure AD, one can provide the basic user information, including the password. Nowadays, when MFA is (hopefully) required in most organisations, pre-registering MFA would make it easier for users to start using Microsoft cloud services.

Also, when deploying users for trainings or demos, pre-registered MFA would remove one extra step from the users.

Deploying users

There are many ways to deploy users, one could use the Azure AD portal or one of the many PowerShell module options.

To pre-register MFA, the user deployment method doesn’t matter, as long as we know the users’ username and password.

The following script examples will use users.csv file as an input. The file must have the following columns populated:

Column Description
Username UPN of the user
Password Password of the user (complexity requirements)

MSOnline module

The following script will provide users using MSOnline module.

# Connect to MSOnline
Connect-MsolService

# Read usernames from a .csv file
$users = Import-Csv -Path .\users.csv

# Deploy users
foreach($user in $users)
{
	# Extract the name from UPN
	$name = $user.Username.Split("@")[0]
	
	# Deploy the user
	New-MsolUser -UserPrincipalName $user.Username -DisplayName $name -PasswordNeverExpires $true -ForceChangePassword $false
}

AzureAD module

The following script will provide users using AzureAD module.

# Connect to AzureAD
Connect-AzureAD

# Read usernames and passwords from a .csv file
$users = Import-Csv -Path .\users.csv

# Deploy users
foreach($user in $users)
{
	# Create a password profile
	$passwordProfile = New-Object -TypeName Microsoft.Open.AzureAD.Model.PasswordProfile
	$passwordProfile.Password = $user.Password
	$passwordProfile.EnforceChangePasswordPolicy = $false
	$passwordProfile.ForceChangePasswordNextLogin = $false
	
	# Extract the name from UPN
	$name = $user.Username.Split("@")[0]
	
	# Deploy the user
	New-AzureADUser -UserPrincipalName $user.Username -DisplayName $name -MailNickName $name -AccountEnabled $true -PasswordProfile $passwordProfile
}

MgGraph Module (Microsoft Graph PowerShell SDK)

The following script will provide users using MgGraph module.

# Import AADInternals and get access token to MgGraph (so no need to give consent to MgGraph app)
Import-Module AADInternals
$at = Get-AADIntAccessTokenForMSGraph

# Connect to MgGraph
Connect-MgGraph -AccessToken $at

# Read usernames and passwords from a .csv file
$users = Import-Csv -Path .\users.csv

# Deploy users
foreach($user in $users)
{
	# Create a password profile
	$passwordProfile = @{
		Password = $user.Password
		ForceChangePasswordNextSignIn = $false
	}
	
	# Extract the name from UPN
	$name = $user.Username.Split("@")[0]
	
	# Deploy the user
	New-MgUser -UserPrincipalName $user.Username -DisplayName $name -MailNickName $name -AccountEnabled -PasswordProfile $passwordProfile
}

Deploying MFA

OTP

The following script will deploy a new OTP app for the given users and saves the OTP secret to a .csv file.

The script below is using a users.csv file as an input. The .csv file must have the following columns deployed:

Column Description
Username UPN of the user
Password Password of the user

The script is using Register-AADIntMFAApp function to register a new OTP app to each user. This can take up to 30 seconds per user. You can use -Verbose switch to see what’s happening under-the-hood.

The OTP secret will be saved in the users.csv in OathSecretKey column. The secret can then be used in authenticator apps, like Microsoft Authenticator and Google Authenticator.

# Import AADInternals
Import-Module AADInternals

# Read usernames and passwords from a .csv file
$users = Import-Csv -Path .\users.csv

# Deploy MFA
foreach($user in $users)
{
	# Create PSCredentials object
	$creds = [pscredential]::new($user.Username,($user.Password | ConvertTo-SecureString -AsPlainText -Force))
	
	# Get access token for MySignins
	$at = Get-AADIntAccessTokenForMySignins -Credentials $creds
	
	try
	{
		# Deploy new OTP
		$result = Register-AADIntMFAApp -AccessToken $at -Type OTP

		# Set the OTP secret
		$user | Add-Member -NotePropertyName "OathSecretKey" -NotePropertyValue $result.OathSecretKey
	}
	catch{}
}

# Export to a .csv file
$users | Export-Csv -Path .\users.csv

The resulting .csv file have the following columns:

Column Description
Username UPN of the user
Password Password of the user
OathSecretKey OTP secret to be used with authenticator apps

SMS

The following script will set MFA phone number and select SMS as the default MFA method for the given users.

Note: This script is using AADGraph API, which is scheduled to be deprecated by June 30, 2023.

The script below is using a users.csv file as an input. The .csv file must have the following columns deployed:

Column Description
Username UPN of the user
PhoneNumber Phone number of the user in format “+CCC NNNNNNN” where CCC is the country code and NNNNNNN the phonenumber without the leading zero.

The script is using Set-AADIntUserMFA function to set MFA phone number of each user and select SMS as the MFA method.

# Import AADInternals
Import-Module AADInternals

# Get access token
Get-AADIntAccessTokenForAADGraph -SaveToCache

# Read usernames and passwords from a .csv file
$users = Import-Csv -Path .\users.csv

# Deploy MFA
foreach($user in $users)
{
	try
	{
		# Set the phone number and the default MFA method
		Set-AADIntUserMFA -UserPrincipalName $user.Username -PhoneNumber $user.PhoneNumber -DefaultMethod OneWaySMS
	}
	catch{}
}

Summary

AADInternals can be used to automate pre-registering OTP and SMS MFA methods for users.

AADInternals will “verify” the OTP app automatically, so it can be used right after registration (as well as SMS method).

References

Dr Nestori Syynimaa (@DrAzureAD) avatar
About Dr Nestori Syynimaa (@DrAzureAD)
Dr Syynimaa works as Principal Identity Security Researcher at Microsoft Security Research.
Before his security researcher career, Dr Syynimaa worked as a CIO, consultant, trainer, and university lecturer for over 20 years. He is a regular speaker in scientific and professional conferences related to Microsoft 365 and Entra ID (Azure AD) security.

Before joining Microsoft, Dr Syynimaa was Microsoft MVP in security category and Microsoft Most Valuable Security Researcher (MVR).