If you run a common sample.
1.GraphClient.Me.FindMeetingTimes, the error [/me request is only valid with delegated authentication flow.]
2.GraphClient.Users["id"].FindMeetingTimes, an [Invalid user address] error occurs.
The following is the result.
When I run POST in Graph Explorer (https://graph.microsoft.com/v1.0/users/{id}/microsoft.graph.findMeetingTimes), the response comes back correctly, but when I try with the source output in Code snippets However, an error occurs when trying with the source output in Code snippets.
[sample code (VSCode)]
Azure Function .Net 6 (LTS)Isolated
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Mvc;
using Azure.Identity;
using Microsoft.Graph;
using Microsoft.Graph.Models;
using Microsoft.Kiota.Abstractions.Authentication;
using Microsoft.Identity.Client;
namespace Company.Function
{
public class HttpTrigger0
{
private readonly ILogger _logger;
public HttpTrigger0(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<HttpTrigger5>();
}
[Function("HttpTrigger0")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestData req)
{
_logger.LogInformation("C# HTTP trigger function processed a request.");
// Dummy Id
var userId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
// https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?tabs=csharp#client-credentials-provider
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = Environment.GetEnvironmentVariable("TENANT_ID");
var clientId = Environment.GetEnvironmentVariable("CLIENT_ID");
var clientSecret = Environment.GetEnvironmentVariable("CLIENT_SECRET");
var options = new ClientSecretCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var requestBody = new Microsoft.Graph.Me.FindMeetingTimes.FindMeetingTimesPostRequestBody
//var requestBody = new Microsoft.Graph.Users.Item.FindMeetingTimes.FindMeetingTimesPostRequestBody
{
Attendees = new List<AttendeeBase>
{
new AttendeeBase
{
EmailAddress = new EmailAddress
{
Name = "User1",
Address = "user1@test.onmicrosoft.com",
},
},
new AttendeeBase
{
EmailAddress = new EmailAddress
{
Name = "User2",
Address = "user2@test.onmicrosoft.com",
},
},
new AttendeeBase
{
EmailAddress = new EmailAddress
{
Name = "User3",
Address = "user3@test.onmicrosoft.com",
},
},
},
};
try {
var result = await graphClient.Me.FindMeetingTimes.PostAsync(requestBody);
//var result = await graphClient.Users[userId].FindMeetingTimes.PostAsync(requestBody);
return new OkObjectResult(result);
} catch (Exception e) {
Console.WriteLine("TRC:" + e.StackTrace);
Console.WriteLine("ERR:" + e.Message);
return new OkObjectResult(null);
}
}
}
}
The error occurred as you are using client credentials flow to retrieve findMeetingTimes which is not supported.
To resolve the error, you need to switch to delegated flows like interactive flow or authorization code flow.
In your app registration, grant Calendars.Read.Shared
permission of Delegated type while using delegated flows.
If you prefer interactive flow, you need to add redirect URI in Mobile and Desktop applications platform like this:
Make sure to enable public client flows in your app registration while using interactive flow:
In my case, I ran below sample c# code in Console app to retrieve findMeetingTimes using interactive flow:
using Azure.Identity;
using Microsoft.Graph;
using Microsoft.Graph.Models;
using Microsoft.Graph.Models.ODataErrors;
// Dummy Id
var userId = "userId";
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenantID";
var clientId = "appID";
var clientSecret = "secret";
var options = new InteractiveBrowserCredentialOptions
{
TenantId = tenantId,
ClientId = clientId,
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
RedirectUri = new Uri("http://localhost"),
};
var interactiveCredential = new InteractiveBrowserCredential(options);
var graphClient = new GraphServiceClient(interactiveCredential, scopes);
var requestBody = new Microsoft.Graph.Me.FindMeetingTimes.FindMeetingTimesPostRequestBody
//var requestBody = new Microsoft.Graph.Users.Item.FindMeetingTimes.FindMeetingTimesPostRequestBody
{
Attendees = new List<AttendeeBase>
{
new AttendeeBase
{
EmailAddress = new EmailAddress
{
Name = "User1",
Address = "user1@test.onmicrosoft.com",
},
},
new AttendeeBase
{
EmailAddress = new EmailAddress
{
Name = "User2",
Address = "user2@test.onmicrosoft.com",
},
},
new AttendeeBase
{
EmailAddress = new EmailAddress
{
Name = "User3",
Address = "user3@test.onmicrosoft.com",
},
},
},
};
try
{
var result = await graphClient.Me.FindMeetingTimes.PostAsync(requestBody);
Console.WriteLine(result);
}
catch (ODataError odataError)
{
Console.WriteLine(odataError.Error.Code);
Console.WriteLine(odataError.Error.Message);
}
Reference: Choose a Microsoft Graph authentication provider - Microsoft Graph