1

I'm struggeling to understand how to use SharePoint CSOM to add a user as Site Collection Admin.

So far this code works for a Global Admin to add a user as Site Colleciton Admin, eventhough the Global Admin is not included as Site Admin.

I've tried to run the code as normal user which is only Site Collection Admin, to add another user as Site Colleciton Admin. But then I get some errors:

  • If I use the SharePoint Admin URL to get the Access Token, then the code crash on row #48 as 401 "Unauthorized"

  • If I use the Site Collection URL to get the Access Token, I get error when trying to get the acces token saying that Site is doesn't exist on the environment.

  • If I use the root site URL ("https://domain-admin.sharepoint.com/) to get the Access Token, then the code crash on row #51 as 401 "Unauthorized".

I'm using the PnP.PowerShell code as reference: https://github.com/pnp/powershell/blob/dev/src/Commands/Admin/SetTenantSite.cs#L547-L574

And my process is pretty much the same as here: MSAL AD token not valid with SharePoint Online CSOM

But I don't have clear if it's a issue of access token or the CSOM commands I use.

Does anyone has any idea how to move forward?

btw, I guess if I use the Global Admin account I only need to use tenant.SetSiteAdmin(siteCollection, userEmail, true);. I read somewhere that even for global admin I need EnsureUser(userEmail);, but so far the code seems working without it.

using Microsoft.Identity.Client;
using Microsoft.SharePoint.Client;

namespace ScriptTester
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            await AddUserAdmin();

        }

        public static async Task AddUserAdmin()
        {
            string siteAdmin = "https://domain-admin.sharepoint.com/";
            string siteRoot = "https://domain.sharepoint.com/";
            string siteCollection = "https://domain.sharepoint.com/sites/SiteName/";
            string userEmail = "_email";

            string accessToken = await GetAccessToken(siteRoot);

            using (var context = new Microsoft.SharePoint.Client.ClientContext(siteRoot))
            {
                context.ExecutingWebRequest += (sender, e) =>
                {
                    e.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + accessToken;
                };

                var tenant = new Microsoft.Online.SharePoint.TenantAdministration.Tenant(context);

                try
                {
                    addLog("Try using tenant context");
                    tenant.SetSiteAdmin(siteCollection, userEmail, true);
                    tenant.Context.ExecuteQueryRetry();
                }
                catch (Exception ex)
                {
                    addLog("Failed using Tenant context");
                    addLog(ex.Message);
                    using (var site = tenant.Context.Clone(siteCollection))
                    {
                        var user = site.Web.EnsureUser(userEmail);
                        user.Update();
                        user.IsSiteAdmin= true;
                        site.Load(user);
                        site.ExecuteQueryRetry();

                        tenant.SetSiteAdmin(siteCollection, userEmail, true);
                        tenant.Context.ExecuteQueryRetry();
                    }
                }
            }
        }

        public static async Task<string> GetAccessToken(string siteUrl)
        {
            string tenantId = "xxxx-xxxx-xxxx-xxxx-xxx";
            string clientId = "xxxx-xxxx-xxxx-xxxx-xxx";
            Uri authority = new Uri($"https://login.microsoftonline.com/{tenantId}");
            string redirectUri = "http://localhost";

            string defaultPermissions = siteUrl + "/.default";
            string[] scopes = new string[] { defaultPermissions };

            var app = PublicClientApplicationBuilder.Create(clientId)
                                                    .WithAuthority(authority)
                                                    .WithRedirectUri(redirectUri)
                                                    .Build();

            AuthenticationResult result;

            result = await app.AcquireTokenInteractive(scopes)
                            .WithUseEmbeddedWebView(false)
                            .ExecuteAsync();

            return result.AccessToken;
        }
    }
}
Barbarur
  • 71
  • 3
  • try using this are a scope string[] scopes = new string[] { "https://.sharepoint.com/.default" }; – jimas13 Jan 09 '23 at 19:09

1 Answers1

0

I will recommend you to use PnP Core component to access site collection and add admin. Please refer to the following code

string siteUrl = "https://xxx.sharepoint.com/";  
string userName = "xxxx@xxx.onmicrosoft.com";  
string password = "*******";  
      
AuthenticationManager authManager = new AuthenticationManager();  
try  
{  
    using (var clientContext = authManager.GetSharePointOnlineAuthenticatedContextTenant(siteUrl, userName, password))  
    {  
        List<UserEntity> admins = new List<UserEntity>();  
        UserEntity admin = new UserEntity();  
        admin.LoginName = "nirmal";  
        admins.Add(admin);  

        clientContext.Site.RootWeb.AddAdministrators(admins, true);  
  
        Console.WriteLine("User added as Site Collection Admin");  
        Console.ReadKey();  
    }  
}  
catch (Exception ex)  
{  
    Console.WriteLine("Error Message: " + ex.Message);  
    Console.ReadKey();  
}