Graph API for C#: 401 - Unauthorized: Access is denied due to invalid credentials. on /planner/plans

Viewed 3175

I am working with Graph API. I don´t have too much experience with this. I am creating an application to add a plan into an existing group.

So, I have registered an application with this permissions (You can see that these are Delegated permissions) :

enter image description here

Then, I have written this code to Add a new Planner (You will see that I am using a token) using this endpoint /planner/plans .

var configAuthority = "https://login.microsoftonline.com/8318d89e-e4db-471e-85da-b34ae833813f";
            IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
                                  .Create(ConfigurationParameters.ClientID)
                                  .WithTenantId(ConfigurationParameters.TenantID)
                                  .WithClientSecret(ConfigurationParameters.ClientSecret)
                                  .WithAuthority(new Uri(configAuthority))
                                  .Build();
            ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
            string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
            AuthenticationResult accessToken = confidentialClientApplication.AcquireTokenForClient(scopes).ExecuteAsync().Result;
            GraphServiceClient graphClient = new GraphServiceClient(authProvider);
            List<HeaderOption> requestHeaders = new List<HeaderOption>() {
                            new HeaderOption("Authorization", "Bearer " + accessToken.AccessToken)
                };
            var existingsplanners = graphClient
                                        .Groups[createPlannerForGroupRequest.GroupId.ToString()]
                                        .Planner
                                        .Plans.
                                        Request(requestHeaders)
                                        .GetAsync()
                                        .Result;
            var planner = graphClient
                        .Groups[createPlannerForGroupRequest.GroupId.ToString()]
                        .Planner
                        .Plans
                        .Request(requestHeaders)
                        .AddAsync(new PlannerPlan { 
                            Title = createPlannerForGroupRequest.Name,
                            Owner = createPlannerForGroupRequest.GroupId.ToString(),
                            ODataType = null,
                        }).Result;

The result for both requests are the same.

Code: UnknownError
Message: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<title>401 - Unauthorized: Access is denied due to invalid credentials.</title>
<style type="text/css">
<!--
body{margin:0;font-size:.7em;font-family:Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;}
fieldset{padding:0 15px 10px 15px;} 
h1{font-size:2.4em;margin:0;color:#FFF;}
h2{font-size:1.7em;margin:0;color:#CC0000;} 
h3{font-size:1.2em;margin:10px 0 0 0;color:#000000;} 
#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS", Verdana, sans-serif;color:#FFF;
background-color:#555555;}
#content{margin:0 0 0 2%;;}
.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;;}
-->
</style>
</head>
<body>
<div id="header"><h1>Server Error</h1></div>
<div id="content">
 <div class="content-container"><fieldset>
  <h2>401 - Unauthorized: Access is denied due to invalid credentials.</h2>
  <h3>You do not have permission to view this directory or page using the credentials that you supplied.</h3>
 </fieldset></div>
</div>
</body>
</html>

Inner error:
    AdditionalData:
    request-id: 19c09b10-1694-4201-85a9-ba3639e1dba5
    date: 2020-06-03T07:29:59
ClientRequestId: 19c09b10-1694-4201-85a9-ba3639e1dba5

As you can see, there is a permissions issue even if it is a delegated permissions on Azure AD. Should I wait 24 hours? Should I change the token requester method instead of use AcquireTokenForClient?

The same method works on Graph Explorer. Creation of Team instance for an existing group works fine.

Thank you!

1 Answers

It seems you use client credential grant flow in your code, but the graph api just support delegated permissions. So we need to use authorization code grant flow or username/password grant flow. (By the way, we recommend authorization code flow rather than username/password flow)

For authorization code flow, please refer to this tutorial with the code sample in it.

IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithRedirectUri(redirectUri)
    .WithClientSecret(clientSecret) // or .WithCertificate(certificate)
    .Build();

AuthorizationCodeProvider authProvider = new AuthorizationCodeProvider(confidentialClientApplication, scopes);

For username/password flow, you can refer to this tutorial with the code sample in it.

IPublicClientApplication publicClientApplication = PublicClientApplicationBuilder
            .Create(clientId)
            .WithTenantId(tenantID)
            .Build();

UsernamePasswordProvider authProvider = new UsernamePasswordProvider(publicClientApplication, scopes);

GraphServiceClient graphClient = new GraphServiceClient(authProvider);

User me = await graphClient.Me.Request()
                .WithUsernamePassword(email, password)
                .GetAsync();

Update:

You can do some changes by following the steps below, then you don't need to provide the client_secret in your code and it also will not show the error message The request body must contain the following parameter: 'client_assertion' or 'client_secret'.

  1. Go to your app registered in azure ad and click "Authentication" --> "Add a platform" --> "Mobile and desktop applications". enter image description here

  2. Choose the first one as the "Redirect URIs". enter image description here

  3. Scroll down and check if this configuration is "yes"(if "no", please change it to "yes"), then click "Save". enter image description here

Related