I have an azure function which is based on PowerShell, here is the local.settings.json file:-
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "powershell",
"FUNCTIONS_WORKER_RUNTIME_VERSION": "7.4",
"AzureWebJobsStorage": "UseDevelopmentStorage=true"
}
}
and i have this code , to get all the items from a sharepoint list named "Emails" and remove the users from all their assigned groups (so i am using Pnp-PowerShell, Microsoft.Graph & ExchangeOnlineManagement):
# 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
Import-Module PnP.PowerShell
Write-Host "Start to connect to SharePoint"
$siteUrl = "https://****.sharepoint.com/sites/DemoCopilot"
Connect-PnPOnline -Url $siteUrl -ManagedIdentity
# Get all items from the 'emails' list
$items = Get-PnPListItem -List "emails"
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Groups
Write-Host "Start to connect to graph"
Connect-MgGraph -Identity
Write-Host "Connected to Graph"
# Connect to Exchange Online
Write-Host "Start to Connect to exchange"
Connect-ExchangeOnline -ManagedIdentity -Organization *****.onmicrosoft.com
Write-Host "Connected to exchange"
# Loop through items and delete each one
foreach ($item in $items) {
$userEmail = $item["Title"]
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 ---
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."
I added this to the requirements files:-
@{
'Az' = '13.*'
"Az.Accounts" = "2.*"
'ExchangeOnlineManagement' = '3.*'
'Microsoft.Graph' = '2.*'
'PnP.PowerShell' = '2.0.45-nightly'
}
But i got this error when the function runs:- ERROR: Could not load type 'Microsoft.Graph.Authentication.AzureIdentityAccessTokenProvider' from assembly 'Microsoft.Graph.Core, Version=1.25.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
2025-05-26T18:26:07Z [Information] INFORMATION: Connected to exchange
2025-05-26T18:26:07Z [Information] INFORMATION: Start to Get-MgUser
2025-05-26T18:26:07Z [Error] ERROR: Could not load type 'Microsoft.Graph.Authentication.AzureIdentityAccessTokenProvider' from assembly 'Microsoft.Graph.Core, Version=1.25.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
Exception :
Type : System.TypeLoadException
Message : Could not load type 'Microsoft.Graph.Authentication.AzureIdentityAccessTokenProvider' from assembly 'Microsoft.Graph.Core, Version=1.25.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
TypeName : Microsoft.Graph.Authentication.AzureIdentityAccessTokenProvider
TargetSite :
Name : GetGraphHttpClient
DeclaringType : [Microsoft.Graph.PowerShell.Authentication.Helpers.HttpHelpers]
MemberType : Method
Module : Microsoft.Graph.Authentication.dll
Source : Microsoft.Graph.Authentication
HResult : -2146233054
StackTrace :
at Microsoft.Graph.PowerShell.Authentication.Helpers.HttpHelpers.GetGraphHttpClient()
at Microsoft.Graph.PowerShell.Module.BeforeCreatePipeline(InvocationInfo invocationInfo, HttpPipeline& pipeline)
at Microsoft.Graph.PowerShell.Module.CreatePipeline(InvocationInfo invocationInfo, String parameterSetName)
at Microsoft.Graph.PowerShell.Cmdlets.GetMgUser_List.ProcessRecordAsync()
CategoryInfo : NotSpecified: (:) [Get-MgUser_List], TypeLoadException
FullyQualifiedErrorId : Microsoft.Graph.PowerShell.Cmdlets.GetMgUser_List
InvocationInfo :
MyCommand : Get-MgUser_List
ScriptLineNumber : 44
OffsetInLine : 1
HistoryId : 1
ScriptName : C:\home\site\wwwroot\PowerShellRemoveUserFromGroups\run.ps1
Line : $userList = Get-MgUser -Filter "mail eq '$userEmail' or userPrincipalName eq '$userEmail'" -ConsistencyLevel eventual -All -Property Id, DisplayName, UserPrincipalName, Mail
Statement : $userList = Get-MgUser -Filter "mail eq '$userEmail' or userPrincipalName eq '$userEmail'" -ConsistencyLevel eventual -All -Property Id, DisplayName, UserPrincipalName, Mail
PositionMessage : At C:\home\site\wwwroot\PowerShellRemoveUserFromGroups\run.ps1:44 char:1
+ $userList = Get-MgUser -Filter "mail eq '$userEmail' or userPrincipal …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PSScriptRoot : C:\home\site\wwwroot\PowerShellRemoveUserFromGroups
PSCommandPath : C:\home\site\wwwroot\PowerShellRemoveUserFromGroups\run.ps1
InvocationName : Get-MgUser
CommandOrigin : Internal
ScriptStackTrace : at Get-MgUser<Process>, C:\home\site\wwwroot\Modules\Microsoft.Graph.Users\2.28.0\exports\ProxyCmdletDefinitions.ps1: line 23082
at <ScriptBlock>, C:\home\site\wwwroot\PowerShellRemoveUserFromGroups\run.ps1: line 44
PipelineIterationInfo :
0
1
so what could be the reasons? i were able to call Graph, but this error occur only after i added the PnP.PowerShell module..