Access denied office 365 / SharePoint online with

2020-06-23 03:19发布

问题:

I am going crazy since two days solving an issue. The problem is;

I am making a console APP which is talking to SharePoint Online using global admin account (One which was specified as admin while making a new subscription). What I am trying to achieve is, I want to add a custom action using CSOM to each site collection and subsite of office 365. That code works fine except on the root site collection which is pre-created by office 365 while signing up (i.e. https://xyz.sharepoint.com)

For any tenant for root site collection, it gives me below error;

{ "SchemaVersion":"15.0.0.0","LibraryVersion":"16.0.3912.1201","ErrorInfo":{ "ErrorMessage":"Access denied. You do not have permission to perform this action or access this resource.","ErrorValue":null,"TraceCorrelationId":"2a47fd9c-c07b-1000-cfb7-cdffbe3ab83a","ErrorCode":-2147024891,"ErrorTypeName":"System.UnauthorizedAccessException" },"TraceCorrelationId":"2a47fd9c-c07b-1000-cfb7-cdffbe3ab83a" }

Now the user is global admin. I also added again that user as site collection admin.

The same piece of code works fine on other site collections (search site collection, any newly made site collection...).

here is a code;

        using (ClientContext spcollContext = new ClientContext(web.Url))
        {
            SecureString passWord = new SecureString();
            foreach (char c in strAdminPassword.ToCharArray()) passWord.AppendChar(c);
            SharePointOnlineCredentials creds = new SharePointOnlineCredentials(strAdminUser, passWord);
            spcollContext.Credentials = creds;
            Web currentweb = spcollContext.Web;
            spcollContext.Load(currentweb);
            spcollContext.ExecuteQuery();

       //     authCookie = creds.GetAuthenticationCookie(new Uri(web.Url));

            var existingActions2 = currentweb.UserCustomActions;
            spcollContext.Load(existingActions2);
            spcollContext.ExecuteQuery();
            var actions2 = existingActions2.ToArray();
            foreach (var action in actions2)
            {
                if (action.Description == "CustomScriptCodeForEachsite" &&
                    action.Location == "ScriptLink")
                {
                    action.DeleteObject();
                    spcollContext.ExecuteQuery();
                }
            }

            var newAction2 = existingActions2.Add();
            newAction2.Description = "CustomScriptCodeForEachsite";
            newAction2.Location = "ScriptLink";

            newAction2.ScriptBlock = scriptBlock;
            newAction2.Update();
            spcollContext.Load(currentweb, s => s.UserCustomActions);
            spcollContext.ExecuteQuery(); // GETTING ERROR ON THIS LINE. 
        }

Note: Above error is Fiddler traces.

回答1:

Most probably this behavior is caused by Custom Script feature, basically the issue occurs when the Custom Script feature is turned off

How to verify?

You could verify the site permissions using the following console app:

using (var ctx = GetContext(webUri, userName, password))
{
    var rootWeb = ctx.Site.RootWeb;
    ctx.Load(rootWeb, w => w.EffectiveBasePermissions);
    ctx.ExecuteQuery();
    var permissions = rootWeb.EffectiveBasePermissions;
    foreach (var permission in Enum.GetValues(typeof(PermissionKind)).Cast<PermissionKind>())
    {
        var permissionName = Enum.GetName(typeof(PermissionKind), permission);
        var hasPermission = permissions.Has(permission);
        Console.WriteLine("Permission: {0}, HasPermission: {1}", permissionName, hasPermission);
    }   
}

where

public static ClientContext GetContext(Uri webUri, string userName, string password)
{
    var securePassword = new SecureString();
    foreach (var ch in password) securePassword.AppendChar(ch);
    return new ClientContext(webUri) {Credentials = new SharePointOnlineCredentials(userName, securePassword)};
}

When SP.PermissionKind.AddAndCustomizePages is set to False, the Access denied error occurs while adding user custom action.

Solution

According to Turn scripting capabilities on or off:

For self-service created sites, custom scripting is disabled by default

Solution: enable Allow users to run custom scripts on self-service created sites

To enable or disable scripting from the SharePoint admin center

  1. Sign in to Office 365 with your work or school account.
  2. Go to the SharePoint admin center.
  3. Select Settings.
  4. Under Custom Script choose:

    • Prevent users from running custom script on personal sites or Allow users to run custom script on personal sites.

    • Prevent users from running custom script on user created sites or Allow users to run custom script on self-service created sites.

  5. Select OK. It takes about 24 hours for the change to take effect.

Since any change to the scripting setting made through the SharePoint Online admin center may take up to 24 hours to take effect, you could enable scripting on a particular site collection immediately via CSOM API (SharePoint Online Client Components SDK) as demonstrated below:

public static void DisableDenyAddAndCustomizePages(ClientContext ctx, string siteUrl)
{
    var tenant = new Tenant(ctx);
    var siteProperties = tenant.GetSitePropertiesByUrl(siteUrl, true);
    ctx.Load(siteProperties);
    ctx.ExecuteQuery();

    siteProperties.DenyAddAndCustomizePages = DenyAddAndCustomizePagesStatus.Disabled;
    var result = siteProperties.Update();
    ctx.Load(result);
    ctx.ExecuteQuery();
    while (!result.IsComplete)
    {
        Thread.Sleep(result.PollingInterval);
        ctx.Load(result);
        ctx.ExecuteQuery();
    }
}

Usage

using (var ctx = GetContext(webUri, userName, password))
{
    using (var tenantAdminCtx = GetContext(tenantAdminUri, userName, password))
    {                  
         DisableDenyAddAndCustomizePages(tenantAdminCtx,webUri.ToString());
    }
    RegisterJQueryLibrary(ctx);
 }

where

public static void RegisterJQueryLibrary(ClientContext context)
{
    var actions = context.Site.UserCustomActions;
    var action = actions.Add();
    action.Location = "ScriptLink";
    action.ScriptSrc = "~SiteCollection/Style Library/Scripts/jQuery/jquery.min.js";
    action.Sequence = 1482;
    action.Update();
    context.ExecuteQuery();
}


回答2:

If you don't have time for CSOM as described by Vadim, the page also links to a powershell script you can use:

Set-SPOsite <SiteURL> -DenyAddAndCustomizePages 0

But note that SiteUrl needs to be the admin url. If your tenant is https://mysite.sharepoint.com, the url you use is https://mysite-admin.sharepoint.com"

In our case, we were in the midst of a deployment when this hit and could not wait 24 hours (or even one hour!) to continue. Everything had been fine in our testing site collections, but when we deployed to the tenant root, we hit the error described above and this script fixed it. Apparently the feature is turned off by default on the tenant root.

Current site is not a tenant administration site

Turn scripting capabilities on or off



回答3:

My first response would be that you shouldn't add a CustomAction on the fly through code. That said, I'm sure you have a good reason to need to do so.

Try to set the AllowUnsafeUpdates flag on SPWeb to true as soon as you reference currentWeb. Make sure to also set it back to false after you call the final ExecuteQuery()

By default, AllowUnsafeUpdates is false. It is used to block cross-site scripting attacks.

https://msdn.microsoft.com/en-us/library/Microsoft.SharePoint.SPWeb_properties.aspx