pnp / PnP

SharePoint / Office 365 Developer Patterns and Practices - Archived older solutions. Please see https://aka.ms/m365pnp for updated guidance
https://aka.ms/m365pnp
Other
1.9k stars 3.31k forks source link

SharePoint Online Provider-Hosted Add-in Error on clientContext.ExecuteQuery() #1619

Open jbartolome opened 7 years ago

jbartolome commented 7 years ago

Category

[x] Bug

Environment

[x] Office 365 / SharePoint Online

Expected or Desired Behavior

I attempted to run the following SharePoint PnP Sample found here: https://github.com/SharePoint/PnP/tree/master/Samples/UserProfile.Manipulation.CSOM

I specifically was interested in the expected/desired behavior to retrieve the user profile information when clicking the button for CodeSample1.aspx.

Observed Behavior

I had success one-time in outputting the list of user profile properties, however, upon subsequent debugging attempts, I get the following error when executing the line containing "clientContext.ExecuteQuery();":

Microsoft.SharePoint.Client.ServerUnauthorizedAccessException was unhandled by user code
  HResult=-2146233088
  Message=Access denied. You do not have permission to perform this action or access this resource.
  ServerErrorCode=-2147024891
  ServerErrorTraceCorrelationId=c7fbdd9d-f00b-3000-9f42-9d9ee552dee6
  ServerErrorTypeName=System.UnauthorizedAccessException
  ServerStackTrace=""
  Source=Microsoft.SharePoint.Client.Runtime
  StackTrace:
       at Microsoft.SharePoint.Client.ClientRequest.ProcessResponseStream(Stream responseStream)
       at Microsoft.SharePoint.Client.ClientRequest.ProcessResponse()
       at Microsoft.SharePoint.Client.ClientRequest.ExecuteQueryToServer(ChunkStringBuilder sb)
       at Microsoft.SharePoint.Client.ClientRequest.ExecuteQuery()
       at Microsoft.SharePoint.Client.ClientRuntimeContext.ExecuteQuery()
       at Microsoft.SharePoint.Client.ClientContext.ExecuteQuery()
       at FleetWeb.Controllers.HomeController.Index() in C:\tfs2\DefaultCollection\Fleet Management\SPO\Fleet Add-in\Fleet\FleetWeb\Controllers\HomeController.cs:line 39
       at lambda_method(Closure , ControllerBase , Object[] )
       at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
       at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
       at System.Web.Mvc.Async.AsyncControllerActionInvoker.ActionInvocation.InvokeSynchronousActionMethod()
       at System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
       at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult)
       at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
       at System.Web.Mvc.Async.AsyncResultWrapper.End[TResult](IAsyncResult asyncResult, Object tag)
       at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
       at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d()
       at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f()
  InnerException: 

I made sure to update the AppManifest.xml file with the appropriate permissions for the add-in to "Write" to the User Profiles (Social) of the tenant, so it looked like this in code:

  <AppPermissionRequests AllowAppOnlyPolicy="true">
    <AppPermissionRequest Scope="http://sharepoint/social/tenant" Right="Write" />
  </AppPermissionRequests>

With some research, I discovered that there is a new development pattern for using Tenant permissions for App-Only SharePoint Add-in's. I followed the steps found here: Developing using Tenant permissions with App-Only in SharePoint Online

Registering the add-in was a great exercise, however, I was still encountering the error on the line for "clientContext.ExecuteQuery();". I realized that this was still a permission issue and I had to assign the add-in with the appropriate permissions. I was able to get it to work by modifying the AppManifest.xml file with the following:

  <AppPermissionRequests AllowAppOnlyPolicy="true">
    <AppPermissionRequest Scope="http://sharepoint/social/tenant" Right="FullControl" />
    <AppPermissionRequest Scope="http://sharepoint/content/sitecollection" Right="FullControl" />
    <AppPermissionRequest Scope="http://sharepoint/content/tenant" Right="FullControl" />
  </AppPermissionRequests>

Now, my next goal is to reduce the amount of permissions such that it is sufficient for the add-in. I have not yet tried this, but I wanted to share my findings with others who are using a low-trust authorization for SharePoint provider-hosted add-in's (or apps) and are running into this issue. I believe that the permission request that was truly needed falls under the "/content/tenant" section, however, more testing needs to be done on this.

