Microsoft Teams Speed Dial Contacts Provisioning

Have you ever thought that it might be handy to provision a curated speed dial list for your end-users to get started with when they are onboarded to Microsoft Teams? Or another scenario, don’t have to manually add speed dial contacts on your common area phones for all the commonly used numbers like the reception, helpdesk, cafeteria, travel booking etc….

The issue is that there is no official way to administrate this from Teams Admin Center, PowerShell, or Graph API. But what about unofficial ways? Yes, there is! So what do we need to be able to do this?

If you are logged in to the Teams web client, and open dev mode (F12) of your browser you are able to see what is happening in the background. All actions in the web client are if you look closely, API calls!

Here we can see the request URL, method, and body/payload. We also see a token we can use to authenticate with. The issue though, this is only valid for this single user and expires in about an hour. This does not scale when doing a lot of provisioning and adding many contacts to the speed dial list. So how do we get the user’s token in a more automatic way? I came over a genius PowerShell module from Dr. Nestori Syynimaa that’s called AADInternals. You can install it by running “Install-Module AADInternals” in PowerShell. This module has a cmdlet called Get-AADIntAccessTokenForTeams, which contains a parameter called -Credentials. This parameter accepts username/password. Now we can before setting MFA or you could maybe have a conditional access rule from where you do the provisioning, then we can use basic-auth to authenticate with the user’s first-time password. You could even reset the first-time password after using it. By having a CSV file containing the headers password and UPN, we can feed that into a script I have created. The script loops through the users and adds the speed dial contacts we define in the script.

#Import the Azure AD Internals module.
Import-Module AADInternals
#Users to process
$Users = import-csv c:\temp\users.csv
foreach($user in $users){
$password = ConvertTo-SecureString $user.password -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList ($($user.upn), $password)
#Get the Teams token for user curently beeing processed.
$token = Get-AADIntAccessTokenForTeams -Credentials $cred
#URL to buddylists.
$URL = ""
$header = @{Authorization = "Bearer $token"}
#Get id of the Speed Dial list.
$ListID = ((Invoke-RestMethod -Uri $URL -Method GET -Headers $header -ContentType "application/json").value | Where-Object{$_.displayname -like "Favorites"}).id
#URL for the Speed Dial list.
$URL = "$ListID/managebuddies?migrationRequested=true&federatedContactsSupported=true"
#Number to Add. MRI is the phonenumber of the contact, same as phone property. If contact to be added is a internal user, add the request like this:
#{"add":[{"mri":"8:orgid:18c4a91b-4fa9-4fbd-ab1c-b39465d81baf","displayName":"Admin","isFederated":false,"email":"[email protected]"}]}
#To find the org id, run this command and look for it in a users buddies list:
#(Invoke-RestMethod -Uri $URL -Method GET -Headers $header -ContentType "application/json").value
$payload1 = @'
#Add phonenumber 1 to Speed Dial list.
Invoke-RestMethod -Uri $URL -Body $payload1 -Method POST -Headers $header -ContentType "application/json"
$payload2 = @'
#Add phonenumber 2 to Speed Dial list.
Invoke-RestMethod -Uri $URL -Body $payload2 -Method POST -Headers $header -ContentType "application/json"

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s