Assign Teams Phone number to users with Lifecycle Workflows in Entra ID Governance

When new employees are about to start in a company, one of the tasks that needs to be done before the employees have its first day is to assign a phone number to them, so they are able to make and receive phone call in their everyday work. If you are using Microsoft Teams in your company as the main form of tele communication and you have some experience in administering Teams phone numbers, then you will probably agree that is quite easy to assign a phone number to user, either via Teams Admin Center or using PowerShell. The trick in assigning phone numbers to new employees is to know what phone number is available to be assigned and which are not. I have seen people use Excel spreadsheets (including myself), but it can quickly spiral out of control and be outdated.

A few years ago, when I was working on migrating my company from Skype for Business to Microsoft Teams, I created a solution that would automatically assign the first available phone number from the company’s phone number series to users that didn’t have a phone (new employees), and at the same time maintain the list of phone numbers in use.
The solution can be found here: ChrFrohn/MSTeams-PhoneNumberMgmt: A project to manage Teams PSTN phone numbers using PowerShell and SQL (github.com) That project is what lays the groundwork for this blog post in how you can use Microsoft Entra ID Governance lifecycle workflows to assign phone numbers to new employees.

In this blog post I want to share with you how to assign a Microsoft Teams phone number (Direct routing) to a new employee in Microsoft Teams using Microsoft Entra ID Governance with PowerShell based on availability of the number in a Azure SQL database, and at the same time updating the user in Active Directory using the API-driven user provisioning, so that the phone number is added to the OfficePhone attribute (You need to have that attribute configured in the API-driven user provisioning mapping (How-To)). If you don’t use API-driven user provisioning, don’t worry – I’ll provided you with the PowerShell script without that part as well.

Pre-requisites

This blog post relies heavily on this post: How to run PowerShell scripts in Entra ID Governance Lifecycle Workflows, so make sure have read it and deployed the resources mentioned in it.

Ressources that needs to be deployed before reading on:

  • Azure SQL Server (How-To)
  • Azure SQL database (How-To)
  • API-Driven user provisioning set up (Optional)
  • A Service Principal with following permissions:
    * Write permissions to the SQL database (How-To)
    * Teams permissions (How-To)

Laying the foundation

The first thing we need to do is to build the foundation for the handling of the phone numbers. This is done by using an Azure SQL database that will contain the list of all phone numbers, and who the numbers are assigned to. The reason behind using an Azure SQL database is because i find it easier to manage and work with and is simpler for the next person to take over my work, plus I’m utilizing the resources I already have setup when I configured the API-driven user provisioning to use and SQL database as source of truth.

We are going to start with the creation of table in the SQL database – This SQL query will create the table plus the columns needed:

ReservedFor is meant for excluding phone numbers so they dont get assigned to users. Type in any value in ReservedFor and the number will not be assigned to any user. This is meant for conference phones, if you have a specific phone number range for those, then, type in “Device” in ReservedFor. (SQL Query)
PSTNnumber is the phone number, and usedBy is for the user it is assigned to and CountryCode is the country code for the phone number (+45 fx.)

The next thing we need to do is to import all the phones numbers in the phone numbers series, and their country code. You don’t need to include what user uses what number; we will do that automatically later. You should be able to get the phone numbers from your telecommunications provider (Or your spreadsheet).
Once you have the phone number list, turn it to a .csv file based on this template: CSV-Template

The next step is to import all those numbers into the SQL database table that was created.

Use this PowerShell script to import all the Phone numbers into the SQL table from CSV file.
You need to provide the path of .csv file along with the Service Principals ClientID, TenantID and Secret for the Service Principal that has write permission to SQL database, and lastly the name of the SQL server, database and table names.

Now every phone number should be in your SQL database table. You can view the content of the table by right clicking and selecting Select Top 1000 Rows

Now the last part before we move on to configuring the Lifecycle Workflow to assign phone numbers to new users. We need to update the SQL database table with what user uses which phone number. This will be done by running the below PowerShell script. The PowerShell script makes sure that if user is found in Microsoft Teams with a phone number, then that information is added to the SQL database table, and the other way around, if the user is found in the SQL database table, but not in Teams, then the phone number is released.

The above PowerShell script is designed to keep the database table up to date, so that when an employee is offboarded (Removed Teams licenses) then the phone number will be released, so you don’t have to anything in the offboarding Lifecycle workflow expect for removing the user’s Teams license. The same goes for when one of your colleagues sets up a new Teams Call queue and assigns a phone number to the associated resources account, then the list of phone numbers will be automatically updated in the SQL database or if a colleague assigns a phone number to a user manually using the Teams Admin Center or PowerShell.

The catch is you need to add the above PowerShell script as runbook in your automation account and set it to run on a daily schedule. This will make sure you always have an up to date list of phone numbers in use and which is available to be assigned.

Assigning a phone number to a new employee

Now that the foundation has been laid, we are then ready to proceed in setting up the Lifecycle Workflow in Entra ID Governance that are going to assign a new employee a phone number.

The following is the PowerShell script that are going to assign a phone number in Teams to a new employee and sets the phone number in Active Directory using the API-driven user provisioning and also update the SQL database.