Any feedback on this approach and/or why this was not mentioned in the sample code is greatly appreciated!

Steps to Reproduce

I am using a development environment to debug the application on SharePoint Online. The steps that I followed were basically found in the sample found in Step 1.

  1. Clone the github repo found here: https://github.com/SharePoint/PnP/tree/master/Samples/UserProfile.Manipulation.CSOM
  2. Setup your site URL to a development SPO environment in Visual Studio (I am using VS2015)
  3. Setup your permissions in the AppManifest.xml to User Profile (Social) to "Write"
  4. Debug the program AS-IS (without registering the add-in)

The add-in may run successfully a couple of times then suddenly fail upon the "clientContext.ExecuteQuery();" call.

Syel commented 7 years ago

Hi,

Yesterday, one of our clients reported an issue with a Provider-Hosted App we had developped last year.

The issue is very similar: the app crashes approximatively 80% of the time we try to use it, and the troubleshooting lead us to the method we use to retrieve the user's properties:

SharePointContext spContext = SharePointContextProvider.Current.GetSharePointContext(Context);
using (ClientContext clientContext = spContext.CreateUserClientContextForSPHost())
{
    Web web = clientContext.Web;
    clientContext.Load(web);
    clientContext.ExecuteQuery();

    try
    {
        PeopleManager peopleManager = new PeopleManager(clientContext);
        PersonProperties personProperties = peopleManager.GetPropertiesFor(loginName);
        clientContext.Load(personProperties);
        clientContext.ExecuteQuery();

        return personProperties;
    }
    catch (Exception ex)
    {
        Response.AppendToLog(ex.StackTrace);
        return null;
    }

}

The error we got is the same as well: You do not have permission to perform this action or access this resource.


I know that posting this will not help solving the issue. However, since this App has been working for several months and until a few days ago (at most), it felt relevant to report, since this may not be an issue for the PnP sample only.

jbartolome commented 7 years ago

@Syel - It's great knowing that I'm not alone in this and I'm certain many of us who use this method would appreciate any type of insight for this. I actually have been using this method for not only the sample, but also in another SharePoint Online provider-hosted app using low-trust authentication. Both the sample code provided by the PnP and our provider-hosted app received the same error until I made the corrections on the AppManifest.xml file and the AppPermissions to scope to FullControl for the tenant and tenant/social (the UserProfiles).

I'm going to keep testing out various combinations in permissions because I do not like the thought of giving our Add-in FullControl of the tenant.

lousimonetti commented 7 years ago

@jbartolome did you ever get any up on this? I was trying the Provisioning.SiteCreation sample and am in the same boat. It is like the TokenHelper is not getting a valid token?

matmig commented 6 years ago

@lousimonetti @jbartolome. We are facing the same issue ([ServerUnauthorizedAccessException: Access denied. You do not have permission to perform this action or access this resource.]). I've even extended permissions to Tenant = Read, and today error appeared again. I will add only that my Provided Hosted Add-In is working 99% time fine, but sometimes, without any reasons, the error come back. Did you find any workaround how to fix it?

dpalfery commented 6 years ago

We are running into this same issue with an app that is in production and working, We are doing some bug fixes and additions and in the development environment are getting access denied when trying to execute the below with an app only context, Based on the comments above this seems to have been deprecated but can someone provide me with an official MS Post stating that.

        PeopleManager peopleManager = new PeopleManager(ctx);
        PersonProperties personProperties = peopleManager.GetPropertiesFor(currentUser.LoginName);
        ctx.Load(personProperties, p => p.AccountName, p => p.UserProfileProperties);
        ctx.ExecuteQuery();

@VesaJuvonen help us ob1 you are the only one that can

nsturdivant-prft commented 6 years ago

I'm having a similar issue; however, in my case I'm using an app-only client context (spContext.CreateAppOnlyClientContextForSPHost()). Does the type of client context object matter (meaning: app-only versus user) with respect to pulling user profile properties (assuming the add-in has the Read permission on the http://sharepoint/social/tenant scope)?

Looking at @jbartolome's original post, the referenced code sample uses a user client context. According to this documentation, it would seem that getting user profile properties using an app client context just isn't supported anymore?

AllowAppOnlyPolicy does not work with...User Profile CSOM operations...