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# を使用して関数を作成しますが、通常、使用できるプログラミング言語について制約はありません。
関数アプリで、[新しい関数] ボタンを押します。
テンプレートの一覧から、[HTTP トリガー] を選択します。
[新しい関数] パネルで、関数名を指定して、[承認レベル] を [匿名] に設定した後、[作成] ボタンをクリックします。
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
}
});
}
関数が正常に機能することを確認するには、[保存して実行] ボタンを押します。
関数が正常に実行されると、テスト ウィンドウに [ステータス: 200 OK] ラベルとリストの順序が表示されます。
Azure 関数をセキュリティで保護する
Azure 関数が機能することが確認されたので、次のステップでは、その関数を Azure Active Directory でセキュリティ保護するために、組織のアカウントでサインインして、アクセスできるようにする必要があります。
サイド パネルの関数アプリ ブレードで、目的の関数アプリを選択します。
最上部のセクションで、[プラットフォーム機能] タブに切り替えます。
次に、[ネットワーク] グループから [認証/承認] リンクを選択します。
[認証/承認] ブレードで、[App Service 認証] トグル ボタンを [オン] にして、App Service 認証を有効にします。
[要求が認証されない場合に実行するアクション] ドロップダウンで、値を [Azure Active Directory でのログイン] に変更します。 この設定により、API に対する匿名要求は許可されなくなります。
次に、認証プロバイダーの一覧から [Azure Active Directory] を選択します。
[Azure Active Directory の設定] ブレードで、[管理モード] オプションを [簡易] に切り替えます。 2 番目の [管理モード] オプションを [新しい AD アプリを作成する] に設定します。
重要
続行する前に、[アプリの作成] フィールドの値をメモします。 この値は、API をセキュリティで保護するために使用する Azure AD アプリケーションの名前を表します。後で、SharePoint Framework プロジェクトから API へのアクセス許可を要求する際に、この値が必要になります。
[OK] ボタンを押して、選択した内容を確認します。
[認証/承認] ブレードに戻り、[保存] ボタンを押して、関数アプリの認証と承認の設定を更新します。
API が適切にセキュリティ保護されていることを確認するには、新しいブラウザー ウィンドウをプライベート モードで開いて API に移動します。 関数アプリの URL は、関数アプリ ブレードの [概要] セクションにあります。 認証設定が正しく適用されている場合は、Azure AD のログイン ページにリダイレクトされます。
Azure AD アプリケーション ID を取得する
API に接続するためのアクセス トークンを要求するには、API をセキュリティで保護するために使用されている Azure AD アプリケーションのアプリケーション ID が必要です。
関数アプリで、[認証] 設定に移動します。 [構成済みの機能] ヘッダーで [認証] リンクが利用できない場合は、左側のパネルの関数アプリの横にある [最新の情報に更新] ボタンを押します。
認証プロバイダーの一覧から、[Azure Active Directory] を選択します。
[Azure Active Directory の設定] ブレードで、[アプリケーションの管理] ボタンを押します。
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] リンクを選択します。
許可されたオリジンの一覧に、SharePoint テナントの URL を追加します。例: https://contoso.sharepoint.com
[保存] ボタンを使用して変更内容を確認します。
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 を使用します。
エンタープライズ API へのアクセス許可を要求する
既定では、SharePoint Framework は、Office 365 と同じ Azure Active Directory に登録されている場合でも、エンタープライズ API にはアクセスできません。 これは意図的な設定であり、SharePoint に展開されたスクリプトやクライアント側のソリューションに公開する API を、組織が意識的に選択できるようにすることを目的としています。 エンタープライズ API にアクセスできるようにするには、作成中の SharePoint Framework プロジェクトからアクセス許可要求を発行する必要があります。
コード エディターで、config/package-solution.json ファイルを開きます。
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 ファイルを開きます。
ファイルの最上部のセクションに次のコード スニペットを追加して、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 フォルダーに移動します。
Web ブラウザーで、Office 365 テナントのテナント アプリ カタログに移動します。
新しく生成された .sppkg ファイルをエクスプローラーからテナント アプリ カタログにドラッグ アンド ドロップして追加します。
ダイアログが表示されたら、[このソリューションを組織内のすべてのサイトで使用できるようにする] チェック ボックスをオンにします。 また、[サービス プリンシパル アクセス許可管理ページ] に移動して、保留中のアクセス許可を承認する必要があることにも注意してください。 [展開] ボタンを押して、展開を確認します。
エンタープライズ API へのアクセスを許可する
Web ブラウザーで、Office 365 アプリ起動ツールの [管理] オプションを選択して、テナント管理サイトに移動します。
メニューの [管理センター] グループから、[SharePoint] を選択します。
SharePoint 管理センターで、[新しい SharePoint 管理センター プレビューをお試しください] リンクを使用して、新しい SharePoint 管理センターのプレビューに移動します。
新しい管理センターで、メニューから [API の管理] オプションを選択します。
[API の管理] ページの [承認待ち] グループで、contoso-api API にアクセスするために新しく追加されたアクセス許可要求を選択します (API 名が表示されます)。
次に、ツールバーから [承認または拒否する] ボタンを押します。
サイド パネルで [承認] ボタンを押して、API へのアクセスを許可します。
注:
AAD でセキュリティ保護された API に接続するドメインの独立した Web パーツを作成できます。 この場合、ドメインの独立した Web パーツの各インスタンスは、一意のドメインを持つ専用のアプリ Web 内で実行されるため、API の CORS を適切に再構成する必要があります。
Orders Web パーツをページに追加する
すべてが正常に動作していることを確認するには、前の手順で作成した Orders Web パーツをページに追加します。
Web ブラウザーで、テナント内のサイトに移動します。 ツールバーから [編集] オプションを選択します。
キャンバスで、Web パーツを追加するセクションを選択します。
+ オプションを選択してツールボックスを開きます。 Orders Web パーツをすばやく見つけるために、検索ボックスに Orders と入力します。
Orders Web パーツを選択してページに追加します。 エンタープライズ API から取得された注文の一覧が表示されます。
エラーが発生し、「ポップアップ ウィンドウを開けませんでした」という技術的な説明が表示された場合は、ポップアップ ブロッカーが有効になっています。 ページを正しく表示するには、サイトのブラウザのポップアップ ブロッカーを無効にする必要があります。