"Get-MgUser" is raising " Insufficient privileges to complete the operation" and "Connect-ExchangeOnline -ManagedIdentity -Organization" is raising "UnAuthorized"

john john Pter 1,065 Reputation points
2025-05-20T19:14:07.1266667+00:00

I have an azure function running powershell, and here is the run.sp1, which mainly remove a user from all the groups; office 365 groups, distribution lists & security group (mail enabled and none-mail enabled):-

# Input bindings are passed in via param block.
param($Timer)
# Get the current universal time in the default string format.
$currentUTCtime = (Get-Date).ToUniversalTime()
# The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
if ($Timer.IsPastDue) {
    Write-Host "PowerShell timer is running late!"
}
# Write an information log with the current time.
Write-Host "PowerShell timer trigger function ran! TIME: $currentUTCtime"
# Connect to Microsoft Graph with required delegated scopes
 Write-Host "Start to connect to graph"
Connect-MgGraph -Identity
 Write-Host "Connected to Graph"
# Target user email
$userEmail = "test@****.onmicrosoft.com" 
 Write-Host "Start to Get-MgUser"
# --- PART 1: Azure AD + Office 365 Groups ---
$userList = Get-MgUser -Filter "mail eq '$userEmail' or userPrincipalName eq '$userEmail'"  -ConsistencyLevel eventual -All -Property Id, DisplayName, UserPrincipalName, Mail
 Write-Host "Get-MgUser completed"
$userObj = $userList | Select-Object -First 1
if (-not $userObj) {
    Write-Host "User $userEmail not found in Microsoft Graph. Skipping AAD removal."
} elseif (-not $userObj.Id) {
    Write-Host "User objectId missing even after lookup. Skipping AAD removal."
} else {
    Write-Host "Found user: $($userObj.DisplayName) ($($userObj.UserPrincipalName))"
    $groups = Get-MgUserMemberOf -UserId $userObj.Id -All
	$groupsAsOwner = Get-MgUserOwnedObject -UserId $userObj.Id -All
    foreach ($group in $groups) {
        if ($group.AdditionalProperties.'@odata.type' -ne '#microsoft.graph.group') {
            continue
        }
        $groupId = $group.Id
        $groupName = $group.AdditionalProperties.DisplayName
        if (-not $groupId) {
            Write-Host "Skipping group with empty ID"
            continue
        }
        $fullGroup = Get-MgGroup -GroupId $groupId
        if ($fullGroup.GroupTypes -contains "DynamicMembership") {
            Write-Host "Skipping dynamic group: ${groupName}"
            continue
        }
        # Remove as MEMBER
        try {
            Remove-MgGroupMemberByRef -GroupId $groupId -DirectoryObjectId $userObj.Id -ErrorAction Stop
            Write-Host "Removed as MEMBER from ${groupName}"
        }
        catch {
            Write-Host "Failed MEMBER removal from ${groupName}: $($_.Exception.Message)"
        }}
foreach ($group2 in $groupsAsOwner) {
$groupId2 = $group2.Id
$groupName2 = $group2.AdditionalProperties.DisplayName
        # Remove as OWNER
        try {
            Remove-MgGroupOwnerByRef -GroupId $groupId2 -DirectoryObjectId $userObj.Id -ErrorAction Stop
            Write-Host "Removed as OWNER from ${groupName2}"
        }
        catch {
            Write-Host "Failed OWNER removal from ${groupName2}: $($_.Exception.Message)"
        }
    }
	}
# --- PART 2: Exchange Distribution Groups + Mail-enabled Security Groups ---
# Connect to Exchange Online
 Write-Host "Start to Connect to exchange"
Connect-ExchangeOnline -ManagedIdentity -Organization ****.onmicrosoft.com
 Write-Host "Connected to exchange"
Write-Host "Start Get-DistributionGroup"
$dlGroups = Get-DistributionGroup -ResultSize Unlimited
Write-Host "completed Get-DistributionGroup"
foreach ($dl in $dlGroups) {
    try {
        # Remove as MEMBER
        $members = Get-DistributionGroupMember -Identity $dl.Identity -ResultSize Unlimited
        $memberMatch = $members | Where-Object { $_.PrimarySmtpAddress -ieq $userEmail }
        if ($memberMatch) {
            Remove-DistributionGroupMember -Identity $dl.Identity -Member $userEmail -BypassSecurityGroupManagerCheck -Confirm:$false
            Write-Host "Removed as MEMBER from Exchange group: $($dl.DisplayName)"
        }
        # Remove as OWNER
        # $owners = (Get-DistributionGroup -Identity $dl.Identity).ManagedBy
		$owners = (Get-DistributionGroup -Identity $dl.Identity).ManagedBy | Foreach-Object { Get-Mailbox $_ }
        $ownerMatch = $owners | Where-Object { $_.PrimarySmtpAddress -ieq $userEmail }
        if ($ownerMatch) {
            Set-DistributionGroup -Identity $dl.Identity -ManagedBy @{ Remove = "$userEmail" }
            Write-Host "Removed as OWNER from Exchange group: $($dl.DisplayName)"
        }
    }
    catch {
        Write-Host "Failed Exchange removal for group: $($dl.DisplayName) - $($_.Exception.Message)"
    }
}
Write-Host "Cleanup script completed."


