この記事では、認証基盤であるAzure AD からユーザー一覧を取得する実装についてお話しできればと思います。
具体的には.NETのSDKを使ってMicorsoft Graph API 経由でAzure AD からユーザー一覧を取得するAPIを作成します。
当方も日々、新しい知識と戦っていますので、間違いがあれば教えてください!!!
前提条件
- Azure ADを含むAzure環境を自由に操作できる
- Visual Studioがインストールされている(Visual Studio Code などのソースコードエディタでもできるっちゃできる)
- PostmanなどのAPIをたたけるツールがある
Microsoft Graphとは
詳しくは公式ドキュメントから
簡単にまとめると、Microsoft のサービスである Office 365 や Azure AD など、様々なサービスのデータをグラフ形式で扱えるエンドポイントです。グラフ形式でデータを扱えるので、「自分の予定」や「自分の上司」などデータを関連から取得できるものです。
Azure Portalでの準備
Azure ADでアプリの登録
Azure AD では「アプリの登録」という機能を使ってあらかじめ登録されているWebアプリケーションからであれば認証要求は受け付けるよ!という機能があります。
こういう機能のことをサービスプリンシパルといいます。
新規作成
「Azure Active Directory」⇒「アプリの登録」⇒「新規作成」からアプリケーションの登録を行います。(命名は目を瞑ってください...)
アクセス許可の付与
アプリの概要のページから、左のメニューの[APIのアクセス許可]を選択
- [+アクセス許可の追加]をクリックし、付与したいAPIを選択
- 今回はGraph APIを使って、ユーザー情報の読み取りを行います
- [Microsoft Graph API]を選択
- [委任されたアクセス許可] ... (A) 対話的にユーザーが許可を与える
- [アプリケーションの許可] ... (B) あらかじめ管理者が許可を与え、ユーザ操作なしで動く
- 後に出てきますが、今回はAPIで実行するので(B)とします。
- ちなみにMicrosoft Graph のアクセス許可のリファレンス
- その中で [User.Read.All]を選択(おおざっぱにAllでいきます。)
- [アクセス許可の追加]をクリック
アクセス許可一覧に1行増えていると思います。
[User.Read.All」の場合は「管理者の同意が必要」なので同意を与えましょう。
- [規定のディレクトリに管理者の同意を与えます]をクリック
クライアントシークレットの作成
- 登録したアプリを表示し、左の[証明書とシークレット]を選択
- [新しいクライアントシークレット]をクリック
- 名前と期間を指定して生成
- 生成されたシークレットの値を確認(この値は後で使うのでどこかに控えます)
プロジェクトの準備
前置き
今回はVisual Studio 2019を使っていこうと思います。
プロジェクトの作成から、「Azure Functions」を選択します。
使用するフレームワークは .NET Core 3.1 です。
次に必要なパッケージをインストールします。
- Microsoft.Graph
- Microsoft.Graph.Auth (プレリリース)
- Microsoft.Identity.Client
もちろんコマンドでもOKです
Install-Package Microsoft.Graph
Install-Package Microsoft.Graph.Auth -IncludePrerelease
「プレリリースを含める」をチェックすると「Microsoft.Graph.Auth」も出てきます。
次に、認証プロバイダーの選択について考えます。
公式ドキュメント
今回は、Azure AD からユーザー一覧を取得するAPIを作成しようと思うので「クライアント資格情報プロバイダー」を選択します。
公式ドキュメントにも、下記の通り記されております。
「クライアント資格情報フローを使用すると、ユーザーによる操作なしでサービスアプリケーションを実行できます。」
クライアント資格情報のテンプレートが下記のようにあります。
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantID)
.WithClientSecret(clientSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
ここで、clientId、tenantId、clientSecretは何だろうと思うので話をそちらに切り替えます。
最初に作成した「アプリの登録」につながります。
- portal上で「アプリの登録」から作成したアプリを表示します。
- 「概要」に「アプリケーション(クライアント)ID」と「ディレクトリ(テナント)ID」とあります。
つまり、テンプレートではそれぞれ
clientId=「アプリケーション(クライアント)ID」
tenantId=「ディレクトリ(テナント)ID」
clientSecret=「クライアントシークレット」(クライアントシークレットの作成をした際に控えたシークレットの値)
を使えばよいということです。
実装
実装といっても数行で収まります。
最初からテンプレートで作成されている「Function1.cs」を使います。
クライアントの作成
まずは、Microsoft Graphクライアントを作成します。
下記がクライアントを作成するコードになります。
// Build a client application.
IPublicClientApplication publicClientApplication = PublicClientApplicationBuilder
.Create("INSERT-CLIENT-APP-ID")
.Build();
// Create an authentication provider by passing in a client application and graph scopes.
DeviceCodeProvider authProvider = new DeviceCodeProvider(publicClientApplication, graphScopes);
// Create a new instance of GraphServiceClient with the authentication provider.
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
ただし、今回はプロバイダーをクライアント資格情報プロバイダーで使いたいので、そこだけ書き換えます。
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantID)
.WithClientSecret(clientSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
Azure AD からユーザー一覧取得
graphClient.hogehogeでいろいろなAPIを呼び出せます。
Azure AD からユーザー一覧をとる場合は下記のコードとなります。
var users = await graphClient.Users.Request().GetAsync();
今回のソースコード全貌
これらを踏まえて書くとこうなります。
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.Identity.Client;
using Microsoft.Graph.Auth;
using Microsoft.Graph;
namespace SampleGraphAPI
{
public static class Function1
{
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
//string name = req.Query["name"];
//string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
//dynamic data = JsonConvert.DeserializeObject(requestBody);
//name = name ?? data?.name;
//string responseMessage = string.IsNullOrEmpty(name)
// ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
// : $"Hello, {name}. This HTTP triggered function executed successfully.";
//return new OkObjectResult(responseMessage);
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId) // 自分の環境に合わせる
.WithTenantId(tenantID) // 自分の環境に合わせる
.WithClientSecret(clientSecret) // 自分の環境に合わせる
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
var users = await graphClient.Users.Request().GetAsync();
return new OkObjectResult(users);
}
}
}
Postmanで動かしてみた
Postmanで動かしてみたところ、こんな感じで無事取得できました。(中身は伏せさせていただきます)
まとめ
今回は自分がAzure AD からデータを取得する際に苦戦したので、その方法についてまとめてみました。
Graph APIを使うことで、他にもユーザーの追加であったりなど様々なこともできそうだなと思いました。