---
lang: ja-jp
breaks: true
---
# 概要

# WebAPI
## テンプレートからプロジェクトを作成


## csproj
```xml=
・・・
<ItemGroup>
<PackageReference Include="Microsoft.Identity.Web" Version="2.13.0" />
</ItemGroup>
・・・
```
## appsettings.json
```json=
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "WebAPIのアプリケーション (クライアント) ID",
"Domain": "[Enter the domain of your tenant, e.g. contoso.onmicrosoft.com]",
"TenantId": "WebAPIのディレクトリ (テナント) ID"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
```
## Program.cs
```csharp=
・・・
IConfigurationSection configuration = builder.Configuration.GetSection("AzureAd");
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(configuration);
・・・
```
## WeatherForecastController.cs
```csharp=
・・・
[Authorize(Roles = "API.Console")]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
・・・
```
:::info
`[Authorize(Roles = "API.Console")]`を追加する。
"API.Console"は、`Azure Active Directory` にアプリロールとして追加された値を指定する。
* 
* 
* 
:::
# Console
## テンプレートからプロジェクトを作成


## csproj
```xml=
・・・
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Identity.Web" Version="2.13.0" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
・・・
```
## appsettings.json
```json=
{
"Instance": "https://login.microsoftonline.com/{0}",
"Tenant": "コンソールアプリのディレクトリ (テナント) ID",
"ClientId": "コンソールアプリのアプリケーション (クライアント) ID",
"ClientSecret": "コンソールアプリのクライアントシークレットの値",
"BaseAddress": "https://localhost:44372",
"Scope": "WebAPIのアプリケーション ID の URI/.default",
"Certificate": {}
}
```
## AuthenticationConfig.cs
```csharp=
using Microsoft.Identity.Web;
namespace Console;
public class AuthenticationConfig
{
public string Instance { get; set; } = "https://login.microsoftonline.com/{0}";
public string Tenant { get; set; } = "";
public string ClientId { get; set; } = "";
public string ClientSecret { get; set; } = "";
public CertificateDescription? Certificate { get; set; } = null;
public string BaseAddress { get; set; } = "";
public string Scope { get; set; } = "";
}
```
## Program.cs
```csharp=
// See https://aka.ms/new-console-template for more information
using System.Diagnostics;
using System.Globalization;
using System.Net.Http.Headers;
using System.Text.Json.Nodes;
using Console;
using Microsoft.Extensions.Configuration;
using Microsoft.Identity.Client;
using Microsoft.Identity.Web;
System.Console.WriteLine("Hello, World!");
// Reads the configuration from a json file
AuthenticationConfig? config;
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
IConfigurationRoot Configuration = builder.Build();
config = Configuration.Get<AuthenticationConfig>();
}
if (config == null)
{
throw new Exception("AuthenticationConfig is null");
}
System.Console.WriteLine(config);
// Even if this is a console application here, a daemon application is a confidential client application
Uri authorityUri = new Uri(String.Format(CultureInfo.InvariantCulture, config.Instance, config.Tenant));
IConfidentialClientApplication app =
ConfidentialClientApplicationBuilder.Create(config.ClientId)
.WithClientSecret(config.ClientSecret)
.WithAuthority(authorityUri)
.Build();
// Add an in-memory well partitioned token cache to MSAL.NET confidential client application.
// Don't use this method in ASP.NET Core: rather use: services.AddInMemoryTokenCache() in ConfigureServices.
app.AddInMemoryTokenCache();
// With client credentials flows the scopes is ALWAYS of the shape "resource/.default", as the
// application permissions need to be set statically (in the portal or by PowerShell), and then granted by
// a tenant administrator
string[] scopes = new string[] { config.Scope };
AuthenticationResult? result = null;
result = await app.AcquireTokenForClient(scopes)
.ExecuteAsync();
if (result != null)
{
System.Console.WriteLine($"[AccessToken]{result.AccessToken}");
System.Console.WriteLine($"[ExpiresOn]{result.ExpiresOn.LocalDateTime.ToString()}");
await CallWebApiAndProcessResultASync(
$"{config.BaseAddress}/WeatherForecast",
result.AccessToken,
node => System.Console.WriteLine(node.ToString())
);
}
static async Task CallWebApiAndProcessResultASync(
string webApiUrl,
string accessToken,
Action<JsonNode> processResult
)
{
var httpClient = new HttpClient();
if (!string.IsNullOrEmpty(accessToken))
{
var defaultRequestHeaders = httpClient.DefaultRequestHeaders;
if ( defaultRequestHeaders.Accept == null
|| !defaultRequestHeaders.Accept.Any(m => m.MediaType == "application/json")
)
{
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json")
);
}
defaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
HttpResponseMessage response = await httpClient.GetAsync(webApiUrl)
.ConfigureAwait(false);
string content = await response.Content.ReadAsStringAsync()
.ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
string json = content;
JsonNode? result = JsonNode.Parse(json);
if (result != null)
{
processResult(result);
}
}
else
{
Debug.WriteLine($"Failed to call the Web Api: {response.StatusCode}[{content}]");
}
}
}
```
:::info
`AcquireTokenForClient`で取得される`AccessToken`の有効期限は、`ExpiresOn`により取得できる。
※取得後1時間の日時が取得される。
:::
# 実行