now inside the azure function which run each 5 minutes, i am getting this error:-

2025-05-20T19:05:01Z [Error] ERROR: [Authorization_RequestDenied] : Insufficient privileges to complete the operation.

on

userList = Get-MgUser -Filter "mail eq '$userEmail' or userPrincipalName eq '$userEmail'"  -ConsistencyLevel eventual -All -Property Id, DisplayName, UserPrincipalName, Mail

and i am getting this error:-

UnAuthorized

on

Connect-ExchangeOnline -ManagedIdentity -Organization ***.onmicrosoft.com

now i have enabled managed identity for the azure function + run this command to grant the managed identity the need permissions:-

$tenantID = '0***e'

$managedIdentityObjectId = '7**b'

$msGraphApiResourceId = '00000003-0000-0000-c000-000000000000'

Connect-MgGraph -TenantId $tenantID -Scopes 'Application.Read.All','AppRoleAssignment.ReadWrite.All','Directory.Read.All'

# Find role ID for Group.ReadWrite.All

$msGraphSp = Get-MgServicePrincipal -Filter "appId eq '$msGraphApiResourceId'"

$role = $msGraphSp.AppRoles | Where-Object { $_.Value -eq 'Group.ReadWrite.All' }

# Assign the role

New-MgServicePrincipalAppRoleAssignment 

 -ServicePrincipalId $managedIdentityObjectId

 -PrincipalId $managedIdentityObjectId

 -ResourceId $msGraphSp.Id

 -AppRoleId $role.Id 

any advice?

thanks

Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
5,930 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Pravallika Kothaveeranna Gari 955 Reputation points Microsoft External Staff Moderator
    2025-05-23T10:22:48.3933333+00:00

    Hi john john Pter,

    The error usually occurs if the managed identity does not have required API permissions and roles to perform the action.

    • To connect to Exchange online, the managed identity must have any of the one Entra roles as mentioned in this MsDoc.

    2025-05-20T19:05:01Z [Error] ERROR: [Authorization_RequestDenied] : Insufficient privileges to complete the operation.

    • To resolve the above error and get users from groups, the managed identity must be assigned with Directory.Read.All and GroupReadWrite.All API permission.

    Hence to resolve the issue, assign API permissions like below:

    Connect-MgGraph -Scopes Application.Read.All, RoleManagement.ReadWrite.Directory, AppRoleAssignment.ReadWrite.All
    
    $params = @{
    
    	principalId = "ObjectIDofMSI"
    
    	resourceId = "2d751609-2fea-406a-8498-xxxx" ##ObjectId of Office 365 Exchange Online Enterprise application
    
    	appRoleId = "dc50a0fb-09a3-484d-be87-xxxx" #App permission ID of Exchange.ManageAsApp
    
    }
    
    New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId "ObjectIDofMSI" -BodyParameter $params
    
    

    image

    Assign Microsoft Graph API permissions:

    
    $params = @{
    
    	principalId = "ObjectIDofMSI"
    
    	resourceId = "c68a82f4-ecea-xxxx" #ObjectId of Microsoft Graph Enterprise application
    
    	appRoleId = "7ab1d382-f21e-4acd-a863-ba3e13f7da61" #App permission ID of Directory.Read.All
    
    }
    
     
    
    New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId "ObjectIDofMSI" -BodyParameter $params
    
    
    
    $params = @{
    
    	principalId = "ObjectIDofMSI"
    
    	resourceId = "c68a82f4-ecea-xxxx" #ObjectId of Microsoft Graph Enterprise application
    
    	appRoleId = "62a82d76-70ea-41e2-9197-370581804d09" #App permission ID of Group.ReadWrite.All
    
    }
    
     
    
    New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId "ObjectIDofMSI" -BodyParameter $params
    
    

    User's image

    The permissions will be assigned to the managed identity successfully:

    Go to Enterprise applications and search for your identity:

    User's image

    I assigned Exchange Admin role to the Function App's managed identity:

    User's image

    OUTPUT:

    Connected to Microsoft Graph:

    image

    Connected to Exchange:image

    Hope it helps!


    Please do not forget to click "Accept the answer” and Yes wherever the information provided helps you, this can be beneficial to other community members.

    User's image

    If you have any other questions or still running into more issues, let me know in the "comments" and I would be happy to help you.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.