I am using Microsoft Graph SDK(C#) V5.56 with App-Only Authentication to upload files to SharePoint. However, when I upload a file, the lastModifiedBy field is always set to "SharePoint App". I need to set the lastModifiedBy field to a specific user instead of the SharePoint App.
Is there a way to upload a file to SharePoint and have the lastModifiedBy field reflect a user of my choice instead of the SharePoint App while using App-Only Authentication?
This code is working well but it set lastModifiedBy to 'SharePoint App' in sharepoint.
public static async Task ReplaceFileInOneDriveAsync(GraphServiceClient gsc, string driveId, string itemId, MemoryStream memoryStream)
{
memoryStream.Position = 0;
Microsoft.Kiota.Abstractions.RequestInformation requestInformations = gsc.Drives[driveId].Items[itemId].Content.ToPutRequestInformation(memoryStream);
requestInformations.URI = new Uri(requestInformations.URI.OriginalString + "?@microsoft.graph.conflictBehavior=replace");
var uploadResult = await gsc.RequestAdapter.SendAsync<DriveItem>(requestInformations, DriveItem.CreateFromDiscriminatorValue);
}
Also I tried some code starting with Users like this but failed.
gsc.Users["user1@constone.com"].Drives["someID"].....this doesn't contains Items :(
Please suggest!
As I mentioned in comments, lastModifiedBy field is set based on the context in which the file is modified.
When I ran below code to upload the file using App-Only Authentication, it set lastModifiedBy to 'SharePoint App' as the operation is performed on behalf of the application.
using System.Net.Http.Headers;
using Azure.Core;
using Azure.Identity;
namespace UserProperties
{
public class GraphHandler
{
private readonly string _clientId = "appId";
private readonly string _clientSecret = "secret";
private readonly string _tenantId = "tenantId";
private readonly string _authorityHost = "https://login.microsoftonline.com/";
public async Task UploadFileToSharePoint(string siteId, string driveId, string fileName, string filePath)
{
try
{
var accessToken = await GetAccessTokenAsync();
var uploadUrl = $"https://graph.microsoft.com/v1.0/sites/{siteId}/drives/{driveId}/items/root:/{fileName}:/content";
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
using (var httpRequest = new HttpRequestMessage(HttpMethod.Put, uploadUrl))
{
httpRequest.Content = new StreamContent(fileStream);
httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
using (var response = await httpClient.SendAsync(httpRequest))
{
response.EnsureSuccessStatusCode();
Console.WriteLine("File uploaded successfully.");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error uploading file: {ex.Message}");
}
}
private async Task<string> GetAccessTokenAsync()
{
var options = new TokenCredentialOptions
{
AuthorityHost = new Uri(_authorityHost)
};
var clientSecretCredential = new ClientSecretCredential(_tenantId, _clientId, _clientSecret, options);
var tokenRequestContext = new TokenRequestContext(new string[] { "https://graph.microsoft.com/.default" });
var accessTokenResult = await clientSecretCredential.GetTokenAsync(tokenRequestContext);
return accessTokenResult.Token;
}
}
class Program
{
static async Task Main(string[] args)
{
var handler = new GraphHandler();
var siteId = "siteId";
var driveId = "driveId";
var fileName = "logo.jpg";
var filePath = "C:\\Users\\xxxxxxx\\Downloads\\srrprofile.jpg";
await handler.UploadFileToSharePoint(siteId, driveId, fileName, filePath);
}
}
}
SharePoint Portal:
To set a specific user as the modifier, you need to switch to
Delegated
flows like interactive flow or authorization code flow that involves user interaction.
I registered one Entra ID application and granted permissions of Delegated
type as below:
While using interactive flow, make sure to add redirect URI in Mobile & Desktop applications
platform and enable public client flow option like this:
Now, I ran below modified code that asks the user to login and uploads file to SharePoint setting that user as modifier as below:
using System.Net.Http.Headers;
using Azure.Core;
using Azure.Identity;
namespace UserProperties
{
public class GraphHandler
{
private readonly string _clientId = "appId";
private readonly string _tenantId = "tenantId";
private readonly string _authorityHost = "https://login.microsoftonline.com/";
public async Task UploadFileToSharePoint(string siteId, string driveId, string fileName, string filePath)
{
try
{
var accessToken = await GetAccessTokenAsync();
var uploadUrl = $"https://graph.microsoft.com/v1.0/sites/{siteId}/drives/{driveId}/items/root:/{fileName}:/content";
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
using (var httpRequest = new HttpRequestMessage(HttpMethod.Put, uploadUrl))
{
httpRequest.Content = new StreamContent(fileStream);
httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
using (var response = await httpClient.SendAsync(httpRequest))
{
response.EnsureSuccessStatusCode();
Console.WriteLine("File uploaded successfully.");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error uploading file: {ex.Message}");
}
}
private async Task<string> GetAccessTokenAsync()
{
var options = new InteractiveBrowserCredentialOptions
{
AuthorityHost = new Uri(_authorityHost)
};
var interactiveCredential = new InteractiveBrowserCredential(_tenantId, _clientId, options);
var tokenRequestContext = new TokenRequestContext(new string[] { "https://graph.microsoft.com/.default" });
var accessTokenResult = await interactiveCredential.GetTokenAsync(tokenRequestContext);
return accessTokenResult.Token;
}
}
class Program
{
static async Task Main(string[] args)
{
var handler = new GraphHandler();
var siteId = "siteId";
var driveId = "driveId";
var fileName = "logo.jpg";
var filePath = "C:\\Users\\xxxxxx\\Downloads\\srrprofile.jpg";
await handler.UploadFileToSharePoint(siteId, driveId, fileName, filePath);
}
}
}
SharePoint Portal: