I am trying to update a SharePoint CSOM application to use the Microsoft Graph API.
The existing program used credentials (username + password) from the SharePoint CSOM to download documents from SharePoint using the System.Net.WebClient library. What I can’t work out how to pass the authentication details from Microsoft graph to SharePoint.
Existing CSOM code:
ClientContext SharePoint;
remotePath = "https://{tenant}.sharepoint.com/sites/{site}/{list}/{filename}";
localPath = "C:\temp\{filename}";
//Authentication in CSOM using username/password not shown
using (var client = new System.Net.WebClient())
{
client.Credentials = SharePoint.Credentials;
client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
client.DownloadFileTaskAsync(remotePath, localPath).Wait();
}
With the Microsoft Graph I ahve attempted the below:
var parentWindowHandle = new System.Windows.Interop.WindowInteropHelper(App.Current.MainWindow).Handle;
var credentialOptions = new Azure.Identity.Broker.InteractiveBrowserCredentialBrokerOptions(parentWindowHandle)
{
ClientId = clientId,
TenantId = tenantId,
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
};
credential = new Azure.Identity.InteractiveBrowserCredential(credentialOptions);
GraphServiceClient graphClient = new GraphServiceClient(credential);
remotePath = "https://{tenant}.sharepoint.com/sites/{site}/{list}/{filename}";
localPath = "C:\temp\{filename}";
var tokenRequestContext = new Azure.Core.TokenRequestContext(new[] { "https://graph.microsoft.com/.default" });
token = await credential.GetTokenAsync(tokenRequestContext);
using (var client = new System.Net.WebClient())
{
client.Headers.Add("Authorization", "Bearer " + token.Token);
client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
client.DownloadFileTaskAsync(remotePath, localPath).Wait();
}
The response I get is:
401 UNAUTHORIZED
I have also tried getting a token for the scope “https://{tenant}.sharepoint.com/.default”, the result is the same.
I have tried with and without “User-Agent: Other” and “X-FORMS_BASED_AUTH_ACCEPTED”, “f” headers.
I see the same generic 401 if I paste the token returned by GetTokenAsync() into Postman.
Current API permissions (There are a lot of similar permissions from testing):
6
Initially, I registered one application and granted Files.Read.All
Microsoft Graph permission of Delegated type as below:
If you are using interactive flow for authentication, you need to add http://localhost
as redirect URI under “Mobile & Desktop applications” platform and enable public client flow option:
I have one file named Document.docx
in sridoclib drive of DemoSite like this:
To download this file locally using Microsoft Graph, you can make use of below sample c# code that asks user to login first and downloads file:
using Azure.Identity;
using Microsoft.Graph;
class Program
{
static async Task Main(string[] args)
{
var tenantId = "tenantId";
var clientId = "appId";
var driveId = "driveId";
var driveItemId = "fileId";
var localFilePath = "C:\test\Document.docx";
var options = new InteractiveBrowserCredentialOptions
{
TenantId = tenantId,
ClientId = clientId
};
var credential = new InteractiveBrowserCredential(options);
var graphClient = new GraphServiceClient(credential);
try
{
using (var stream = await graphClient.Drives[driveId].Items[driveItemId].Content.GetAsync())
{
using (var fileStream = new FileStream(localFilePath, FileMode.Create, FileAccess.Write))
{
await stream.CopyToAsync(fileStream);
}
}
Console.WriteLine("File downloaded successfully to: " + localFilePath);
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
}
}
Response:
To confirm that, I checked the same in local path where file downloaded successfully as below:
You can run below API calls in Graph Explorer to get the values of site ID, drive ID and driveItem ID respectively:
Site ID:
GET https://graph.microsoft.com/v1.0/sites/root:/sites/siteName
Drive ID:
GET https://graph.microsoft.com/v1.0/sites/siteIDfromAbove/drives?$filter=name eq 'driveName'
DriveItem / File ID:
GET https://graph.microsoft.com/v1.0/drives/driveIDfromAbove/root/children?$filter=name eq 'DocumentName.docx'&$select=id,name
Reference:
Download driveItem content – Microsoft Graph v1.0
3