Reading the wonderful series on Azure Multi-Factor Authentication (MFA) by Sander Berkouwer gave me the idea of sharing a PowerShell function that allows you to enable this feature for a single user or multiple users. The ability to automate enabling MFA is very powerful for configuring all users the same way. Not having to do this through the GUI also saves valuable time.
Avatar
Latest posts by Graham Beer (see all)

To connect to Azure Active Directory to manage our users, install the PowerShell module MSOnline. If you have PowerShell version 5, you can use the PowerShell Gallery to install the module:

Find-Module -Name 'Msonline' | Install-Module

After installing the module, you need to make a connection to your Azure Active Directory. First capture your credentials like so:

$cred = Get-Credential -Credential 'Administrator@*****.onmicrosoft.com'

The credential username is my administrator account on my Office 365 trial account. Microsoft lets you create an Office Business 365 account for a free one-month trial. It's really useful if you wish to create a development area to test.

With your captured credentials, use the Connect-MsolService cmdlet to initiate a connection to Azure Active Directory:

Connect-MsolService -Credential $cred

A successful connection won't give you a confirmation message. You can test it by performing a simple user search:

Get-MsolUser -UserPrincipalName 'Test.Person@*****.onmicrosoft.com'

When enabling MFA, you will find (or not!) there isn't a cmdlet for this. You will need to use PowerShell's New-Object cmdlet to create an instance of the Microsoft.Online.Administration.StrongAuthenticationRequirement object:

Let's examine what properties we have to work with. Using Get-Member on $mfaobject shows us this:

$mfaobject | Get-Member -MemberType Properties
GetMember properties of an mfaobject

GetMember properties of an mfaobject

The two properties we need to populate are RelyingParty and State. For the RelyingParty property, we can set this to "*".

$mfaobject.RelyingParty = "*"

We now have to set the State. Microsoft says, "A user's state reflects whether an admin has enrolled them in Azure MFA, and whether they completed the registration process."

So what options do we have? Again, I'll refer to the Microsoft documentation:

Disabled = The default state for a new user not enrolled in Azure MFA.

Enabled = The user has been enrolled in Azure MFA, but has not registered. They receive a prompt to register the next time they sign in.

Enforced = The user has been enrolled and has completed the registration process for Azure MFA.

So we have three options to choose from. In this example, we will set our user to Enabled:

$mfaobject.State = "Enforced"

We capture our MFA authentication settings in a new variable, cast as an array.

$mfauthenabled = @($mfobject)

So we can go ahead and set this on the user. Let's make this process slightly easier. From what we have talked about, we know the properties we need to set to get our MFA template. We can do this in a line of code. The -Property parameter on New-Object allows us to use a hash table for the property names and their values. This is how it looks:

$MFASetting = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement -Property @{
    RelyingParty = "*"
    State        = "Enabled"
}

I like this approach since it is much cleaner. If you want to see what you have set, type in the variable $MFASetting. This is what you will see:

Configured settings of the variable MFASetting

Configured settings of the variable MFASetting

Now that we have our MFA template, we are ready to apply it to our user. We achieve this via the Set-MsolUser cmdlet. Pass the UserPrincipalName and add the StrongAuthenticationRequirements parameter with our Multifactor authentication template variable.

Set-MsolUser -UserPrincipalName 'Test.Person@*****.onmicrosoft.com' -StrongAuthenticationRequirements $MFASetting

To confirm we've applied this option to our user, we can expand the StrongAuthenticationRequirements settings we just populated and look at the State property:

$ThisUser = Get-msoluser -UserPrincipalName 'Test.Person@*****.onmicrosoft.com' | 
    Select-Object -ExpandProperty StrongAuthenticationRequirements
$ThisUser.State

We can confirm the system has set this value.

It's very easy to upscale this approach to more than a single user. I've created the function below, which takes a list of User Principal Name (UPN) addresses and allows the Enabled and Enforced state options. The function will apply the settings to the user and perform a check at the end to confirm it's made the changes.

Within the code you might spot the -ReadCount setting on the Get-Content cmdlet. When processing large files, you should use the -ReadCount parameter to specify a block size of -1. Doing so will cause it to load the entire file and process it at once, which is much faster.

function Set-MFAUsers {
    param (
        [parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        [ValidateScript( {Test-Path $_})]  
        [Alias('FullName')]
        [String] $Path,
        
        [ValidateSet('Enabled','Enforced')]
        [String] $State = 'Enabled'
    )

    # Set MFA object
    $MFASetting = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement -Property @{
        RelyingParty = "*"
        State        = $State
    }
    
    # Get user list
    $Users = Get-Content -Path $Path -ReadCount -1

    foreach ($user in $users) 
    {
         $SetUser = @{
            UserPrincipalName                = $user
            StrongAuthenticationRequirements = $MFASetting 
            ErrorAction                      = 'Stop'  
        }

        Try {
            # Set MFA
            Set-MsolUser @SetUser
            
            # Post Check
            $ThisUser = Get-msoluser -UserPrincipalName $User | 
                Select-Object -ExpandProperty StrongAuthenticationRequirements

            if ($ThisUser.State -eq $SetUser.StrongAuthenticationRequirements.State) {
                Write-Host "[SUCCESS] UPN: $user" -ForegroundColor Green
            }
            else {
                Write-Host "[FAILED ] UPN: $user" -ForegroundColor Red
            }
        }
        Catch {
             Write-Warning -Message $_.Exception.Message
        }   
    } 
}

To use this function, you pipe the file to it:

Or by:

Get-ChildItem C:\temp\MFA_Users.txt | Set-MFAUsers -State Enforced
avatar
5 Comments
  1. Avatar

    Great article.  We’re working with MFA in Azure now, but we’re performing it through the GUI.  I also found a diamond in the rough with the -readcount tidbit you gave us in the last paragraph.  I’ll use that going forward for sure.

  2. Avatar
    Graham Beer 6 years ago

    Thank you Marcus. Glad it helped.

  3. Avatar

    Awesome article, Graham! 🙂

  4. Avatar
    John Langston 5 years ago

    I like it because it tells me more than what I knew.  I am clearly missing something though or a little slow.  I am looking for a way to navigate MFA executing a scheduled PS script in which I copy databases (400+) and then creates accounts/groups and assigns permission in the dark of night.  The creation of accounts/groups and their permissions has to be done in Azure under the context of an AAD account.  Having to interactively enter information in order for the script to run defeats scheduling something in the wee hours.

  5. Avatar
    Bill Daly 4 years ago

    Is there any documentation on the RelyingParty property?

Leave a reply

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account