Use the OneDrive API without user interaction, such as a batch program (.NET C# version) (no additional use libraries)
Operating environment
- Visual Studio
-
- Visual Studio 2022
- .NET
-
- .NET 8
- Microsoft Authentication API
-
- 2.0 OAuth 2
- Microsoft OneDrive API
-
- 1.0
- Types of Microsoft accounts
-
- Work or school account
Prerequisites
- Visual Studio
-
- One of the versions
- .NET
-
- One of the versions
- Microsoft Authentication API
-
- 2.0 OAuth 2
- Microsoft OneDrive API
-
- 1.0
- Types of Microsoft accounts
-
- Work or school account
About the purpose of this event
Now you'll use the OneDrive APIs to prepare you for programmatically uploading and downloading files to OneDrive. In this article, we'll go into what you can do with the OneDrive API, so we'll not go into what you can do with the OneDrive API. However, as long as you can connect, you can read the API documentation and apply it after that.
How to run the program
Access to OneDrive is not dependent on the form of the program, such as a web application, a desktop application, or a console application, and can be run by a variety of programs. In this case, we will create a console application and execute it automatically without any user operation.
What are the different types of Microsoft accounts?
If you've ever created a Microsoft account, you've probably seen it. There are two main types of Microsoft accounts: personal Microsoft accounts and work or school accounts. OneDrive is tied to a Microsoft account, but the type of OneDrive varies slightly depending on the account type listed above.
For the time being, the OneDrive API can be used with both of the above types of accounts. In this program in the form of "created as a console application and executed without user operation", Please note that it can only be used with a Microsoft account in the "Work or school account" account. This is due to differences in authentication methods.
About the authentication method
First, you must authenticate in order to access OneDrive programmatically. As mentioned above, any program can access OneDrive, but the authentication to connect to the API depends on how the program is running. Web applications and desktop applications can be authenticated by user interaction. Since the user cannot operate it in a console application that runs in the background, the authentication method is also different from the above.
I don't know the detailed reason because I haven't been able to look it up, but if it comes to mind, it seems to be due to security and account management. I can only say that this is already a specification, so if you want to programmatically access OneDrive associated with a "personal Microsoft account", I think that there is no choice but to use a program other than a program that runs in the background, or to run a console application with an authentication method that includes user operations.
We won't be using the library to access the OneDrive API at this time
Access to the OneDrive API is relatively easy to handle using a library called "Microsoft Graph". In this case, we will use the method of directly accessing the URL of the API and executing it. It's a bit cumbersome, but since it doesn't use a library, it has the advantage that non-.NET programs can access the OneDrive API in the same way. It also prevents the disadvantage that the code changes due to different versions of the library.
We'll show you how to use Microsoft Graph in another tip.
precondition
- You have a Microsoft account for a work or school account
- You can use the OneDrive associated with the Microsoft account listed above (e.g., OneDrive Business)
- Visual Studio 2022 installed
Set up your application to access your Microsoft account or OneDrive in Azure
Log in to Azure at the following URL:
From the search field above, type "app registrations" and select it.
Click New Registration.
The content of the "Name" is arbitrary. Please enter a descriptive name.
Select a "Supported account type" other than "Personal Microsoft accounts only." This is because, as mentioned above, this authentication can only be used with accounts that belong to an organization. In this case, we've selected "Accounts in any organizational directory (any Microsoft Entra ID tenant - multi-tenant) and personal Microsoft accounts (Skype, Xbox, etc.)".
You do not need to enter the "Redirect URI" because it will not be used this time.
When you are done, click the "Register" button.
You'll be taken to the summary page of the app registration you created, so copy the Application (client) ID and Directory (tenant) ID. You'll use this value later.
Select "Certificates & secrets" from the management category in the left menu, and make sure "Client secrets" is selected in the middle tab. Click New Client Secret.
Entering a Description is optional. If you want to continue using it, please include an explanation that clearly explains the purpose of use.
The "expiration date" is the period of time that this client secret is valid. Since it is for testing purposes this time, it is 90 days, but please set it according to the purpose of use.
When you create a client secret, it is added to the list. In this, we will use the value in the "Value" column, so copy it. Note that this value cannot be copied later.
Next, select "API Permissions" from the Administration category in the left menu and click "Add Permissions" in the middle.
In the API permission request, click Microsoft Graph.
Click Allow Application. This option isn't available for personal Microsoft accounts.
A list of permissions will be displayed below, so use the search field to check the following items.
- Files.ReadWrite.All
That's enough if you only want to use OneDrive, but if you want to access anything else, add permissions. The permissions required to access OneDrive can be found on the official page below.
Once you've made your selections, click the Add Permissions button.
The added one is added to the list, and the "Type" is "Application". However, since the "Status" is "Not granted to XXXX", click "Give administrator consent to XXXX". (XXXX is the name of your organization)
Click Yes.
It changes to the granted state.
By the way, you can delete the "delegated User.Read" that is there from the beginning because we will not use it this time. If you added "User.Read" as an application, use it.
Verifying User IDs
Since you will be accessing the OneDrive that the target user has, check the user ID in advance.
Microsoft Entra ID
and open it.
Select Users from the menu on the left.
A list of users will be displayed, so click on the target user.
Make a note of the "Object ID" as it will be the user ID.
Create a console application
Start Visual Studio and create a project for your console application. You can create it outside of Visual Studio, but I'll use Visual Studio for now.
The location and project name are optional. In this case, the project name is OneDriveApiDotNetClientCredentialsHttpClient
.
This time, we will not divide the code, but Program.cs
will write it staggered from the top, so if you can check the movement, please rewrite it by dividing the code as necessary.
using System.Runtime.Serialization.Json;
using System.Text;
using System.Text.Json;
using System.Web;
using System.Xml;
Describe the namespace you want to use.
// 認証結果を格納するクラスです
public record TokenResponse(string token_type, int expires_in, int ext_expires_in, string access_token);
This class is used to receive token information after authentication.
Program.cs
, please write it at the end of the code.
You can separate this class into other files.
// JSON 文字列を整形するメソッド
static string ConvertToIndentedJson(string json)
{
byte[] buffer = Encoding.UTF8.GetBytes(json);
using MemoryStream stream = new();
using XmlDictionaryWriter writer = JsonReaderWriterFactory.CreateJsonWriter(stream, Encoding.UTF8, true, true);
using XmlDictionaryReader reader = JsonReaderWriterFactory.CreateJsonReader(buffer, XmlDictionaryReaderQuotas.Max);
writer.WriteNode(reader, true);
writer.Flush();
return Encoding.UTF8.GetString(stream.ToArray());
}
This is a magical method that formats JSON text received from the API with indentation. Since it is a code picked up from the Internet, I will not explain the contents in detail.
// 各種 ID などの定義
var clientId = "XXXXXXXX"; // クライアント ID
var tenantId = "XXXXXXXX"; // テナント ID
var clientSecret = "XXXXXXXX"; // クライアント シークレット
var userId = "XXXXXXXX"; // ユーザー ID
var accessToken = ""; // アクセストークン
Set the ID obtained on Azure for each.
accessToken
is a temporary token for accessing OneDrive, so it is set at runtime.
// 各種 URL の定義
var urlToken = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
var urlOneDriveGetRootFolders = $"https://graph.microsoft.com/v1.0/users/{userId}/drive/root/children";
The API URL for authentication and the API URL to get the list of folders at the root of OneDvie. This is a description of how to check access to the OneDrive API, so I will not describe the contents of the OneDrive API. If you have access to the OneDrive API, uploading and downloading is an application, so I don't think it's that difficult.
// 使いまわすので最初に定義しておく
HttpClient httpClient = new();
You have generated a to make a request to HttpClient
the specified URL.
// 「Name1=Value1&Name2=Value2...」形式のクエリパラメータ文字列を作成する
var valueDict = new Dictionary<string, string>
{
{ "client_id", clientId },
{ "scope", "https://graph.microsoft.com/.default" },
{ "client_secret", clientSecret },
{ "grant_type", "client_credentials" },
};
var valueQS = string.Join("&", valueDict.Select(x => string.Format("{0}={1}", x.Key, HttpUtility.UrlEncode(x.Value))));
Console.WriteLine($"valueQS={valueQS}");
First, you'll make a request to the authentication API with data, so prepare that data. The format of the data to be sent is a query parameter string in the format "Name1=Value1&Name2=Value2...", so it is created in a dictionary and then converted to a query parameter string.
There are four parameters to be sent:
ExampleParameter Name | Values |
---|---|
client_id | Set the client ID that you obtained in the app registration. |
scope | Authentication with a client secret is fixed https://graph.microsoft.com/.default . |
client_secret | Set the value of the client secret that you obtained in the app registration. |
grant_type | Since it is authentication with a client secret, client_credentials it will be |
For more information, please refer to the following official website.
// 認証処理
using (HttpRequestMessage request = new(HttpMethod.Post, urlToken))
{
request.Content = new StringContent(valueQS, Encoding.UTF8, "application/x-www-form-urlencoded");
// データを送信し結果を受け取る
using var response = httpClient.SendAsync(request).Result;
Console.WriteLine($"IsSuccessStatusCode={response.IsSuccessStatusCode}");
Console.WriteLine($"StatusCode={response.StatusCode}");
Console.WriteLine($"ReasonPhrase={response.ReasonPhrase}");
if (response.IsSuccessStatusCode == false)
{
Console.WriteLine("トークンの取得に失敗しました。");
return;
}
// レスポンスからアクセストークンを受け取る。
var tokenResultJson = response.Content.ReadAsStringAsync().Result;
Console.WriteLine($"tokenResultJson={ConvertToIndentedJson(tokenResultJson)}");
var tokenResult = JsonSerializer.Deserialize<TokenResponse>(tokenResultJson) ?? throw new Exception("JSON をデシリアライズできませんでした。");
accessToken = tokenResult.access_token;
}
HttpClient
to make a request to the authentication API. HttpClient
It's a common usage, so I don't think there's much to pay attention to.
The data to be sent must be UTF8 encoded and the Content-Type should be application/x-www-form-urlencoded
. The method is POST
.
If the IsSuccessStatusCode
response is checked and processed successfully, you will receive the result as a JSON string.
The JSON you receive has the following parameters:
{
"token_type": "Bearer",
"expires_in": 3599,
"ext_expires_in": 3599,
"access_token": "XXXXXXXXXXXXXXX"
}
In this, access_token
we will use . Use this value with the OneDrive API.
You can ignore the other parameters, butaccess_token
if you want to know the expiration date of , use expires_in
.
It is difficult to use as a JSON string, so JsonSerializer.Deserialize
we deserialize it with and then access_token
get .
// OneDrive 処理
using (HttpRequestMessage request = new(HttpMethod.Get, urlOneDriveGetRootFolders))
{
// アクセストークンをヘッダーに追加する
request.Headers.Add("Authorization", "Bearer " + accessToken);
// OneDrive API にリクエスト
using var response = httpClient.SendAsync(request).Result;
Console.WriteLine($"IsSuccessStatusCode={response.IsSuccessStatusCode}");
Console.WriteLine($"StatusCode={response.StatusCode}");
Console.WriteLine($"ReasonPhrase={response.ReasonPhrase}");
if (response.IsSuccessStatusCode == false)
{
Console.WriteLine("OneDrive へのアクセスに失敗しました。");
return;
}
// レスポンスからアクセストークンを受け取る。
var apiResultJson = response.Content.ReadAsStringAsync().Result;
Console.WriteLine($"apiResultJson={ConvertToIndentedJson(apiResultJson)}");
}
Finally, use the access token to make a request to the OneDrive API.
The method specifies GET
, but it depends on the type of API, so check the OneDrive API documentation.
Add the access token to the header. Set the key as Authorization
and the value in the Bearer {アクセストークン}
format .
All you have to do is make a request and receive the result as a JSON string. Now that we're just making sure we have access to the OneDrive API, we're just formatting the JSON string and printing it to the console. In fact, it deserializes the received JSON and processes it accordingly.
I have received a list of folders this time, but I think the JSON is as follows.
{
"@odata.context": "https:\/\/graph.microsoft.com\/v1.0\/$metadata#Collection(driveItem)",
"value": [
{
"@microsoft.graph.Decorator": "decorator has been deprecated. Refer to folder.decorator",
"createdBy": {
"フォルダ作成者の情報":""
},
"createdDateTime": "2017-06-20T04:31:24Z",
"eTag": "\"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX},1\"",
"id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"lastModifiedBy": {
"フォルダ更新者の情報":""
},
"lastModifiedDateTime": "2017-06-20T04:31:24Z",
"name": "フォルダ名",
"parentReference": {
"親フォルダの情報":""
},
"webUrl": "フォルダにアクセスできる URL",
"cTag": "\"c:{5926E2DA-B7FF-4936-88A8-7908C378ECE2},0\"",
"fileSystemInfo": {
"createdDateTime": "2017-06-20T04:31:24Z",
"lastModifiedDateTime": "2017-06-20T04:31:24Z"
},
"folder": {
"childCount": 0
},
"size": 0,
"specialFolder": {
"name": "フォルダ名"
}
},
:
]
}
I don't think you need all the information, so if you want to get only the folder name, for example, you value
can get only the parameters from name
the array in .
Summary
If it works fine so far, you should be able to access OneDrive with a batch program. I don't know if the tips summarize the methods of uploading and downloading, but basically it should work if you apply the list of folders in the root described above. The types of APIs are summarized on the official website below, so please find the API you want to use and implement it.
thanks
I had some questions about using the OneDrive API this time, so I asked a question.