I get an error 400 Bad Request when I try to upload a file to my OneDrive with a daemon app, using the Microsoft Graph API. I use a HttpClient, not a GraphServiceClient as the latter assumes interaction and works with a DelegatedAuthenticationProvider(?).
- The App is registered in AAD and has the right Application Permission (Microsoft Graph / File ReadWrite.All)
- The registration is for One Tenant and has no redirect url (as per instructions)
The main Method Upload
gets an AccessToken through a Helper AuthenticationConfig
and puts a file to OneDrive/SharePoint with the Helper ProtectedApiCallHelper
.
[HttpPost]
public async Task<IActionResult> Upload(IFormFile file)
{
var toegang = new AuthenticationConfig();
var token = toegang.GetAccessTokenAsync().GetAwaiter().GetResult();
var httpClient = new HttpClient();
string bestandsnaam = file.FileName;
var serviceEndPoint = "https://graph.microsoft.com/v1.0/drive/items/{Id_Of_Specific_Folder}/";
var wurl = serviceEndPoint + bestandsnaam + "/content";
// The variable wurl looks as follows: "https://graph.microsoft.com/v1.0/drive/items/{Id_Of_Specific_Folder}/proefdocument.txt/content"
var apicaller = new ProtectedApiCallHelper(httpClient);
apicaller.PostWebApi(wurl, token.AccessToken, file).GetAwaiter();
return View();
}
I get a proper Access Token using the following standard helper AuthenticationConfig.GetAccessToken()
public async Task<AuthenticationResult> GetAccessTokenAsync()
{
AuthenticationConfig config = AuthenticationConfig.ReadFromJsonFile("appsettings.json");
IConfidentialClientApplication app;
app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
.WithClientSecret(config.ClientSecret)
.WithAuthority(new Uri(config.Authority))
.Build();
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
AuthenticationResult result = null;
try
{
result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
return result;
}
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
{
...
return result;
}
}
With the AccessToken, the Graph-Url and the File to be uploaded (as an IFormFile) the Helper ProtectedApiCallHelper.PostWebApi
is called
public async Task PostWebApi(string webApiUrl, string accessToken, IFormFile fileToUpload)
{
Stream stream = fileToUpload.OpenReadStream();
var x = stream.Length;
HttpContent content = new StreamContent(stream);
if (!string.IsNullOrEmpty(accessToken))
{
var defaultRequestHeaders = HttpClient.DefaultRequestHeaders;
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
defaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
// Here the 400 Bad Request happens
HttpResponseMessage response = await HttpClient.PutAsync(webApiUrl, content);
if (response.IsSuccessStatusCode)
{
return;
}
else
{
//error handling
return;
}
}
}
EDIT
Please see the working solution below.