MSEndpointMgr
Home » Security » Prepopulate MFA phone authentication solution

Prepopulate MFA phone authentication solution

Prepopulate MFA phone authentication (Multi-Factor Authentication) details on a user in Azure Active Directory – This is the act of getting a known second factor added to a user’s account details in Azure AD automatically. These details are also known as the user’s “Strong Authentication Methods.”

Normally MFA enrollment is a manual process done with the Microsoft Authenticator App during first sign-in to a Modern Authentication capable app or website. However, a more basic second factor is most often know to IT. And that is the user’s cellular/mobile number, which, in a corporate environment, is usually owned and assigned by HR or IT.

With a recent addition to the Microsoft Graph API, it is now possible to add or replace a user’s strong authentication phone method programmatically. Although still on the Beta endpoint of the Graph API, you can use this with high confidence in production today – although it requires jumping through some hoops, which is why we wrote you this article. So it will be easier for you to configure and maintain.

A little history…

There have been various attempts and solutions for prepopulating MFA details throughout the last few years. In 2015, it became possible to do some parts of what this solution does with the MSOnline PowerShell Module. But when the backends of Self Service Password Reset (SSPR) and Azure Multi-Factor Authentication (MFA) got merged and brought us the magic of “Combined Registration,” the possibility to script against the strong authentication details was lost for some time, and only resurfaced with the option to get insights… Until now!

Overview of the MFA Automation solution

TL; DR; It will enable you to register the users automatically for MFA and SSPR at the same time!

The MFA Automation solution for prepopulating new and existing users with phone authentication details makes use of the following Microsoft technologies:

  • Azure Automation.
  • Microsoft Graph API (beta).
  • PowerShell.
  • Azure AD (P1).
  • Combined registration
  • (optionally) Azure Log Analytics.
  • An Azure Subscription.

The cost of running this solution is next to nothing unless you have a considerable amount of users, in which case it is still very cheap compared to the amount of time saved.

Please notice the requirement for Azure AD P1, which is because you need to enable combined registration and have a license for Self-Service Password Reset (SSPR).

This article will cover the following subjects and guide you into a ready state for running in production.

  • Required permissions
  • Use cases for the MFA Pepopulation solution
  • Installation of the solution in Azure
  • Output explanation
  • Log Analytics for enhanced monitoring
  • Script explanation
  • Opportunities for enhancements
  • Caveats
  • Troubleshooting

DISCLAIMER: This solution is provided freely to the community as inspiration only. While we have done our best to test the solution for production use, we cannot take any responsibility for data loss or damage caused by the script or instructions provided in this article.

Required permissions

Permissions for the solution are a bit tricky since we initially wanted this to run with application permissions and not delegated as a user. But as the documentation states, only delegated permissions can be used to update a user’s authentication details. Furthermore, the user that we delegate the permissions to needs to be assigned some pretty hefty permissions (either of the roles listed below will do):

  • Global admin
  • Privileged authentication admin
  • Authentication admin

In the installation guide, you will be using the “Authentication Admin” role. Because you always want to start with the least possible permissions. But in some cases, the “Privileged Authentication Admin” might be your role of choice since it can read the current phone number, which the “authentication admin” can not.

Since you will be working with authentication details and require the highest level of access in your tenant, you must have the “Global Administrators” role during the solution’s implementation. But if you are using Azure PIM, you must be prepared to grant an active, permanent assignment of “Authentication Admin” to the solutions service account.

Use cases for the Prepopulate MFA phone authentication solution

For companies that want to supercharge their MFA enrollment, this solution will allow them to achieve the following:

  • Have the user registered for MFA and SSPR as part of the account provisioning process.
  • Lockdown MFA registration completely.
  • Get to compliant Multi-Factor Authentication state in record time!
  • Have SSPR work from the user’s first day of work!
  • Register those pesky users that never seem to get caught by

Installation of Prepopulate MFA phone authentication solution in Azure

This is what you came for!

Expand the following accordion items to read the guided steps. And remember that each part should be completed entirely and in order.

NB: As a good measure of caution, the guide assumes that you will be testing this solution on a small group of users. These users should be put in an Azure AD Security group. You will need the name of that security group in the “Configuring the Automation Account” part.

As with most things in Azure, you begin the journey at https://portal.azure.com, and from there, you can follow these simple steps to configure a suitable Azure Automation environment for this solution to run in.

  1. In the universal search area, search for automation.
  2. Click on “Automation Accounts” in the results dropdown.
Finding the Automation Accounts area in the Azure Portal
  1. Click on the “+ Add” button to open the “Add Automation Account” blade.
  2. Enter a name for the account, like “Automation-MFA,” if you do not follow a cool naming scheme.
  3. Choose the subscription that you want to the automation account to reside in.
  4. Choose or Create a new resource group to hold the automation account and the resources that will accompany the solution you are about to deploy.
  5. Choose the data center location (consider keeping it within Europe to comply with the GDPR).
  6. Leave the “Create Azure Run As account” on “Yes,” as you will use it.
  7. Click on “Create.”
Adding a new Automation Account in the Azure Portal

Wait for the deployment to complete. Note that the service principal will get added to your subscription access control list (More about this in the last section about opportunities for enhancements).

You are done creating the Automation account!

As you are dealing with highly privileged actions, you will need to assign some permissions to our new RunAs account.

While still in the Azure Resource Manager Portal:

  1. Go to the “Universal Search” at the top of the web page.
  2. Search for “App reg“.
  3. Click on “App registrations” in the results list.
Finding App registrations in the Azure Portal
  1. On the “App registrations” page, click on “All applications.”
  2. (Optionally) filter the list by entering the name of the Automation account your previously created.
  3. Click on the app registration that corresponds to your new Automation account.
Selecting specific app registrations in the Azure Portal
  1. On the app page, click on “API permissions.”
  2. Click on “+ Add a permission“.
  3. Click on the huge “Microsoft Graph” button (impossible to miss!).
Requesting API permissions in The Azure Portal

Now comes the part where you actually assign the permissions, and since we will be using both “application” AND “delegated” permissions, we will go ahead and get both types selected before exiting the “Request API permissions” blade. So don’t be hasty and just close things right away!

Delegated permissions

  1. Click on “Delegated permissions.”
  2. Search for “UserAuth“.
  3. Find and tick “UserAuthenticationMethod.ReadWrite.All” which will give access to get and set the strong authentication details of any user in the Azure Active Directory.
  4. Now, click on “Application permissions,” and don’t worry, the permission you just selected will be remembered.
Assigning delegated permissions for Microsoft Graph API in he Azure Portal

Application permissions

  1. You must now be on the “Application permissions” selector.
  2. Search for the following permissions one at a time:
    user.read.all
    reports.read.all
    groupmember.read.all
  3. Tick the permissions once found.
  4. Click on “Add permissions” once you have found and ticked the required permissions.
Assigning application permissions for Microsoft Graph API in the Azure Portal
  1. Back on the main page for the automation app, review the permissions.
  2. Notice that permissions are not granted for the tenant yet.
  3. Click on “Grant admin consent for <Tenant name>“.
  4. Click on “Yes” when prompted.
Granting admin consent for an app registration in Azure AD

Default client type

Lastly, you must configure the App registration to treat the application as a public client. Otherwise, delegated access will not work.

  1. Click on “Authentication” in the left-hand menu.
  2. Set the “Default client type” option as “Yes” on the lower right.
Default client type setting for Azure App Registration

Don’t forget to click on the “Save” button!

You are done configuring the app registration!

Creating a service account is a crucial part of getting the solution to function correctly. The delegated app permission will only work properly when requested by a user account, so we need to create a service account to act as our delegate. This account needs to be assigned the “Authentication Admin” role as permanently active (if you are using PIM), and steps must be taken to ensure that MFA prompts do not occur.

You can do this part of the guide through either PowerShell or the Azure Portal, as explained in the following steps:

Create user

  1. Search for “users.”
  2. Click on “Users” in the results list.
Finding the users list in the Azure Portal
  1. At the top of the “All users” list, click on “+ New user“.
The new user button in Azure AD
  1. Select “Create user.”
  2. Enter your desired “User name” and choose an appropriate domain.
  3. Create a good display “Name” for the account.
  4. Enter an appropriate “First name” and “Last name.”
  5. Click on “Create” to finish (Don’t worry about the other details right now).
Creating a new service account in Azure AD
  1. Click on the “Refresh” button to update the list with our new user.
  2. “Search” for your new user on the list.
  3. Click on the user in the list once found.
Finding the newly created Azure AD Service Account
  1. Click on “Assigned roles” on the service accounts page.
  2. Click on “+ Add assignment“.
Adding a role assignment to a user in Azure AD
  1. Search for “Authentication“.
  2. Choose “Authentication Administrator“.
  3. Click on the “Add” button.

If you have Azure PIM enabled, your screen will look like the below image instead, and you will be required to do the following steps, so if you don’t, continue after the second image below.

Assignment of roles with PIM enabled in Azure
  1. Select “Active“.
  2. Tick “Permanently assigned“.
  3. Enter a justification that will appease the security gods!
  4. Click on “Assign“.
