Connecting Azure Function to SharePoint list using Azure Function managed Identity sometime raise "There has been an error authenticating the request.";category="invalid_client""

john john Pter 1,015 Reputation points
2025-04-26T09:27:04.3166667+00:00

I have an Azure Function which we enabled its managed Identity, as follow:-

User's image

then we run those commands, to allow the azure function to access SharePoint using the Azure Function managed identity, based on this technical documentation https://learn.microsoft.com/en-us/sharepoint/dev/apis/webhooks/sharepoint-webhooks-using-azd-template#grant-the-function-app-access-to-sharepoint-online:-

Script for Site.Selected

# This script requires the modules Microsoft.Graph.Authentication, Microsoft.Graph.Applications, Microsoft.Graph.Identity.SignIns, which can be installed with the cmdlet Install-Module below:
# Install-Module Microsoft.Graph.Authentication, Microsoft.Graph.Applications, Microsoft.Graph.Identity.SignIns -Scope CurrentUser -Repository PSGallery -Force
Connect-MgGraph -Scope "Application.Read.All", "AppRoleAssignment.ReadWrite.All"
$managedIdentityObjectId = "****" # 'Object (principal) ID' of the managed identity
$scopeName = "Sites.Selected"
$resourceAppPrincipalObj = Get-MgServicePrincipal -Filter "displayName eq 'Office 365 SharePoint Online'" # SPO
$targetAppPrincipalAppRole = $resourceAppPrincipalObj.AppRoles | ? Value -eq $scopeName

$appRoleAssignment = @{
    "principalId" = $managedIdentityObjectId
    "resourceId"  = $resourceAppPrincipalObj.Id
    "appRoleId"   = $targetAppPrincipalAppRole.Id
}
New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $managedIdentityObjectId -BodyParameter $appRoleAssignment | Format-List

& Script for Sites.FullControl.All

# This script requires the modules Microsoft.Graph.Authentication, Microsoft.Graph.Applications, Microsoft.Graph.Identity.SignIns, which can be installed with the cmdlet Install-Module below:
# Install-Module Microsoft.Graph.Authentication, Microsoft.Graph.Applications, Microsoft.Graph.Identity.SignIns -Scope CurrentUser -Repository PSGallery -Force
Connect-MgGraph -Scope "Application.Read.All", "AppRoleAssignment.ReadWrite.All"
$managedIdentityObjectId = "****" # 'Object (principal) ID' of the managed identity
$scopeName = "Sites.FullControl.All"
$resourceAppPrincipalObj = Get-MgServicePrincipal -Filter "displayName eq 'Office 365 SharePoint Online'" # SPO
$targetAppPrincipalAppRole = $resourceAppPrincipalObj.AppRoles | ? Value -eq $scopeName

$appRoleAssignment = @{
    "principalId" = $managedIdentityObjectId
    "resourceId"  = $resourceAppPrincipalObj.Id
    "appRoleId"   = $targetAppPrincipalAppRole.Id
}
New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $managedIdentityObjectId -BodyParameter $appRoleAssignment | Format-List

And finally,

Connect-PnPOnline -Url "https://YOUR_SHAREPOINT_TENANT_PREFIX.sharepoint.com/sites/HR" -Interactive -ClientId "YOUR_PNP_APP_CLIENT_ID" 
Grant-PnPAzureADAppSitePermission -AppId "***" -DisplayName "YOUR_FUNC_APP_NAME" -Permissions Manage

now here is the code to connect to the SharePoint list:-

string accessToken = await GetJwtTokenUsingSystemManagedIdentity();

 string siteUrl = "https://**.sharepoint.com/sites/HR";

 string listName = "Call Transfer Log Data";

 string tenant = "***";

 string site = "analytics";

 string listTitle = "Call Transfer";

 siteUrl = $"https://{tenant}.sharepoint.com/sites/{site}";

 string apiBaseUrl = $"{siteUrl}/_api/web/lists/GetByTitle('{listTitle}')/items";

 var httpClient = new HttpClient();

 httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

 httpClient.DefaultRequestHeaders.Accept.ParseAdd("application/json;odata=verbose");

 string filterDate = DateTime.UtcNow.AddDays(-120).ToString("yyyy-MM-ddTHH:mm:ssZ");

 string requestUrl = $"{apiBaseUrl}?$filter=Modified ge datetime'{filterDate}'&$top=100&$orderby=Modified desc";

 bool hasMore = true;

 int page = 1;

 List<CallTransferLogData> responseContent = new List<CallTransferLogData>();

 while (hasMore)

 {

     Console.WriteLine($"Fetching page {page}...");

     var request = new HttpRequestMessage(HttpMethod.Get, requestUrl);

     var response = await httpClient.SendAsync(request);

     Console.WriteLine($"row response = " + response);

     string content = await response.Content.ReadAsStringAsync();

     using JsonDocument doc = JsonDocument.Parse(content);

     

     var root = doc.RootElement.GetProperty("d");

     Console.WriteLine($"Building Root {page}...");

     // Process results

     foreach (var item in root.GetProperty("results").EnumerateArray())

     { //code goes here

     }

}

        private static async Task<string> GetJwtTokenUsingSystemManagedIdentity()

        {

            string resource = "https://***.sharepoint.com/.default";

            var credential = new DefaultAzureCredential();

            var tokenRequestContext = new TokenRequestContext(new[] { resource });

            var token = await credential.GetTokenAsync(tokenRequestContext);

            //Console.WriteLine("Toekn is " + token.Token)

;            return token.Token;

        }

Now the azure function is suppose to run each day at 4 & 6 am UTC(). where yesterday at 11 pm UTC() , i deployed the azure function and to test it, i set its execution time to be 11:15 PM UTC(), and worked well, it got the items from SharePoint. then i modify the azure function to run at 4 & 6 am utc(). but today at 8 am UTC() i checked the logs and the call to SharePoint failed wit this exception:-

row response = StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:

x-ms-diagnostics: 3001000;reason="There has been an error authenticating the request.";category="invalid_client"

so i did a new deployed to test the azure function and i forced it to run at 8:30 am UTC(), but it raised the same error, so i did a new deployed and i set the execution time to be at 9 am UTC(), and i stopped the azure function after the deployment and i start it again.. now the call to SharePoint succeed, as follow:-

row response = StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:

so what is going on? is the reason that i need to stop/start the function after each deployment? or the azure function after certain amount of time, will fail to connect using its managed identity and will need a new deployment, and a new restart ?? Please any help on this?

Thanks

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

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.