I am trying to upload file on onedrive by using microsoft graph onedrive api. I am using the method for authentication Client credentials provider
Like:
// /.default scope, and preconfigure your permissions on the
// app registration in Azure. An administrator must grant consent
// to those permissions beforehand.
var scopes = new[] { "https://graph.microsoft.com/.default" };
// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "my-tenantid";
// Values from app registration
var clientId = "YOUR_CLIENT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";
// using Azure.Identity;
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
// https://learn.microsoft.com/dotnet/api/azure.identity.clientsecretcredential
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
HttpPostedFileBase file = Request.Files;[0];
int fileSize = file.ContentLength;
string fileName = file.FileName;
string mimeType = file.ContentType;
Stream fileContent = file.InputStream;
var res = await graphClient.Me.Drive.Root.ItemWithPath(fileName).Content
.Request()
.PutAsync<DriveItem>(fileContent);
After executing this code then it gives an error in response.
Message: /me request is only valid with delegated authentication flow.
Inner error:
AdditionalData:
date: 2021-12-29T05:30:08
request-id: b51e50ea-4a62-4dc7-b8d2-b26d75268cdc
client-request-id: b51e50ea-4a62-4dc7-b8d2-b26d75268cdc
ClientRequestId: b51e50ea-4a62-4dc7-b8d2-b26d75268cdc
Client credential flow will generate the token on behalf the app itself, so in this scenario, users don't need to sign in first to generate the token stand for the user and then call the api. And because of the design,when you used Me
in the graph SDK, your code/app don't know who is Me
so it can't work. You should know the user_id first and use /users/{id | userPrincipalName}
instead of /Me
, in the SDK, that is graphClient.Users["your_user_id"]
instead of graphClient.Me
In your scenario, there're 2 solutions, one way is using delegated authentication flow like what you said in your title, another way is get the user id before calling the graph api so that you can use Users["id"]
but not Me
===================== Update=========================
I haven't finished the code yet but I found the correct solution now.
Firstly, we can upload file to one drive by this api, you may check the screenshot if this is one drive or sharepoint:
https://graph.microsoft.com/v1.0/users/user_id/drive/items/root:/testupload2.txt:/content
If it is, then the next is easy, using the code below to get an access token and send http request to calling the api:
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenant_name.onmicrosoft.com";
var clientId = "your_azuread_clientid";
var clientSecret = "corresponding_client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var tokenRequestContext = new TokenRequestContext(scopes);
var token = clientSecretCredential.GetTokenAsync(tokenRequestContext).Result.Token;
I know it's complex because the api is not the same as this one which has SDK sample, but I think it also deserves to try if they are similar.