SharePoint Framework での、Azure AD でセキュリティ保護されたエンタープライズ API の使用

この記事では、SharePoint Framework ソリューションから、Azure Active Directory でセキュリティ保護されたエンタープライズ API に接続する方法を説明します。 API を作成してセキュリティで保護する方法と、SharePoint Framework ソリューションを構築する方法の両方について取り上げます。

Azure AD でセキュリティ保護されたエンタープライズ API を作成する

まず、Azure Active Directory でセキュリティ保護されたエンタープライズ API の作成から説明します。 SharePoint Framework では、API の実装方法に制約はありませんが、このチュートリアルでは、Azure 関数 を使用して API を作成し、Azure App Service 認証を使用して API をセキュリティ保護します。

組織のアプリケーションを公開する特定の API は、おそらく既に存在するはずですが、このセクションでは、実装および構成手順全体の概要を説明します。

Azure 関数を作成する

Azure portal で、新しい関数アプリを作成します。

Azure で関数アプリを作成する方法の詳細については、サポート記事「Azure Portal から関数アプリを作成する」を参照してください。

関数アプリで、HTTP でトリガーされる新しい関数を作成します。 この例では C# を使用して関数を作成しますが、通常、使用できるプログラミング言語について制約はありません。

関数アプリで、[新しい関数] ボタンを押します。

Azure portal で強調表示された [新規作成] ボタン

テンプレートの一覧から、[HTTP トリガー] を選択します。

Azure portal で強調表示された [HTTP トリガー] 関数のテンプレート

[新しい関数] パネルで、関数名を指定して、[承認レベル][匿名] に設定した後、[作成] ボタンをクリックします。

Azure portal での新しい Azure 関数の設定

Azure 関数をセキュリティで保護する方法は、いくつかあります。 Azure AD を使用して関数をセキュリティで保護する必要があるため、関数自体ではなく、基になる関数アプリをセキュリティで保護します。 そのため、この段階では関数自体のセキュリティ保護は行わないように設定します。 関数アプリに適用される認証設定は、このアプリに含まれるすべての関数に適用されます。

関数を作成したら、その内容を次のスニペットに置き換えます。

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    return (ActionResult)new OkObjectResult(new List<object> {
        new {
            Id = 1,
            OrderDate = new DateTime(2016, 1, 6),
            Region = "east",
            Rep = "Jones",
            Item = "Pencil",
            Units = 95,
            UnitCost = 1.99,
            Total = 189.05
        },
        new {
            Id = 2,
            OrderDate = new DateTime(2016, 1, 23),
            Region = "central",
            Rep = "Kivell",
            Item = "Binder",
            Units = 50,
            UnitCost = 19.99,
            Total = 999.50
        },
        new {
            Id = 3,
            OrderDate = new DateTime(2016, 2, 9),
            Region = "central",
            Rep = "Jardine",
            Item = "Pencil",
            Units = 36,
            UnitCost = 4.99,
            Total = 179.64
        },
        new {
            Id = 4,
            OrderDate = new DateTime(2016, 2, 26),
            Region = "central",
            Rep = "Gill",
            Item = "Pen",
            Units = 27,
            UnitCost = 19.99,
            Total = 539.73
        },
        new {
            Id = 5,
            OrderDate = new DateTime(2016, 3, 15),
            Region = "west",
            Rep = "Sorvino",
            Item = "Pencil",
            Units = 56,
            UnitCost = 2.99,
            Total = 167.44
        }
    });
}

関数が正常に機能することを確認するには、[保存して実行] ボタンを押します。

Azure portal で強調表示された [保存して実行] ボタン

関数が正常に実行されると、テスト ウィンドウに [ステータス: 200 OK] ラベルとリストの順序が表示されます。

Azure 関数をセキュリティで保護する

Azure 関数が機能することが確認されたので、次のステップでは、その関数を Azure Active Directory でセキュリティ保護するために、組織のアカウントでサインインして、アクセスできるようにする必要があります。

サイド パネルの関数アプリ ブレードで、目的の関数アプリを選択します。