Assigning an active permission with Azure PIM

Now you just need to configure the account password and policy.

Password policy

You will use Azure Cloud shell (or the Azure AD PowerShell module) to configure the account to have a very secure password – one that never expires.

Edit the following PowerShell code to suit your environment. Pay special attention to:
Line 2. A password needs to be filled in.
Line 4. You will need to enter the Object Id, which is the full UPN username (i.e., [email protected]) that you just created in the previous steps.

$PasswordProfile = New-Object -TypeName Microsoft.Open.AzureAD.Model.PasswordProfile
$PasswordProfile.Password = "Verylongandhardpasswordtoguess1sttimearound"
$PasswordProfile.ForceChangePasswordNextLogin = $false
Set-AzureADUser -ObjectId "[email protected]" -PasswordPolicies DisablePasswordExpiration -PasswordProfile $PasswordProfile

NB: If you are using Conditional Access to either enforce MFA for All users or enforce it for privileged role members, you must ensure that the proper exclusions are made so that the service account is not affected. You can target the Service Principal for the automation account to secure access as much as possible.

You are done with the service account, but please keep the username and password handy for the runbook’s configuration.

Before you add the runbook to your new Automation Account, there are some requirements that need to be met in order for the solution to run successfully.

Credentials and Variables need to be defined, as they will be consumed by the script automatically and in a safer way, than just hardcoding them into the script.

Start by going to your new Azure Automation account (you can use the universal search bar like shown in all the previous parts of the installation).

Credentials

  1. (optionally) Search for the “Credentials” menu item.
  2. Click on “Credentials” in the left-hand menu.
Finding the “Credentials” button for the Azure Automation Account

DelegateServiceAccount

  1. Click on “+ Add a credential” to open the “New credential” blade.
  2. Type preciselyDelegateServiceAccount” into the “Name” field (don’t change this).
  3. Enter a “Description” that makes sense.
  4. Fill with the “User name” of your service account.
  5. Fill with the “Password” of the account and confirm it with a second entry.
  6. Click on the “Create” button.
Entering credential details into Azure Automation credentials blade

Verify that the account has been added to the Automation account credentials page.

Variables

Now you need to setup some required variables – without these the runbook will error.

  1. (optionally) Search for the “Variables” menu item.
  2. Click on the “Variables” menu item on the left.
  3. Click on the “+ Add a variable” button.
Finding the variables menu item in Azure Automation

You will need to add variables to the automation account, so we will not explain how you click on the “+ Add a variable” button each time. Instead, we just show the variables you need to enter and their values.

EnableStagingGroup

  1. Enter precisely EnableStagingGroup” into the “Name” field.
  2. Enter a good “Description” like in the example picture below.
  3. Change the “Type” to “Boolean.”
  4. Set the “Value” as “True” to begin with. Piloting solutions like this should be what you do first.
  5. Set “Encrypted” as “No.”
  6. Click on the “Create” button.

StagingGroupName

  1. Enter precisely StagingGroupName” into the “Name” field.
  2. Enter a good “Description” like in the example picture below.
  3. Change the “Type” to “String.”
  4. Enter a “Value” with the name of the Azure AD security group of user accounts that you wish to pilot this solution with.
  5. Leave “Encrypted” on “No.”
  6. Click on the “Create” button.

That’s it for adding Azure Automation account variables to the solution.
Now we must add a single module that the solution depends on…

Installing the MSAL.PS module

The MSAL.PS module is used for simplifying the authentication with the Microsoft Graph API and it is a hard requirement of the MFA automation solution.

You should still be in the Azure automation Account from the last part of this guide.

  1. (optionally) Search for Modules in the menu.
  2. Click on the “Modules gallery” item.
  3. Search for “MSAL.PS” in the search field on the right.
  4. Click on the “MSAL.PS” module in the results pane.
Finding PowerShell modules in Azure Automation
  1. Click on the “Import” button (you accept the license terms at the same time).
Importing a module to an Azure Automation account

Click “Ok” on the next page and wait for the import to complete. You can follow the progress by clicking on the notifications icon.

Viewing a notification in the Azure Portal

You have now configured all the dependencies and are ready to deploy the actual runbook script!

You can download the AzAutomationScript4MFAPrePopulate.ps1 script directly from the MSEndpointMgr GitHub account if you are proficient in Azure Automation runbook import, or follow this part step-by-step (uh baby) like the new kids on the block.

https://github.com/MSEndpointMgr/AzureAD/tree/master/AzureMFAProvisioning

