0

I need to download files from a list from SPO using console app. Since the users have MFA enabled, I am using clientid, clientsecret.

I am able to read the metadata but when I am trying to download a file, it throws 401 unauthorized exception.

I cannot pass the context current credentials as the windows domain and the SharePoint domain are different.

So, is there something missing in the code or do I have to go with MFA authentication to download the file.

Here is the c# code:

using (var cc = new OfficeDevPnP.Core.AuthenticationManager().GetAppOnlyAuthenticatedContext(siteCollectionUrl,ClientId,clientSecret))
            {
                Web oWebsite = cc.Web;

                List list = cc.Web.Lists.GetByTitle("Shared Documents");
                CamlQuery camlQuery = new CamlQuery();
                camlQuery.ViewXml = "<View Scope='RecursiveAll'>" +
                          "<Query>" +
                              "<Where>" +
                                    "<Eq>" +
                                         "<FieldRef Name='FSObjType' />" +
                                         "<Value Type='Integer'>0</Value>" +
                                    "</Eq>" +
                             "</Where>" +
                           "</Query>" +
                        "</View>";//"<View><RowLimit>10000</RowLimit></View>";
                ListItemCollection colllist = list.GetItems(camlQuery);
                cc.Load(colllist);
                cc.ExecuteQuery();
                Console.WriteLine(cc.Web.Title);
                foreach (ListItem oListItem in colllist)
                {
                    DownloadAFile(oListItem, @"C:\Downloads");

                }
            };

private static void DownloadAFile(Microsoft.SharePoint.Client.ListItem item, string targetPath)
    {
        var ctx = (ClientContext)item.Context;
        var fileRef = (string)item["FileRef"];
        var fileName = System.IO.Path.GetFileName(fileRef);
        var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(ctx, fileRef);
        var filePath = System.IO.Path.Combine(targetPath, fileName);
        using (var fileStream = System.IO.File.Create(filePath))
        {
            fileInfo.Stream.CopyTo(fileStream);
        }
    }
Ed K
  • 1

2 Answers2

0

According to my research and testing, you can use the following code to connect SharePoint with MFA Enabled via CSOM:

static void Main(string[] args)  
{  
   string siteUrl = "https://<tenant-name>.sharepoint.com/sites/contosoteam";  
   var authManager = new OfficeDevPnP.Core.AuthenticationManager();  
   // This method calls a pop up window with the login page and it also prompts  
   // for the multi factor authentication code.  
   ClientContext ctx = authManager.GetWebLoginClientContext(siteUrl);  
   // The obtained ClientContext object can be used to connect to the SharePoint site.  
   Web web = ctx.Web;  
   ctx.Load(web, w => w.Title);  
   ctx.ExecuteQuery();  
   Console.WriteLine("You have connected to {0} site, with Multi Factor Authentication enabled!!", web.Title);  
}   

And you can using the following code to download file:

Microsoft.SharePoint.Client.File filetoDownload = web.GetFileByServerRelativeUrl("/sites/zellatest/test/Document.docx");
        ctx.Load(filetoDownload);
        ctx.ExecuteQuery();
        var fileRef = filetoDownload.ServerRelativeUrl;
        var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(ctx, fileRef);
        var fileName = Path.Combine("C:\\", (string)filetoDownload.Name);

        using (var fileStream = System.IO.File.Create(fileName))
        {
            fileInfo.Stream.CopyTo(fileStream);
        }

More information for reference: Using CSOM To Connect To A SharePoint Site With Multi Factor Authentication Enabled

Note: Microsoft is providing this information as a convenience to you. The sites are not controlled by Microsoft. Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there. Please make sure that you completely understand the risk before retrieving any suggestions from the above link.

halfer
  • 19,824
  • 17
  • 99
  • 186
Zella_msft
  • 372
  • 2
  • 4
  • Thanks for providing the solution. I am able to download the files with MFA authentication. However, I am trying to download it without MFA. I used clientid & client secret but it only provides the metadata of the list and list items. To download a file, I am looking for a way to pass in user information without MFA. – Ed K Aug 02 '22 at 16:46
  • @EdK What permissions you've assigned to your app? – Muhammad Obaidullah Ather Aug 05 '22 at 04:31
0

Make sure the app you've the AppOnlyPolicy set to true if you are using SharePoint app.

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

If you are using Azure AD app then your app should have Application Permissions (not Delegated Permissions)

here I've created a repo with the working code. Let me know if it works for you.