Azure portal のサイド パネルにある関数アプリ ブレードで強調表示された関数アプリ

最上部のセクションで、[プラットフォーム機能] タブに切り替えます。

Azure portal の関数アプリ ブレードで強調表示された [プラットフォーム機能] タブ

次に、[ネットワーク] グループから [認証/承認] リンクを選択します。

Azure portal の関数アプリ ブレードで強調表示された [認証/承認] リンク

[認証/承認] ブレードで、[App Service 認証] トグル ボタンを [オン] にして、App Service 認証を有効にします。

Azure portal の関数アプリの認証の設定で強調表示された、[App Service 認証] トグル ボタンの [オン] オプション

[要求が認証されない場合に実行するアクション] ドロップダウンで、値を [Azure Active Directory でのログイン] に変更します。 この設定により、API に対する匿名要求は許可されなくなります。

Function App 認証設定のブレードで強調表示された、[要求が認証されない場合に実行するアクション] ドロップダウンの [Azure Active Directory でのログイン] オプション

次に、認証プロバイダーの一覧から [Azure Active Directory] を選択します。

関数アプリの認証プロバイダーの一覧で強調表示された [Azure Active Directory]

[Azure Active Directory の設定] ブレードで、[管理モード] オプションを [簡易] に切り替えます。 2 番目の [管理モード] オプションを [新しい AD アプリを作成する] に設定します。

Azure portal の関数アプリで開いた [Azure Active Directory の設定] ブレード

重要

続行する前に、[アプリの作成] フィールドの値をメモします。 この値は、API をセキュリティで保護するために使用する Azure AD アプリケーションの名前を表します。後で、SharePoint Framework プロジェクトから API へのアクセス許可を要求する際に、この値が必要になります。

[OK] ボタンを押して、選択した内容を確認します。

[認証/承認] ブレードに戻り、[保存] ボタンを押して、関数アプリの認証と承認の設定を更新します。

Azure portal の関数アプリの [認証/承認] ブレードで強調表示された [保存] ボタン

API が適切にセキュリティ保護されていることを確認するには、新しいブラウザー ウィンドウをプライベート モードで開いて API に移動します。 関数アプリの URL は、関数アプリ ブレードの [概要] セクションにあります。 認証設定が正しく適用されている場合は、Azure AD のログイン ページにリダイレクトされます。

Azure AD のログイン ページ

Azure AD アプリケーション ID を取得する

API に接続するためのアクセス トークンを要求するには、API をセキュリティで保護するために使用されている Azure AD アプリケーションのアプリケーション ID が必要です。

関数アプリで、[認証] 設定に移動します。 [構成済みの機能] ヘッダーで [認証] リンクが利用できない場合は、左側のパネルの関数アプリの横にある [最新の情報に更新] ボタンを押します。

関数アプリ ページで強調表示された [認証] リンク

認証プロバイダーの一覧から、[Azure Active Directory] を選択します。

関数アプリの認証プロバイダーの一覧で強調表示された [Azure Active Directory]

[Azure Active Directory の設定] ブレードで、[アプリケーションの管理] ボタンを押します。

[Azure Active Directory の設定] ブレードで強調表示された [アプリケーションの管理] ボタン

Azure AD アプリケーションのブレードで、[アプリケーション ID] プロパティの値をコピーします。

Azure AD アプリケーションのブレードで強調表示された、[アプリケーション ID] プロパティの横にある [コピー] ボタン

CORS を有効にする

Function App は、SharePoint ページで実行されている JavaScript から呼び出されます。 この API は SharePoint Portal とは異なるドメインでホストされているため、API 呼び出しには、クロスドメイン セキュリティの制約事項が適用されます。 既定では、Azure 関数アプリを使用して実装された API を他のドメインから呼び出すことはできません。 他のドメインから呼び出せるようにするには、関数アプリの CORS 設定を調整します。

重要

OAuth ではなく SharePoint Online Cookie を使用して API で認証する場合は、Azure portal から CORS 設定を構成することはできません。 認証が機能するには、Azure portal のすべての CORS 設定をクリアして、代わりに API で指定する必要があります。

