0

I'm trying to read all planner tasks for a single plan with the GraphServiceClient using a registered app with the Group.Read.All and Group.ReadWrite.All permission in the azure portal.

I've tried using the Microsoft.Graph and the Microsoft.Graph.Beta packages but I always get an InternalServerError when calling any of the planner api endpoints.

Setting up the GraphServiceClient with the following code

IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
             .Create("ClientId")
             .WithTenantId("TenantId")
             .WithClientSecret("ClientSecret")
             .Build();

ClientCredentialProvider clientCredentialProvider = new ClientCredentialProvider(confidentialClientApplication);

GraphServiceClient graphClient = new GraphServiceClient(clientCredentialProvider);

works fine. Calling the group api with

try
{
    Task<IGraphServiceGroupsCollectionPage> groups = graphClient.Groups
        .Request()
        .GetAsync();
    groups.Wait();

    foreach (var item in groups.Result)
    {
        Console.WriteLine(item.DisplayName);
    }
}
catch (Exception e)
{
    Console.WriteLine(e);
}

Also works. But calling the planner API

try
{
    Task<PlannerPlan> plan = graphClient.Planner.Plans["PlanId"]
        .Request()
        .GetAsync();
    plan.Wait();
    Console.WriteLine(plan.Result.Title);
}
catch (Exception e)
{
    Console.WriteLine(e);
}

Only throws an expection Server Error in '/taskApi' Application.

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

[NullReferenceException: Object reference not set to an instance of an object.]
Microsoft.Office.Tasks.Service.S2SProxies.FederatedGraph.FederatedGraphService.DeserializeFederatedGraphObject(String json) +35
Microsoft.Office.Tasks.Service.S2SProxies.FederatedGraph.d__51.MoveNext() +1385 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +31
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +60
Microsoft.Office.Tasks.Service.S2SProxies.FederatedGraph.d__47.MoveNext() +509

[FederatedGraphProxyException: Error getting graph object]
Microsoft.Office.Tasks.Service.CorrelationSafeAsync.ExecuteSynchronously(Func`2 asyncFunction, CancellationToken cancellationToken) +294
Microsoft.Office.Tasks.Service.UserAccountManager.AadUserAccountManager.GetExternalUserInfoInternal(IdentityClaim claim) +520

[InvalidOperationException: Unexpected error retrieving graph object] Microsoft.Office.Tasks.Service.UserAccountManager.AadUserAccountManager.GetExternalUserInfoInternal(IdentityClaim claim) +1288
Microsoft.Office.Tasks.Service.UserAccountManager.AadUserAccountManager.EnsureUser(String displayName, Boolean isLogin, CancellationToken cancellationToken, IdentityClaim[] claims) +1013
Microsoft.Office.Tasks.Service.Authentication.AuthenticationModuleBase.EnsureUserAndSetCurrentUserProvider(HttpContextBase httpContext, IUserAuthentication currentUser) +936
Microsoft.Office.Tasks.Service.Authentication.AuthenticationModuleBase.HandleAuthenticatedUser(HttpContextBase httpContextBase, IUserAuthentication currentUser) +168
Microsoft.Office.Tasks.Service.Authentication.AuthenticationModuleBase.AuthorizeRequest(Object sender, EventArgs e) +1867
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +223 System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +213 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +91

Using my microsoft account works, altough I have to change the authentication provider.

Anything I'm missing in my code?

EDIT: Working Code

Thanks to @Jim Xu I got my code working. For anyone running into the same issue here is the working sample. I had to add the client secrect to the headers of all the requests, but still it works.

IPublicClientApplication publicClientApplication = PublicClientApplicationBuilder
.Create("CLientId")
.WithTenantId("TenantId")
.Build();
String[] scopes = new String[] { "Group.Read.All", "Group.ReadWrite.All" };
Func<DeviceCodeResult, Task> deviceCodeReadyCallback = async dcr => await Console.Out.WriteLineAsync(dcr.Message);

DeviceCodeProvider authProvider = new DeviceCodeProvider(publicClientApplication, scopes, deviceCodeReadyCallback);

GraphServiceClient graphClient = new GraphServiceClient(authProvider);
IGraphServiceGroupsCollectionRequest groupRequest = graphClient.Groups.Request();
groupRequest.Headers.Add(new HeaderOption("client_secret", "ClientSecrect"));

Task<IGraphServiceGroupsCollectionPage> groups = groupRequest.GetAsync();
groups.Wait();

foreach (var item in groups.Result)
{
    Console.WriteLine(item.DisplayName);
}
JoeJoe87577
  • 512
  • 3
  • 17
  • Use a sniffer like wireshark or fiddler. Error 500 indicates the request you are sending is not correct. Compare the 1st request headers in working api with non working c# application. Then modify c# to look like working api. – jdweng Apr 30 '20 at 12:55
  • The requests are, besides the different request url, the same. And I think the error is either our config in the azure portal, or, altough not very plausible, the api itself. – JoeJoe87577 Apr 30 '20 at 14:36
  • Are the two URLs processing the same type request (same API, same version)? How did you install the API on Server? The defaults on the server may be different. for example one may be processing http 1.0 and the other http 1.1. The version of Net could be different so you may need to publish and install the API. The API version could be different. – jdweng Apr 30 '20 at 16:39
  • I'm using the microsoft graph api. All requests go to grap.microsoft.com. I just added the app registration in our azure AD. – JoeJoe87577 Apr 30 '20 at 23:44

1 Answers1

1

According to your code, you use Client Credential flow to call Microsoft Plan API. In other words, you use the application permissions to call Microsoft Graph Plan API. It is wrong. According to the official document, We just can use Delegated permissions to call the API. So you will get the error. enter image description here

Regarding how to call the api with SDk, please refer to the following code(I test in the console application)

  1. Configure your Azure AD application

    a. open allowPublicClient setting enter image description here

    b. update API permissions. Please add require Delegated permissions : Group.Read.All, Group.ReadWrite.All

  2. Code

  string clientId = "";
            string tenantId = "";
            IPublicClientApplication publicClientApplication = PublicClientApplicationBuilder
            .Create(clientId)
            .WithTenantId(tenantId)
            .Build();
            var scopes = new string[] { "Group.Read.All", "Group.ReadWrite.All" };
            Func<DeviceCodeResult, Task> deviceCodeReadyCallback = async dcr => await Console.Out.WriteLineAsync(dcr.Message);

            DeviceCodeProvider authProvider = new DeviceCodeProvider(publicClientApplication, scopes, deviceCodeReadyCallback);
            GraphServiceClient graphClient = new GraphServiceClient(authProvider);
            Task<PlannerPlan> plan = graphClient.Planner.Plans["Lc1LT2z1aEqnACVeA8KtIGUABIeE"]
                .Request()
                .GetAsync();
             plan.Wait();
             Console.WriteLine("The plan tiltel : " + plan.Result.Title);
            Console.ReadLine();

enter image description here

Jim Xu
  • 21,610
  • 2
  • 19
  • 39