LoginSignup
6
0

More than 3 years have passed since last update.

Microsoft Graphを.NETで使いAzure ADから情報を取得してみた

Last updated at Posted at 2020-12-18

この記事では、認証基盤である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でいきます。)
    • [アクセス許可の追加]をクリック

image.png

アクセス許可一覧に1行増えていると思います。
[User.Read.All」の場合は「管理者の同意が必要」なので同意を与えましょう。

  • [規定のディレクトリに管理者の同意を与えます]をクリック
    • 先のアクセス権の追加だけでなく、管理者の同意を与えて、初めてAPIのアクセス権が有効になります
    • ※ポータルにログインしているユーザのロールが「グローバル管理者」になっていないと、同意ができない image.png

クライアントシークレットの作成

  • 登録したアプリを表示し、左の[証明書とシークレット]を選択
  • [新しいクライアントシークレット]をクリック
    • 名前と期間を指定して生成
  • 生成されたシークレットの値を確認(この値は後で使うのでどこかに控えます)

image.png

プロジェクトの準備

前置き

今回はVisual Studio 2019を使っていこうと思います。
プロジェクトの作成から、「Azure Functions」を選択します。

使用するフレームワークは .NET Core 3.1 です。
image.png

次に必要なパッケージをインストールします。

  • Microsoft.Graph
  • Microsoft.Graph.Auth (プレリリース)
  • Microsoft.Identity.Client

もちろんコマンドでもOKです

Install-Package Microsoft.Graph
Install-Package Microsoft.Graph.Auth -IncludePrerelease

「プレリリースを含める」をチェックすると「Microsoft.Graph.Auth」も出てきます。
image.png

今回は下記のバージョンでやっていきます。
image.png

次に、認証プロバイダーの選択について考えます。
公式ドキュメント
今回は、Azure AD からユーザー一覧を取得するAPIを作成しようと思うので「クライアント資格情報プロバイダー」を選択します。
公式ドキュメントにも、下記の通り記されております。
「クライアント資格情報フローを使用すると、ユーザーによる操作なしでサービスアプリケーションを実行できます。」
image.png

クライアント資格情報のテンプレートが下記のようにあります。

公式ドキュメント引用.cs
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithTenantId(tenantID)
    .WithClientSecret(clientSecret)
    .Build();

ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);

ここで、clientId、tenantId、clientSecretは何だろうと思うので話をそちらに切り替えます。
最初に作成した「アプリの登録」につながります。

  • portal上で「アプリの登録」から作成したアプリを表示します。
  • 「概要」に「アプリケーション(クライアント)ID」と「ディレクトリ(テナント)ID」とあります。

image.png

つまり、テンプレートではそれぞれ
clientId=「アプリケーション(クライアント)ID」
tenantId=「ディレクトリ(テナント)ID」
clientSecret=「クライアントシークレット」(クライアントシークレットの作成をした際に控えたシークレットの値)

を使えばよいということです。

実装

実装といっても数行で収まります。
最初からテンプレートで作成されている「Function1.cs」を使います。

クライアントの作成

まずは、Microsoft Graphクライアントを作成します。
下記がクライアントを作成するコードになります。

公式ドキュメント

公式ドキュメント.cs
// 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);

ただし、今回はプロバイダーをクライアント資格情報プロバイダーで使いたいので、そこだけ書き換えます。

書き換えたやつ.cs
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();

今回のソースコード全貌

これらを踏まえて書くとこうなります。

Function1.cs
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で動かしてみたところ、こんな感じで無事取得できました。(中身は伏せさせていただきます)
image.png

まとめ

今回は自分がAzure AD からデータを取得する際に苦戦したので、その方法についてまとめてみました。
Graph APIを使うことで、他にもユーザーの追加であったりなど様々なこともできそうだなと思いました。

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0