関数アプリで、[プラットフォーム機能] タブに切り替えます。

[API] グループから、[CORS] リンクを選択します。

関数アプリの [プラットフォーム機能] タブで強調表示された [CORS] リンク

許可されたオリジンの一覧に、SharePoint テナントの URL を追加します。例: https://contoso.sharepoint.com

関数アプリの CORS 設定で許可されたオリジンの一覧に追加された SharePoint テナントの URL

[保存] ボタンを使用して変更内容を確認します。

SharePoint Framework から、Azure AD でセキュリティ保護されたエンタープライズ API を使用する

API を構成して機能するようになったら、次のステップは、この API を使用する SharePoint Framework ソリューションの構築です。

続行する前に、バージョン 1.4.1 以上の SharePoint Framework Yeoman ジェネレーターがインストールされていることを確認してください。 このジェネレーターをグローバルにインストールしている場合は、コマンド ラインで npm ls -g --depth=0 を実行することによって、インストールされているバージョンを確認できます。

新しい SharePoint Framework プロジェクトを作成する

次に、API を使用するための新しい SharePoint Framework プロジェクトを作成します。

コマンド ラインで次のコマンドを実行して、プロジェクトの新しいフォルダーを作成します。

md contoso-api

作業ディレクトリを変更します。

cd contoso-api

新しいプロジェクトを作成するには、SharePoint Framework Yeoman ジェネレーターを起動します。

yo @microsoft/sharepoint

ダイアログ ボックスが表示されたら、次の値を使用します。

  • ソリューション名は何ですか? contoso-api
  • どのベースライン パッケージをコンポーネントのターゲットにしたいですか? SharePoint Online のみ (最新)
  • ファイルをどこに保存しますか? 現在のフォルダーを使用する
  • テナント管理者が、サイトで機能を展開したり、アプリを追加したりせず、すぐにすべてのサイトでソリューションを展開できるようにしたいですか? はい
  • ソリューションのコンポーネントには、テナント内の他のコンポーネントと共有されていない一意の Web API にアクセスするためのアクセス許可が必要ですか? いいえ
  • どの種類のクライアント側コンポーネントを作成しますか? WebPart
  • Web パーツ名は何ですか? 注文
  • Web パーツで何を行いますか? 最近の注文の表示
  • どのフレームワークを使用しますか? JavaScript なしのフレームワーク

プロジェクトを作成したら、コード エディターでプロジェクトを開きます。 このチュートリアルでは、Visual Studio Code を使用します。

Visual Studio Code で開かれた SharePoint Framework プロジェクト

エンタープライズ API へのアクセス許可を要求する

既定では、SharePoint Framework は、Office 365 と同じ Azure Active Directory に登録されている場合でも、エンタープライズ API にはアクセスできません。 これは意図的な設定であり、SharePoint に展開されたスクリプトやクライアント側のソリューションに公開する API を、組織が意識的に選択できるようにすることを目的としています。 エンタープライズ API にアクセスできるようにするには、作成中の SharePoint Framework プロジェクトからアクセス許可要求を発行する必要があります。

コード エディターで、config/package-solution.json ファイルを開きます。

Visual Studio Code で開かれたパッケージ ソリューション ファイル

solution プロパティに、webApiPermissionRequests という名前の新しいプロパティを追加し、API をセキュリティ保護するために使用している Azure AD アプリケーションへの参照を設定します。

{
  "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
  "solution": {
    "name": "contoso-api-client-side-solution",
    "id": "8cbc01fb-bab6-48fc-afec-2c2053759771",
    "version": "1.0.0.0",
    "includeClientSideAssets": true,
    "skipFeatureDeployment": true,
    "isDomainIsolated": false,
    "webApiPermissionRequests": [
      {
        "resource": "contoso-api-dp20191109",
        "scope": "user_impersonation"
      }
    ]
  },
  "paths": {
    "zippedPackage": "solution/contoso-api.sppkg"
  }
}

