Microsoft Entra 認証でログインする Web アプリケーションで、ユーザーの権限に応じて AI Search を検索させたい
質問
Microsoft Entra 認証でログインする Web アプリケーションがあり、AI Search のインデックスを検索させたいです。
ただし、ユーザーが AI Search のインデックスを検索する権限がない場合は、検索できないようにしたいです。
回答
端的に申し上げますと、Web アプリケーションが利用する Microsoft Entra ID アプリケーションの設定で、AI Search サービスの API に対する「委任されたアクセス許可」を追加いただき、
認証スコープを https://search.azure.com/user_impersonation
としてトークンを取得すると、ユーザーの権限に応じて AI Search のインデックスを検索させることができます。
AI Search 側で必要な前提条件
アプリケーションの設定前に、AI Search 側で必要な対応を記載いたします。
- ロールの割り当て のドキュメントを参考に、インデックスもしくは AI Search スコープで、ユーザーに対して権限を付与します。
- AI Search のインデックスを検索するための組み込みロールとして「検索インデックス データ閲覧者」がございます。アプリケーション経由で AI Search を検索する場合はこちらのロールが便利と存じます。
- データ プレーンにロールベースのアクセスを構成する のドキュメントを参考に、AI Search でロールベースのアクセス制御を有効にします。
Web アプリケーション および Microsoft Entra ID アプリケーションの設定
手順 1. Microsoft Entra ID 認証でログインする Web アプリケーションを用意します。
サンプルとして、Microsoft ID プラットフォームのコード サンプル にある React アプリケーション「Azure REST API と Azure Storage を呼び出す」を使用します。
手順 2. Microsoft Entra ID アプリケーションを設定します。
手順 1. のサンプルをご利用の場合は、Step 3: Register the sample application(s) in your tenant の手順に従います。
以下の 1 ~ 6 の手順は、Step 3: Register the sample application(s) in your tenant に基づく内容となりますが、Microsoft Entra ID アプリケーションの設定方法を参考までに記載いたします。
既に Microsoft Entra ID アプリケーションを構成いただいている場合は、以下の 4. 5. の「Azure Cognitive Search」の API へのアクセス許可設定のみ実施いただければと存じます。
1. Azure Portal で Microsoft Entra ID を開き、「アプリの登録」から「新規登録」をクリックします。
2. アプリケーションの表示名を入力し、「この組織ディレクトリのみに含まれるアカウント」を選択し、アプリケーションを作成します。
3. 「認証」ブレードより、「プラットフォームを追加」をクリックします。サンプルはシングルページアプリケーションなので、「シングルページアプリケーション」を選択し、リダイレクト URI に以下を設定し保存します。
http://localhost:3000/redirect
http://localhost:3000/
4. 「API のアクセス許可」ブレードを開き、「アクセス許可の追加」から「Azure Cognitive Search」という名前の API を探します。
5. 「Azure Cognitive Search」をクリックし、「委任されたアクセス許可」を選択し、「user_impersonation」にチェックを入れアクセス許可を追加します。
API のアクセス許可が以下のようになっていれば問題ありません。
6. 「トークン構成」のブレードより、「オプションの要求の追加」をクリックし、トークンの種類 「ID」で「acct」にチェックを入れて保存します。
手順 3. Web アプリケーションの構成
恐れ入りますが、以下の内容はあくまでサンプルアプリケーションをベースにしたものになりますので、お客様のアプリケーションに応じて適宜検証の上開発いただけますと幸いです。
1. 手順 2 で作成した Microsoft Entra ID アプリケーションの概要ページより、アプリケーション ID とディレクトリ ID を取得します。
2. Web アプリケーションの設定ファイルにて、アプリケーション ID とディレクトリ ID を設定します。サンプルでは SPA/src/authConfig.js#L16 内の以下の部分に設定します。
export const msalConfig = {
auth: {
clientId: 'Enter_the_Application_Id_Here', // This is the ONLY mandatory field that you need to supply.
authority: 'https://login.microsoftonline.com/Enter_the_Tenant_Info_Here', // Defaults to "https://login.microsoftonline.com/common"
3. AI Search 用のトークンを取得するため、SPA/src/authConfig.js#L71 に以下のようにスコープの定義を追加します。
armBlobStorage: {
scopes: ['https://storage.azure.com/user_impersonation'],
},
armSearch: {
scopes: ['https://search.azure.com/user_impersonation'],
}
4. SPA/src/authConfig.js に接続先の AI Search サービス名と、インデックス名を指定します。
export const searchInformation = {
serviceName: 'search-service-name',
indexName: 'hotels-sample-index'
};
5. サンプルの SPA/src/pages/BlobStorage.jsx と同様に、Search.jsx
を用意し、request
定数の scopes
に 3. で作成した armSearch
の scopes
を指定します。
export const Search = () => {
// 中略
const request = {
scopes: protectedResources.armSearch.scopes,
account: account,
};
const { login, result, error } = useMsalAuthentication(InteractionType.Popup, {
...request,
redirectUri: '/redirect',
});
6. SPA/src/azureManagement.js にある、Blob Storage クライアントの初期化処理と同様に、以下のように AI Search の検索用クライアントを初期化する処理を記載します。ここで 4. で設定した値を使用します。
export const getSearchClient = async (accessToken) => {
const credential = new StaticTokenCredential({
token: accessToken,
expiresOnTimestamp: accessToken.exp,
});
const client = new SearchClient(`https://${searchInformation.serviceName}.search.windows.net`, searchInformation.indexName, credential);
return client;
};
7. 検索結果を取得するコードを記載します。
export const Search = () => {
const { instance } = useMsal();
const [searchWord, setsearchWord] = useState(null);
// 中略
const handleSubmit = async (e) => {
e.preventDefault();
try {
const client = await getSearchClient(result.accessToken);
const searchResults = await client.search(searchWord);
let r = "";
for await (const result of searchResults.results) {
r += result.document.HotelName;
}
setMessage(r);
setShowMessage(true);
// 中略
return (
<Container>
<Row>
<Form onSubmit={handleSubmit}>
<input id="searchWord" name="searchWord" placeholder="search word" type="text" onChange={handleChangesearchWord} />
<Button type="submit">Submit</Button>
</Form>
</Row>
例えば以下のようにフォームに記載した内容に基づいて検索し、検索結果を取得することができます。
参考ドキュメント
2024 年 04 月 09 日時点の内容となります。
本記事の内容は予告なく変更される場合がございますので予めご了承ください。