Sometimes, something simple as writing a filter query to search for Entra ID users which have a specific phone number can take way longer than we would like. Instead of making you search through numerous Stack Overflow posts or ask ChatGPT on how to do it, I decided to write this short blog post which will give you everything you need to quickly find Entra ID users which have a specific phone number.
Number Types
The most common numbers in Entra ID are Mobile phone and Business Phone. While the Entra ID admin portal displays Business phone
in singular, the property is actually called businessPhones
and is a string collection.
Filter Queries
This page tells us which conditions are supported for which user properties. I wasn’t able to get this to work using Get-MgUser -Filter "Filter Query"
since an API request using an advanced filter query will require a special header. Not long ago, I wrote about the Invoke-MgGraphRequest
Cmdlet and how that can be used to call the Graph REST API directly using the session token from Connect-MgGraph
.
To make it work, you’ll need to create a header with ConsistencyLevel: eventual
which is then added to the Graph Request.
Since this is a web request, you’ll also need to url encode the +
character. A simple replace with %2B
will do the trick here. It’s important to note that this will only work if the phone number is stored on the Entra user exactly the same as what’s in the filter query. For example, it won’t work if the phone number is stored without spaces in Entra but you’re querying it with spaces. If your phone numbers in Entra are a mess, I recommend to take a look at this blog post. This will show you how you can format all phone numbers in the same, and most importantly in the correct way.
Here’s how to create the header.
|
|
PowerShell Example
Here is an example script which contains all possible filter conditions for both mobile and business phone numbers. The important thing here is that the custom header is included and that the Uri includes the Count variable. Note that the businessPhones
property does not support the in
condition.
|
|
Example Output
What’s a little weird is that PowerShell outputs an array with name/value pairs instead of a PS custom object.
While it’s possible to access properties directly, it doesn’t work in Format-Table
.
A simple trick to convert the array returned by Graph into a PS custom object I often use is to convert it to Json and than convert it from Json straight away again.
|
|
Obviously, you can do the same for the $mgUserMatchesBusinessPhone
variable. That will store and display the values as a proper PowerShell object.
Now you can work with the $mgUserMatchesMobilePhone
and $mgUserMatchesBusinessPhone
as expected and do anything you want with them.
Bonus Tip (Power Automate)
The standard action Search for users (V2) from the Office 365 Users connector doesn’t support to filter for phone numbers of any type.
Luckily, there’s also a an action called Send an HTTP request within the Office 365 Users connector. This will allow you to make the same kinds of advanced requests to the Graph API as I’ve shown above with PowerShell.
Below is an example of a simple Power Automate Flow that can also filter for Entra ID users by phone number. What’s important is that you also need to add the ConsistencyLevel header and that you must remove all occurrences of the escape character `
from the Uri. Since Power Automate does not use $
to define variables, the escape character is not needed/supported here. The &$count=true
also needs to be included at the end of the Uri.
Since this is just an example, the phone number used as the filter is simply stored in Compose Phone Number action. The next action, Compose Phone Number URL Safe will replace the +
with %2B
using an expression.
|
|
To extract the Display Name of the result, I’m using another compose action with the following expression.
|
|
Example Output
If there is a user match for the phone number, Graph will return a nice Json response to Power Automate.
Summary & Download
I hope that these examples help you with whatever you’re trying to achieve. I’m certainly going to use this blog post as a cheat sheet for myself in the future. You can also download the entire script from my GitHub profile.