NB: if you choose to import the Runbook manually, please name it “AzAutomationScript4MFAPrePopulate“, so you can avoid changing the Log Analytics queries that we are going to show you later in this article.

Automated deployment of the Prepopulate MFA phone authentication solution

You can also click this link to start the import process automatically in the Azure portal:

Deploy to Azure

You will be asked to fill in some details about the automation account you just created – most of which will be prefilled with the settings used in this article.

  1. Select the “Subscription” you create the Automation Resource Group in.
  2. Select the “Resource Group” that the automation account lives in.
  3. Enter the “Automation Account Name” of your automation account if you choose a different name.
  4. Select the “Automation Region” you deployed the automation account into.
  5. Click on the “Review + create” button.
Deploying the script via an ARM template

Now review the setting s and click on the “Create” button to start the deployment.
Once it completes, click on the “Go to resource” button.

Deployment complete in Azure Portal
  1. You can now click on “Start” to execute the runbook.
  2. (optional) Create a schedule by clicking on “Schedules” in the left-hand menu.
  3. (optional) Afterward, link the schedule to the runbook by clicking on “Link to schedule.

    (Scheduling is not in the scope of this guide)
Starting a runbook in Azure automation

Output explanation

The script will output statistics and results in a specific format. This is to enable easy parsing by Log Analytics and enable a monitoring workbook for the results. Some example outputs from the script:

  • Runstate – shows if a staging group is used or if all users are processed.
  • Stats: Numbers of users without MFA is: 4499 – the total number of users without MFA in Azure AD.
  • Stats: Numbers of targeted users without MFA and a mobile number in AAD is: 101 – Number of applicable users.
  • Stats: 100 users have been processed successfully. – The number of successfully provisioned users
  • Status: MFA Update failed; User: <username>; Message: <The message>
  • Status: Number Format error; User: <username>; Message: MobilePhone <The number>
  • Status: MFA Phonemethod Provisioned successfully; User: <username>; Message: MobilePhone <The number>

In addition to this output, the script also generates verbose logging, if enabled, for troubleshooting purposes.

Log Analytics for enhanced monitoring

Logging is important, especially when dealing with highly privileged details such as Multi-Factor Authentication. But accessing the logs in the Azure Automation account requires permission to read details on the job.

You might not want too many people to have access to the automation account itself. Forwarding the job stream to log analytics gives you the option to delegate access to the job logs.

This article’s scope does not include configuring Log Analytics – The following examples are provided as a recommendation on how to use Log Analytics with this MFA automation solution.

The recommended queries are as follows:

AzureDiagnostics 
| where RunbookName_s == "AzAutomationScript4MFAPrePopulate" and StreamType_s == "Output" and ResultDescription startswith "\"Status:"
| parse ResultDescription with * "Status: " Status "; User: " User "; Message:" Message 
| project User, Status, Message, TimeGenerated
| summarize count() by Status
AzureDiagnostics
| where RunbookName_s == "AzAutomationScript4MFAPrePopulate" and StreamType_s == "Output" and ResultDescription startswith "\"Status:"
| parse ResultDescription with * "Status: " Status "; User: " User "; Message:" Message
| project User, Status, Message, TimeGenerated
AzureDiagnostics 
| where RunbookName_s == "AzAutomationScript4MFAPrePopulate" and StreamType_s == "Output" and ResultDescription startswith "\"Stats: Numbers of users without MFA"
| parse ResultDescription with * 'Stats: Numbers of users without MFA is:' UsersWithoutMFA '"' *
| project TimeGenerated, toint(UsersWithoutMFA)
| render timechart 

You can manually run all these queries or create a workbook containing all the queries above to have your own monitoring dashboard for the solution.

The monitoring dashboard could end up looking like this:

MFA Solution dashboard example
MFA Solution example graph of users without MFA

The workbook example can be downloaded from the same Github repository as the MFA Prepopulate script and imported into your monitoring workspace in Azure.

Authentication methods – Usage and Insights (Preview)

Microsoft recently released a dashboard into public preview, that allows you to monitor the overall status of your MFA and SSPR deployment. This dashboard can also help you asses how far your are with your journey, but keep in mind, the data also includes guest/external accounts.

https://portal.azure.com/#blade/Microsoft_AAD_IAM/AuthMethodsOverviewBlade

Script explanation

We have been generous with inline comments, so please look at the source code in our GitHub repository if you would like to understand the inner workings.

Opportunities for enhancements

Some thins we never got around to automating.

Securing the Automation account

