'How to get Microsoft 365 Planner 'All Plans for all users' using Microsoft Graph

We have got a requirement to list all Plans for all users along with their respective buckets within the organization.

I tried OAuth authorization services (AAD > App registrations) to access the planner APIs/resources using the Graph API Endpoint however I am getting access denied - It is important to mention here that the app has got all the privileges.

Does Microsoft allow to read all Planners data? provided the account has all the required permissions - if so then what am I missing here?

public static string GetAccessToken_Delegate()
    {
        try
        {
            AuthenticationContext authContext = new AuthenticationContext(Globals.AuthorityUrl, true);
            AuthenticationResult authResult = authContext.AcquireTokenAsync(Globals.GraphResourceUrl, Globals.AppId, new Uri(Globals.RedirectUri), new PlatformParameters(PromptBehavior.Auto)).Result;
            return authResult.AccessToken;
        }
        catch (Exception ex)
        {
            WriteLogEvents.WriteException(ex);
        }
        return null;
    }

    public static GraphServiceClient GetGraphClient(string graphToken)
    {
        try
        {
            DelegateAuthenticationProvider authenticationProvider = new DelegateAuthenticationProvider(
            (requestMessage) =>
            {
                requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", graphToken);
                return Task.FromResult(0);
            });
            return new GraphServiceClient(authenticationProvider);
        }
        catch (Exception ex)
        {
            WriteLogEvents.WriteException(ex);
        }
        return null;
    }

    public async static Task<List<PlansData>> GetPlans()
    {
        List<PlansData> plansData = new List<PlansData>();
        try
        {
            String accessToken = GetAccessToken_Delegate();
            GraphServiceClient graphClient = GetGraphClient(accessToken);
            if (graphClient != null)
            {
                message += string.Format("GraphClient Base Url: {0}", graphClient.BaseUrl) + Environment.NewLine;

                plansData = await GetGroup(graphClient, plansData);
            }
            else
                throw new Exception("GraphServiceClient is null");
        }
        catch (Exception ex)
        {
            WriteLogEvents.WriteException(ex);
        }
        finally
        {
        }
        return plansData;
    }

    public async static Task<List<PlansData>> GetGroup(GraphServiceClient graphClient, List<PlansData> plansData)
    {
        try
        {
            IGraphServiceGroupsCollectionPage groupCollection = await graphClient.Groups.Request().GetAsync();

            if (groupCollection?.Count > 0)
            {
                message += string.Format("Group Count: {0}", groupCollection.Count) + Environment.NewLine;

                foreach (Microsoft.Graph.Group group in groupCollection)
                {
                    if (group is Microsoft.Graph.Group)
                    {
                        if (group != null && group.GroupTypes != null && group.GroupTypes.Count() > 0)
                        {
                            plansData = await GetPlanData(graphClient, plansData, group);
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            WriteLogEvents.WriteException(ex);
        }
        return plansData;
    }

    public async static Task<List<PlansData>> GetPlanData(GraphServiceClient graphClient, List<PlansData> plansData, Microsoft.Graph.Group group)
    {
        try
        {
            //https://graph.microsoft.com/v1.0/groups/a047a2b3-3687-4464-bbdb-084f675c7528/planner/plans

            //Get Plans Information based on the group id
            IPlannerGroupPlansCollectionPage plansCollection = await graphClient.Groups[group.Id].Planner.Plans.Request().GetAsync();
            if (plansCollection?.Count > 0)
            {
                message += string.Format("Plans Count: {0}", plansCollection.Count) + Environment.NewLine;

                foreach (PlannerPlan record in plansCollection)
                {
                    List<Bucket> bucketsList = await GetBuckets(graphClient, record.Id);
                    Groups groupData = new Groups(group.Id, group.DisplayName);
                    string siteUrl = string.Format("https://myOrg.sharepoint.com/teams/{0}/", group.MailNickname);
                    plansData.Add(new PlansData(record.Id, record.Title, siteUrl, groupData, bucketsList));
                }
            }
        }
        catch (Exception ex)
        {
            WriteLogEvents.WriteException(ex);
        }
        return plansData;
    }

    public async static Task<List<Bucket>> GetBuckets(GraphServiceClient graphClient, string planId)
    {
        List<Bucket> bucketsList = new List<Bucket>();

        try
        {
            //https://graph.microsoft.com/v1.0/planner/plans/CONGZUWfGUu4msTgNP66e2UAAySi/buckets

            //Get Plans Information based on the group id
            IPlannerPlanBucketsCollectionPage bucketCollection = await graphClient.Planner.Plans[planId].Buckets.Request().GetAsync();
            if (bucketCollection?.Count > 0)
            {
                message += string.Format("Buckets Count: {0}", bucketCollection.Count) + Environment.NewLine;

                foreach (PlannerBucket bucket in bucketCollection)
                {
                    Bucket b = new Bucket(bucket.Id, bucket.Name);
                    bucketsList.Add(b);
                }
            }
        }
        catch (Exception ex)
        {
            WriteLogEvents.WriteException(ex);
        }
        return bucketsList;
    }

enter image description here

Thanks in advance.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source