resource プロパティの値は、API をセキュリティ保護するために使用している Azure AD アプリケーションの名前を表します。 scope プロパティの値は、ソリューションが API と通信するために必要なアクセス許可の適用範囲を指定します。 このチュートリアルでは、API を保護する目的でのみ Azure AD を使用するため、適用範囲として user_impersonation を使用します。

注:

作成済みのエンタープライズ API に接続する必要がある場合は、管理者に連絡して、その API をセキュリティ保護するために使用している Azure AD アプリケーションの詳細を入手してください。 必要となる情報は、アプリケーション ID、アプリケーションが公開しているアクセス許可、アプリケーション構成の対象となっているユーザーなどです。

エンタープライズ API に接続する

最後に残された作業は、エンタープライズ API への実際の接続を実装することです。

コード エディターで、src\webparts\orders\OrdersWebPart.ts ファイルを開きます。

Visual Studio Code で開かれた OrdersWebPart.ts ファイル

ファイルの最上部のセクションに次のコード スニペットを追加して、AadHttpClient クラスと HttpClientResponse クラスを参照します。

import { AadHttpClient, HttpClientResponse } from '@microsoft/sp-http';

OrdersWebPart クラスに、ordersClient という名前の新しいクラス変数を追加します。

export default class OrdersWebPart extends BaseClientSideWebPart<IOrdersWebPartProps> {
  private ordersClient: AadHttpClient;

  // shortened for brevity
}

次に、AadHttpClient のインスタンスを作成するために、OrdersWebPart クラスに含まれる onInit() メソッドを次のように上書きします。

export default class OrdersWebPart extends BaseClientSideWebPart<IOrdersWebPartProps> {
  private ordersClient: AadHttpClient;

  protected onInit(): Promise<void> {
    return new Promise<void>((resolve: () => void, reject: (error: any) => void): void => {
      this.context.aadHttpClientFactory
        .getClient('6bc8bca8-5866-405d-b236-9200bdbb73c0')
        .then((client: AadHttpClient): void => {
          this.ordersClient = client;
          resolve();
        }, err => reject(err));
    });
  }

  // shortened for brevity
}

AadHttpClient コンストラクターの 2 番目のパラメーターとして渡される GUID は、エンタープライズ API をセキュリティ保護するために使用している Azure AD アプリケーションのアプリケーションの ID です。

最後に、エンタープライズ API から取得した注文を読み込んで表示するように render() メソッドを拡張します。

export default class OrdersWebPart extends BaseClientSideWebPart<IOrdersWebPartProps> {
  private ordersClient: AadHttpClient;

  protected onInit(): Promise<void> {
    return new Promise<void>((resolve: () => void, reject: (error: any) => void): void => {
      this.context.aadHttpClientFactory
        .getClient('6bc8bca8-5866-405d-b236-9200bdbb73c0')
        .then((client: AadHttpClient): void => {
          this.ordersClient = client;
          resolve();
        }, err => reject(err));
    });
  }

  public render(): void {
    this.context.statusRenderer.displayLoadingIndicator(this.domElement, 'orders');

    this.ordersClient
      .get('https://contoso-api-dp20191109.azurewebsites.net/api/Orders', AadHttpClient.configurations.v1)
      .then((res: HttpClientResponse): Promise<any> => {
        return res.json();
      })
      .then((orders: any): void => {
        this.context.statusRenderer.clearLoadingIndicator(this.domElement);
        this.domElement.innerHTML = `
          <div class="${ styles.orders}">
            <div class="${ styles.container}">
              <div class="${ styles.row}">
                <div class="${ styles.column}">
                  <span class="${ styles.title}">Orders</span>
                  <p class="${ styles.description}">
                    <ul>
                      ${orders.map(o => `<li>${o.rep} $${o.total}</li>`).join('')}
                    </ul>
                  </p>
                  <a href="https://aka.ms/spfx" class="${ styles.button}">
                    <span class="${ styles.label}">Learn more</span>
                  </a>
                </div>
              </div>
            </div>
          </div>`;
      }, (err: any): void => {
        this.context.statusRenderer.renderError(this.domElement, err);
      });
  }

  // shortened for brevity
}

ソリューションを SharePoint アプリ カタログに展開する

