CSOM to SharePoint Online via OAuth receives 401 Unauthorized

Jonathan Brauer (A) 0 Reputation points
2024-03-21T19:51:38.79+00:00

It looks like SharePoint Online no longer supports CSOM connections via OAuth? I've tried the following and nothing works. All return the following error:

401 Unauthorized.

x-ms-diagnostics: 3001000;reason="There has been an error authenticating the request.";category="invalid_client"

{"error_description":"ID3035: The request was not valid or is malformed."}.

#1 Via AuthenticationManager and CreateWithCertificate

         

  // Connect to the target SPO site via CSOM
            using (var clientContext = await AuthenticationManager.CreateWithCertificate(
                this.configuration.GetValue<string>("AppSettings:ClientId"),
                System.Security.Cryptography.X509Certificates.StoreName.My,
                System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser,
                this.configuration.GetValue<string>("AppSettings:CertificateThumbprint"),
                this.configuration.GetValue<string>("AppSettings:TenantId"))
                .GetContextAsync($"https://{spoTenant}{siteRelativeUri}"))
            {
                // Let's see if the current user is site admin
                var currentUser = clientContext.Web.CurrentUser;
                clientContext.Load(currentUser, u => u.IsSiteAdmin);
                await clientContext.ExecuteQueryAsync();

#2 Via ConfidentialClientApplicationBuilder and ClientSecret

     

  var confidentialClientApplication = ConfidentialClientApplicationBuilder.Create(clientId).WithClientSecret(clientSecret)
       .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
       .Build();
       
       var graphAuthResult = await confidentialClientApplication.AcquireTokenForClient(scopes)
           .ExecuteAsync();
       graphAccessToken = graphAuthResult.AccessToken;
var ctx = new ClientContext(config.webUrl);
 ctx.ExecutingWebRequest += async (sender, e) =>
 {
     e.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + graphAccessToken;
 };
 ctx.Load(ctx.Web, w => w.Lists);
 ctx.ExecuteQuery();

What am I missing? I think I've tried everything. Microsoft Graph connections work fine for the same app with both ClientSecret AND ClientCredential.

AuthenticationManager.CreateWithInteractiveLogin works fine.

Thanks,

Jonathan Brauer

SharePoint Development
SharePoint Development
SharePoint: A group of Microsoft Products and technologies used for sharing and managing content, knowledge, and applications.Development: The process of researching, productizing, and refining new or existing technologies.
2,673 questions
SharePoint Server Management
SharePoint Server Management
SharePoint Server: A family of Microsoft on-premises document management and storage systems.Management: The act or process of organizing, handling, directing or controlling something.
2,806 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. RaytheonXie_MSFT 31,226 Reputation points Microsoft Vendor
    2024-03-22T02:16:40.15+00:00

    Hi @Jonathan Brauer (A),

    Per my research, CSOM authentication is based on basic authentication. Basic auth doesn’t support scoping or grading permissions, so every app which connects with the basic auth protocol, gains potential access to all data a certain user has access to. As the describetion in the document you provided

    Basic authentication simply means the application sends a username and password with every request, and those credentials are also often stored or saved on the device. Traditionally, Basic authentication is enabled by default on most servers or services, and is simple to set up.

    The credential is stored in context and you always need to load it when get items from sharepoint by CSOM. So the CSOM authentication type is Basic Authentication.

    If you want to use authentication based on Oauth 2.0, I will recommend you to use SharePoint App-only using PnP Framework.

    string siteUrl = "https://contoso.sharepoint.com/sites/demo";  
    using (var cc = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, "[Your Client ID]", "[Your Client Secret]"))  
    {  
        cc.Load(cc.Web, p => p.Title);  
        cc.ExecuteQuery();  
        Console.WriteLine(cc.Web.Title);  
    };  
    

    Here is the document for more details

    https://learn.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azureacs


    If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.