If you followed the guide explicitly, you now have a RunAs account with “Contributor” access to the subscription you provisioned the automation account into. For this solution, we are not using much of that access. If you want to limit the permissions of the account, look at the official documentation here:
https://docs.microsoft.com/en-us/azure/automation/manage-runas-account#limit-run-as-account-permissions

Auto Renewing the RunAs account’s self-signed certificate

The RunAs account you created in this guide has a self-signed certificate that expires in one year. It would be best if you considered monitoring certificate expiration or adding some auto-renew solution.
https://docs.microsoft.com/en-us/azure/automation/manage-runas-account#cert-renewal

Caveats

Dealing with new Microsoft features often comes with some caveats that you must know before implementing and running this solution.

In this solution, we are using the Microsoft Graph API to call the PhoneMethod query. This is a slow process. In our experience, 2000 users/hour is approximated performance.

Fair share

Azure Automation has a feature called “fair share,” where any runbook that runs for 3 hours is unloaded to allow other runbooks to run. This means, if you have more than 6000 users, the runbook is going to fail because of run time limitation. The script can run in environments with many users, but you would either have to stage them in the staging group (a few thousand at a time) or run the script more times with a few hours of wait time in-between (so the reporting on the back end has completed).

Graph Token expiration

Another issue that we ran into during our testing was access-token expiration. By default, the Access Token is valid for an hour. Therefore, we added a Refresh Token method for getting a new Access Token in our solution.

There are some delays in audit and reporting data, not having been updated immediately for MFA registration. The reason is unknown. but we rely heavily on this reporting data, so you might see unexpected results if you run the script twice and the reporting backed has not been refreshed yet.

Phone numbers should ideally be in the format +AAA BBBBBBBBBBB.

Otherwise, the Graph API will reject them. We have added some example parsing code to the script that can fix some common errors, but they are disabled. Look at the comments in the execution region of the script.

The Microsoft Graph API endpoint queries that we are using in the script, are only available in the Microsoft Graph beta endpoint.

Note: The beta endpoint is subject to change. Microsoft’s official statement is; Microsoft doesn’t recommend that you use them in your production apps.

Final words

This has been a fun collaboration in the community between @michael_mardahl, @jankeskanke, and @sandy_tsang. Feel free to reach out to any of us should you require professional assistance with EMS.

We hope you appreciate the tool we have provided to the community and will do us the honor of following us on Twitter and Linkedin for more great EMS content in the future!

(3448)

Michael Mardahl

Michael works as a Microsoft Certified Cloud Architect with APENTO in Denmark. He is specializing in customer journeys from classic Infrastructure to Cloud consumption with a strong focus on security. And has now been in the IT industry for more than 20 years, where he started as a Network Administrator. He has gained experience through a broad range of IT projects. When not at work, Michael enjoys the value of spending time with family and friends and BLOG's passionately about Microsoft cloud technology whenever he has time to spare.

Jan Ketil Skanke

Jan Ketil is an Enterprise Mobility MVP since 2016 and are working as a COO and Principal Cloud Architect at CloudWay in Norway. He has been in the industry for more than 20 years working for both Microsoft Partners and Microsoft. He loves to speak about anything around Enterprise Mobility and Secure Productivity. He is also the lead for the community conference Experts Live Norway. Jan Ketil has presented at large industry conferences like Microsoft Ignite, Microsoft Ignite The Tour, Microsoft Inspire, Experts Live Europe, Techmentor HQ (3rd best session 2019) and NIC Conference in Oslo.

Sandy Zeng

Sandy is an Enterprise Mobility MVP since 2018. She is an experienced Information Technology Specialist for over 10 years. Skilled in Microsoft Endpoint Manager (ConfigMgr and Intune), Windows 10 and security. Sandy's interests are mostly related to Microsoft Technologies, she has passions learning new skill sets to improve her professional career and also as her hobbies. She uses her expertise to help customers achieve their goals and solve their issues.

Sandy founded the https://sandyzeng.com blog and is now a blogger on MSEndPointMgr.

3 comments

  • Hello

    Thanks for this great solution.

    This was working great. But now I get the following error message.
    Status: MFA Phonemethod provisioning failed; User: [email protected]; Message: accessDenied: Request Authorization failed

    Any ideas to what might have happend?

      • Hi Anders,
        We often encounter small but passing bugs with the service that we can only attribute to the fact that this is BETA Graph API and that “Speed fo the cloud” is not always synonymous with being fast on the backend 😉

Sponsors

Subscribe

Do you want to be notified of new posts on our site?

Please enter your email address below:

Categories

MSEndpointMgr.com use cookies to ensure that we give you the best experience on our website.