SharePoint Framework ソリューションの実装が完了したら、次のステップは、このソリューションを SharePoint に展開することです。

まず、コマンド ラインを使用して、プロジェクトを構築してパッケージ化します。

gulp bundle --ship && gulp package-solution --ship

次に、エクスプローラーでプロジェクト フォルダーを開き、sharepoint/solution フォルダーに移動します。

macOS Finder で開かれた 'sharepoint/solution' プロジェクト フォルダー

Web ブラウザーで、Office 365 テナントのテナント アプリ カタログに移動します。

Web ブラウザーに表示されたテナント アプリ カタログ

新しく生成された .sppkg ファイルをエクスプローラーからテナント アプリ カタログにドラッグ アンド ドロップして追加します。

Web ブラウザーの最上部に表示された、テナント アプリ カタログを表示する macOS Finder ウィンドウ

ダイアログが表示されたら、[このソリューションを組織内のすべてのサイトで使用できるようにする] チェック ボックスをオンにします。 また、[サービス プリンシパル アクセス許可管理ページ] に移動して、保留中のアクセス許可を承認する必要があることにも注意してください。 [展開] ボタンを押して、展開を確認します。

エンタープライズ API へのアクセスを許可する

Web ブラウザーで、Office 365 アプリ起動ツールの [管理] オプションを選択して、テナント管理サイトに移動します。

Office 365 アプリ起動ツールのメニューで強調表示された [管理] オプション

メニューの [管理センター] グループから、[SharePoint] を選択します。

Office 365 管理センターのメニューで強調表示された [SharePoint] オプション

SharePoint 管理センターで、[新しい SharePoint 管理センター プレビューをお試しください] リンクを使用して、新しい SharePoint 管理センターのプレビューに移動します。

SharePoint 管理センターで強調表示された [新しい SharePoint 管理センター プレビューをお試しください] リンク

新しい管理センターで、メニューから [API の管理] オプションを選択します。

新しい SharePoint Online 管理センターのメニューで強調表示された [API の管理] オプション

[API の管理] ページの [承認待ち] グループで、contoso-api API にアクセスするために新しく追加されたアクセス許可要求を選択します (API 名が表示されます)。

新しい SharePoint Online 管理センターの [API の管理] ページで強調表示された、アクセス許可要求の横の選択ボタン

次に、ツールバーから [承認または拒否する] ボタンを押します。

新しい SharePoint Online 管理センターの [API の管理] ページのツールバーで強調表示された [承認または拒否する] オプション

サイド パネルで [承認] ボタンを押して、API へのアクセスを許可します。

新しい SharePoint Online 管理センターで API 要求を管理するためのサイド パネルで強調表示された [承認] ボタン

注:

AAD でセキュリティ保護された API に接続するドメインの独立した Web パーツを作成できます。 この場合、ドメインの独立した Web パーツの各インスタンスは、一意のドメインを持つ専用のアプリ Web 内で実行されるため、API の CORS を適切に再構成する必要があります。

Orders Web パーツをページに追加する

すべてが正常に動作していることを確認するには、前の手順で作成した Orders Web パーツをページに追加します。

Web ブラウザーで、テナント内のサイトに移動します。 ツールバーから [編集] オプションを選択します。

モダン チーム サイトのツールバーで強調表示された [編集] ボタン

キャンバスで、Web パーツを追加するセクションを選択します。

Web ブラウザーで強調表示されたページのセクション

+ オプションを選択してツールボックスを開きます。 Orders Web パーツをすばやく見つけるために、検索ボックスに Orders と入力します。

ツールボックスに 「Orders」と入力します。ツールボックスに表示される注文 Web パーツ

Orders Web パーツを選択してページに追加します。 エンタープライズ API から取得された注文の一覧が表示されます。

SharePoint ページに表示された、エンタープライズ API から取得された最近の注文の一覧

エラーが発生し、「ポップアップ ウィンドウを開けませんでした」という技術的な説明が表示された場合は、ポップアップ ブロッカーが有効になっています。 ページを正しく表示するには、サイトのブラウザのポップアップ ブロッカーを無効にする必要があります。