The new version of CSOM is focused on Azure AD app permissions and MSAL.net as a most comfortable library for authentication.
I meet one issue/blocker.
We can setup _Sites.FullControl.All_ as a most powerfull SharePoint permission for app in Azure AD.
I checked approach (CSOM + MSAL.net client credential flow (using certificate) and it works fine for working with site collections.
But these permissions are not enough for working with Tenant.
Should we expect some updates in Azure AD permissions for working with Tenant level? Some alternative for
Case: I have a function app V3 and I need to get all site collection from tenant.
var tenant = new Tenant(ctx);
var filter = new SPOSitePropertiesEnumerableFilter();
filter.IncludePersonalSite = PersonalSiteFilter.Exclude;
filter.IncludeDetail = false;
var sitesChunk = tenant.GetSitePropertiesFromSharePointByFilters(filter);
ctx.Load(sitesChunk);
ctx.ExecuteQuery();
My solution has valid sertificate and Sites.FullControl.All with admin consent permissions but seems it's not enough for this code and I got 401 error.
P.S. I figure out only one alternative - rebuild old TokenHelper and integrate it with .net core + SharePoint App-only permissions.
Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible.
@paveldanilchyk
that 'ctx' object you are using in your code above, is that connected to _yourtenant_.sharepoint.com or to _yourtenant-admin_.sharepoint.com? Connecting to the SharePoint admin site collection using your AAD app should give you the permissions needed for using the Tenant class.
@cwdata
ctx - ClientContext for admin site ( yourtenant-admin.sharepoint.com)
if you will use some other your site , you will get an error -'Current site is not a tenant administration site.'
Hi @paveldanilchyk, I tried to execute your code in CSOM with MSAL.Net certificate authentication, in a Console Application and it worked, even with _Sites.Manage.All_ permissions.
private static async Task<string> GetToken()
{
string applicationId = "AAD_APP_ID";
string tenantId = "contoso.onmicrosoft.com";
string sharePointUrl = "https://contoso-admin.sharepoint.com";
string certThumbPrint = "CERT_THUMBPRINT"; // Certificate is stored both in my machine and on my AAD application
IConfidentialClientApplication confApp = ConfidentialClientApplicationBuilder.Create(applicationId)
.WithAuthority($"https://login.microsoftonline.com/{tenantId}")
.WithCertificate(GetLocalCertificate(certThumbPrint)) // This is just a local method that gets the certificate on my machine
.Build();
var scopes = new[] { $"{sharePointUrl}/.default" };
var authenticationResult = await confApp.AcquireTokenForClient(scopes).ExecuteAsync();
return authenticationResult.AccessToken;
}
static void Main(string[] args)
{
var task = Task.Run(async () => { token = await GetToken(); });
task.Wait();
ClientContext ctx = new ClientContext(url);
ctx.ExecutingWebRequest += (s, e) =>
{
e.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + token;
};
Tenant tenant = new Tenant(ctx);
var filter = new SPOSitePropertiesEnumerableFilter();
filter.IncludePersonalSite = PersonalSiteFilter.Exclude;
filter.IncludeDetail = false;
var sitesChunk = tenant.GetSitePropertiesFromSharePointByFilters(filter);
ctx.Load(sitesChunk);
ctx.ExecuteQuery();
}
Maybe something's missing in the authentication? Can you share your sample?
Hi @michaelmaillot
Thank you.
Indeed I missed one smal but critical thing here. I need to have acccess to tenant administration and site collections, but I missed that scope must be different due to different domains.
string sharePointUrl = "https://contoso-admin.sharepoint.com";
This record helped me.
It works. Just need to keed in mind that scope should be dynamic in this situation.
Thank you.
Issues that have been closed & had no follow-up activity for at least 7 days are automatically locked. Please refer to our wiki for more details, including how to remediate this action if you feel this was done prematurely or in error: Issue List: Our approach to locked issues