The PowerShell scripts need to be added as runbook to an Automation account that is associated with a hybrid worker in order to run.

Note: If you don’t use the API-driven user provisioning to manage users in active directory, and only want to assign the number in Teams, you can use this PowerShell script: MSTeams-PhoneNumberMgmt/EnableAndAssignPhoneNumber.ps1 at main · ChrFrohn/MSTeams-PhoneNumberMgmt (github.com)

The above PowerShell script assign the new employee the first available phone number in the Azure SQL database, but before the number is assigned, the scripts performance a few checks to make sure the user is ready to be assigned a phone number. The checks that are performed on the following attributes on user in Microsoft Teams:

  • OnPremLineURI – Must be empty
  • LineURI – Must be empty
  • RegistrarPool – Must not be empty
  • CoexistenceMode – Must be TeamsOnly or Island Mode
  • InterpretedUserType – Must be an acceptable value, see below

InterpretedUserType, this is a “tricky” Teams user attribute that has a whole blog post dedicated to it, but the short version is that is must be one of many acceptable values in order to pass the check. These values are collected into an XML file: MSTeams-PhoneNumberMgmt/InterpretedUserType.xml at main · ChrFrohn/MSTeams-PhoneNumberMgmt (github.com)

The XML file needs to be place (C:\Scripts\InterpretedUserType.xml for example) on the hybrid worker VM that is associated with the Automation account from where the PowerShell script is set to run from. The PowerShell script then fetches the XML file content and then performance the InterpretedUserType check based on the XML files content.

The reason for handling the InterpretedUserType check this way, is because there are 24 InterpretedUserType values (as of this writing) that I have found, and they would have to be hardcoded into the script and I found that it was not flexible. So, I decided to create the XML file for easier use and flexibility, so when I discover new values for InterpretedUserType i can just added them to the XML file without changing the PowerShell code.

When all checks are passed the user is then assigned the first available phone number from the SQL database table and the SQL database table is then updated to reflect that the user is assigned that phone number. Then the phone number is added to the user in Active Directory using the API-driven user provisioning service. If one of the checks fails, the PowerShell script will abort and not update the SQL database table and not assign a phone number in Teams to user or updated the user in Active Directory.

The PowerShell script connects to Microsoft Teams and the SQL database by using a Service Principal, so you need to provide the script with ClientID, TenantID and secret for that Service principal along with the ClientID and Secret for the API-driven user provisioning Service Principal and the Provisioning API EndPoint url.

When you have modified the script with the required information and create the XML file on the Hybrid worker VM, we can then move to last step in creating the task our Lifecycle Workflow.

Creating the task in a Lifecycle Workflow

This is the part where the blog post about How to run PowerShell scripts in Entra ID Governance Lifecycle Workflows, comes in. You should have configured an Automation Account with a Hybrid worker VM and created a Runbook with the PowerShell script to assign Teams phone numbers plus placed the XML on the hybrid worker VM.

This part will assume that you have.

The first step is to create the Custom Extension (Logic app) that will run the PowerShell script. Navigate to Identity Governance in Entra ID and select Lifecycle Workflows, and then Custom extensions to create a new one – You can use this link: https://portal.azure.com/#view/Microsoft_AAD_LifecycleManagement/CommonMenuBlade/~/customExtension

Start off by providing the Custom extension task with a name and a description that fits your needs.

When you have completed that, select next and in Task behavior step – Select Launch and wait and the select next again to go to details. The select the Azure resource group to place the logic app (Custom Extension), and a name for the logic app (pref. the same name as in the first step.) Select deploy and wait, and then create.
(All of this is detailed in blog post about how to run PowerShell scripts in lifecycle workflows)

When you are done, navigate to the Logic App that was created and add Azure automation – Create job as task like this:

Remember you need to write/paste the name of the Hybrid work group in.

Now that the logic app is created and configured we can then move over to the Lifecycle Workflows to configure the Lifecycle Workflow that will run the PowerShell script to assign a Teams phone number to new employee.

Start by navigating to the Lifecycle Workflow where you want the task to assign Teams phone number to a user in. (I’m going to use the Onboarding pre-hire employee template). When you have selected the Lifecycle Workflow, add the task called Run a Custom Task Extension

Then select the Run Custom Task Extension again and the provide it with a name and then select the Custom task Extension you have created.

Then select save, and then save again to save the Lifecycle workflow.

Now, the only thing left is to test it, navigate to the workflow and select Run on demand, and then select the user you want to test it on. When the Lifecycle Workflow has completed its run, you can navigate to the Automation account and then selecting the runbook with the PowerShell script and the output should be this:

You can then verify it be running this command in PowerShell

Connect-MicrosoftTeams
Get-CsOnlineuser "Username" | Select-Object LineUri 

And then in the SQL database run this query:

Select * from dbo.PhoneNumbers
Where usedby = ‘Username’

Remember you can monitor Lifecycle workflows task in case a some of the checks is not passed – Read more here: Monitor Lifecycle Workflows status in Entra ID Governance