Graph User.ReadBasic.All Application Permission Available

Controlling Application Access to Entra ID User Account Information

Message center notification MC704030 (5 January 2024) brings important news for developers that the User.ReadBasic.All permission is now available for both delegated and application usage. The permission restricts the ability of an app to retrieve properties of Entra ID user accounts to a basic set instead of all properties. The Microsoft Graph access model is based on least permissions, but if an app can always retrieve everything known about a user account, that hardly fits the definition of “least.”

Until now, the User.ReadBasic.All has been available for delegated permissions, meaning that it works in the context of the signed-in user and restricts the user to viewing the limited set of properties for other users. This is good, but many apps, including those run by PowerShell scripts, process user details and some of those apps don’t need access to all account properties. That’s where the User.ReadBasic.All permission comes in.

Testing the Effect of the User.ReadBasic.All Permission

Let’s examine what using the new permission means in practice. First, create a registered app in Entra ID. You can also use an existing app. The important thing is to ensure that the application permissions consented for the app include User.ReadBasic.All and no other permission that could allow the app to access full user information (like Directory.Read.All).

Fetch an access token for the app as normal and examine the access token to ensure that the permissions specified in the token are as expected. The access token shown through jwt.io in Figure 1 has two permissions: User.ReadBasic.All and Group.Read.All. The latter won’t allow the app to fetch extended user information, so it’s good to test.

An access token with the User.ReadBasic.All permission.
Figure 1: An access token with the User.ReadBasic.All permission

Running a Graph query to find properties for a specified user account returns the following:

$Uri = "https://graph.microsoft.com/v1.0/Users/21a3ce8f-6d55-4e57-9210-d85a2f1618ec?`$Select=businessPhones,displayname, givenname, jobtitle, mail,mobilephone,officelocation,preferredlanguage, surname, userprincipalname, id, department, city, stateorprovince, country, employeeid, employeetype, employeehiredate"
[array]$user = Get-GraphData -AccessToken $Token -Uri $Uri
$User | Format-List

businessPhones    : {}
displayName       : "Popeye" Doyle
givenName         : Jimmy
jobTitle          :
mail              : Popeye.Doyle@o365maestro.onmicrosoft.com
mobilePhone       :
officeLocation    :
preferredLanguage :
surname           : Doyle
userPrincipalName : Popeye.Doyle@o365maestro.onmicrosoft.com
id                : 21a3ce8f-6d55-4e57-9210-d85a2f1618ec
department        :
city              :
country           :
employeeId        :
employeeType      :
employeeHireDate  :

You can see that even though the query requested a bunch of user properties, the restricted permission limited the Graph to returning only some properties. If an app needs to retrieve all properties, it needs consent for the User.Read.All permission. The same query run by an app with User.Read.All permission returns this set:

businessPhones    : {1 404 14746141}
displayName       : "Popeye" Doyle
givenName         : Jimmy
jobTitle          : Chief Police Sleuth
mail              : Popeye.Doyle@o365maestro.onmicrosoft.com
mobilePhone       : 1 405 1461511
officeLocation    : Manhatten
preferredLanguage :
surname           : Doyle
userPrincipalName : Popeye.Doyle@o365maestro.onmicrosoft.com
id                : 21a3ce8f-6d55-4e57-9210-d85a2f1618ec
department        : Detectives
city              : NYC
country           : United States
employeeId        : 1461431
employeeType      : Permanent
employeeHireDate  : 06/06/2023 23:00:00

The difference in output is obvious!

Filtering with User.ReadBasic.All

Before rushing to limit all applications, make sure that you understand what properties each application needs to process. Also, in MC704030, Microsoft notes that they fixed a bug that allowed apps to filter on properties that should have been blocked (like the employee hire date property). Attempts to filter against unauthorized properties now generate a 403 “insufficient privileges” error. This can cause unexpected results.

For example, the code below uses a reasonably common query to find user accounts with assigned licenses that are member of the tenant rather than guest accounts. After using certificate-based authentication to sign into the Microsoft Graph PowerShell SDK (to use application rather than delegated permissions), the script runs the Get-MgUser cmdlet, and the cmdlet fails due to insufficient privileges.

Connect-MgGraph -TenantId $TenantId -AppId $AppId -CertificateThumbprint $CertificateThumbprint

(Get-MgContext).Scopes
Group.Read.All
User.ReadBasic.All

[array]$Users = Get-MgUser -Filter "assignedLicenses/`$count ne 0 and userType eq 'Member'" -ConsistencyLevel eventual -CountVariable Records -All -Property Id, userprincipalname, displayname, mail, city, country, usagelocation, usertype, signinactivity | Sort-Object displayName
Get-MgUser_List: Insufficient privileges to complete the operation.

The result is exactly what is expected. The Graph declines to run the query because of the filters against the assignedLicenses and UserType properties, neither of which are in the restricted set allowed by User.ReadBasic.All.

Pause Before Using User.ReadBasic.All

Like any improvement made by Microsoft, care must be exercised about taking advantage of the improvement. As in this case, implementing a change with the best intentions might have unfortunate side effects like stopping applications working. That’s always a bad thing.


Insight like this doesn’t come easily. You’ve got to know the technology and understand how to look behind the scenes. Benefit from the knowledge and experience of the Office 365 for IT Pros team by subscribing to the best eBook covering Office 365 and the wider Microsoft 365 ecosystem.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.