[アーティクル] 09/18/2024
4 人の共同作成者
フィードバック
この記事の内容
Copilot Studio は、シングル サインオン (SSO) をサポートしています。 SSO を使用すると、Web サイト上のコパイロットは、コパイロットが展開されているページまたはアプリに既にサインインしている場合に、顧客をサインインすることができます。
たとえば、コパイロットは社内のイントラネットまたはユーザーが既にサインインしているアプリでホストされます。
Copilot Studio の SSO を構成する、4 つの主な手順があります:
Microsoft Entra ID でカスタム キャンバスにアプリ登録を作成します。
コパイロットのカスタム スコープを定義します。
SSO を有効にするように Copilot Studio で認証を構成します。
SSO を有効にするように、カスタム キャンバス HTML コードを構成します。
前提条件
サポート対象のチャネル
次の表は、現在 SSO をサポートしているチャネル の詳細です。 追加のチャネルのサポートは Microsoft Copilot Studio アイデア フォーラム で提案できます。
1 Teamsチャネルも有効になっている場合は、 副操縦士のIDを使用してシングル サインオンを構成する Microsoft Entra ドキュメント Microsoft Teams の構成手順を 追従する する必要があります。 そのページの指示に従って Teams SSO 設定を構成しないと、ユーザーは Teams チャネルを使用するときに常に認証に失敗します。
2 ライブチャットチャネルのみがサポートされています。 詳細については、Dynamics 365 Customer Service へのハンドオフを構成する を参照してください。
重要
現在、コパイロットが次のいずれかの場合、SSO はサポートされていません:
ただし、SPFxコンポーネント として SharePoint Webサイトに公開されたコパイロットでは、SSO がサポートされます。
カスタム Web サイト用のアプリ登録を作成する
SSO を有効にするには、2 つの個別のアプリ登録を作成する必要です。
認証アプリ登録 で、コパイロットの Microsoft Entra ID ユーザー認証を有効にします
カスタム Web ページの SSO を有効にするキャンバス アプリの登録
セキュリティ上の理由から、コパイロットとカスタム Web サイトの両方に同じアプリ登録を再利用することはお勧めしません。
Microsoft Entra ID を使用してユーザー認証を構成する の手順に従って、認証アプリ登録を作成します。
追従する 認証アプリ登録を再度作成する手順を実行して、キャンバス アプリ登録として機能する2番目のアプリ登録を作成します。
認証アプリ登録にキャンバス アプリの登録 ID を追加します。
トークンの交換 URL の追加
Copilot Studio の Microsoft Entra ID認証設定を更新するには、トークン エクスチェンジ URL を追加して、アプリと Copilot Studio が情報を共有できるようにする必要があります。
Azure ポータルの認証アプリ登録ブレードで、API を公開する にアクセスします。
スコープ の下で、 クリップボードにコピー アイコンを選択します。
Copilot Studio の ナビゲーション メニューの 設定 で、セキュリティ を選択して 認証 タイルを選択します。
トークンの交換 URL (SSO に必要) に、先ほどコピーしたスコープを貼り付けます。
保存 を選びます。
キャンバス アプリの登録を作成した後は、認証 にアクセスし、プラットフォームの追加 を選択します。
プラットフォームの構成 の下で、プラットフォームの追加 、次に Web を選択します。
リダイレクト URI の下で、http://contoso.com/index.html
などの Web ページの URL を入力します。
暗黙的な許可とハイブリッド フロー セクションで、アクセス トークン (暗黙的なフローに使用) と ID トークン (暗黙的およびハイブリッド フローに使用) の両方をオンにします。
構成 を選択します。
コパイロットのトークン エンドポイント URL を確認する
Copilot Studio で、コパイロットを開いた状態で、チャネル を選択します。
モバイル アプリ を選択します。
トークン エンドポイント の下で、コピー を選択します。
Web ページで SSO を構成する
Copilot Studio GitHub リポジトリ で提供されるコードを使用して、リダイレクト URL の Web ページを作成します。 GitHubリポジトリからコードをコピーし、次の手順に従って変更します。
注意
GitHub リポジトリのコードでは、ユーザーがログイン ボタンを選択 するか、別のサイトからログインする必要があります。 自動ログインを有効にするには、 aysnc function main()
の先頭に次のコードを追加します。
(async function main() {
if (clientApplication.getAccount() == null) {
await clientApplication.loginPopup(requestObj).then(onSignin).catch(function (error) {console.log(error) });
}
// Add your BOT ID below
var theURL =
Azure ポータルの概要 ページに移動し、キャンバス アプリ登録からアプリケーション (クライアント) ID とディレクトリ (テナント) ID をコピーします。
Microsoft Authentication Library (MSAL) を構成する方法:
clientId
を アプリケーション (クライアント) ID に割り当てます。
authority
を https://login.microsoftonline.com/
に割り当て、最後に ディレクトリ (テナント) ID を追加します。
例:
var clientApplication;
(function (){
var msalConfig = {
auth: {
clientId: '692e92c7-xxxx-4060-76d3-b381798f4d9c',
authority: 'https://login.microsoftonline.com/7ef988bf-xxxx-51af-01ab-2d7fd011db47'
},
theURL
変数を、すでにコピーしたトークン エンドポイント URL に設定します。 例:
(async function main() {
var theURL = "https://1c0.0.environment.api.powerplatform.com/powervirtualagents/bots/5a099fd/directline/token?api-version=2022-03-01-preview"
userId
の値を編集して、カスタム接頭辞を含めます。 例:
var userId = clientApplication.account?.accountIdentifier != null ?
("My-custom-prefix" + clientApplication.account.accountIdentifier).substr(0, 64)
: (Math.random().toString() + Date.now().toString()).substr(0,64);
変更を保存。
Web ページを使用してコパイロットをテストする
ブラウザで Web ページを開きます。
ログイン を選択します。
Note
ブラウザーがポップアップをブロックしている場合、またはシークレットまたはプライベートブラウザー ウィンドウを使用している場合は、ログインするよう求められます。 それ以外の場合、ログインは検証コードを使用して完了します。
新しいブラウザー タブが開きます。
新しいタブに切り替えて、検証コードをコピーします。
コパイロットのあるタブに戻り、コパイロットの会話に検証コードを貼り付けます。
関連するコンテンツ
技術的な概要
次の図は、ユーザーが Copilot Studio でログイン プロンプト (SSO) を表示せずにサインインする方法を示します:
コパイロット ユーザーは、サインイン トピックをトリガーする フレーズを入力します。 サインイン トピック は、ユーザーをサインインさせ、ユーザーの 認証済みトークン (User.AccessToken
変数) を使用するように設計されています。
Copilot Studio はログイン プロンプトを送信して、ユーザーが構成された ID プロバイダーでサインインできるようにします。
コパイロットの カスタム キャンバス はサインイン プロンプトを受信し、代理 (OBO) トークンを Microsoft Entra ID から要求します。 キャンバスはトークンをコパイロットに送信します。
OBO トークンの受信時に、コパイロットは OBO トークンを「アクセス トークン」に交換し、アクセス トークンの値を使用して AuthToken
変数を入力します。 IsLoggedIn
変数はこの時点でも設定されます。
Microsoft Entra ID でカスタム キャンバスにアプリ登録を作成する
SSO を有効にするには、2 つの個別のアプリ登録が必要です:
重要
コパイロットのユーザー認証とカスタム キャンバスの両方に同じアプリ登録を使いまわすことはできません。
コパイロットのキャンバス用アプリ登録を作成する
Azure portal にサインインします。
アプリ登録 に移動して、アイコンを選択するか、上部の検索バーで検索します。
新規登録 を選択します。
登録の名前を入力してください。 登録しているキャンバスのコパイロットの名前を使用し、"キャンバス" を含めて認証用のアプリ登録と区別するのに役立ちます。
たとえば、コパイロットが "Contoso sales help" という名前の場合、アプリ登録に "ContosoSalesCanvas" などの名前を付ける場合があります。
サポートされているアカウントの種類 の下で、選択 任意の組織テナント内のアカウント (任意の Microsoft Entra IDディレクトリ - マルチテナント) および個人のMicrosoftアカウント (Skypeなど、 Xbox) 。
次のステップでその情報を入力するので、今回は リダイレクト URI セクションを空白のままにします。 登録 を選択します。
登録が完了した後、概要 ページが開きます。 マニフェスト にアクセスします。 accessTokenAcceptedVersion
が 2
に設定されていることを確認します。 そうでない場合は、2
に変更し、保存 を選択します。
リダイレクト URL の追加
登録を開いた状態で、認証 にアクセスし、プラットフォームの追加 を選択します。
[プラットフォームの構成] ブレードで、選択 Web を選択します。
リダイレクト URI で、チャット キャンバスがホストされているページに完全な URL を追加します。 暗示的な許可 セクションで、ID トークン およびアクセス トークン チェックボックスを選択します。
構成 を選択して変更を確認します。
API アクセス許可 に移動します。 <テナント名>に管理者の承認を付与する を選択してから、はい を選択します。
重要
ユーザーが各アプリケーションに同意するのを防ぐには、グローバル管理者、アプリケーション管理者、またはクラウド アプリケーション管理者がアプリの登録にテナント全体の同意を付与する 必要があります。
コパイロットのカスタム スコープを定義する
認証アプリ登録内でキャンバス アプリ登録用の API を公開することにより、カスタム スコープを定義します。 スコープ を使用すると、ユーザーと管理者の役割とアクセス権を決定できます。
この手順では、認証用の認証アプリ登録とカスタム キャンバス用のアプリ登録の間に信頼関係が作成されます。
認証を構成したとき に作成したアプリ登録を開きます。
API アクセス許可 に移動し、コパイロットに適切なアクセス許可が追加されていることを確認してください。 <テナント名>に管理者の承認を付与する を選択してから、はい を選択します。
重要
ユーザーが各アプリケーションに同意するのを防ぐには、グローバル管理者、アプリケーション管理者、またはクラウド アプリケーション管理者がアプリの登録にテナント全体の同意を付与する 必要があります。
API を公開する に移動してからスコープの追加 を選択します。
スコープの名前と、ユーザーが SSO 画面にアクセスしたときに表示される表示情報を入力します。 スコープの追加 を選択します。
クライアント アプリケーションの追加 を選択します。
アプリケーション (クライアント) ID を、キャンバス アプリ登録の概要 ページからクライアント ID フィールドに入力します。 作成した一覧表示スコープのチェックボックスを選択します。
アプリケーションの追加 を選択します。
Copilot Studio 認証設定ページの トークン交換 URL は、Bot Framework を通じて要求されたアクセス トークンに対する OBO トークンを交換するために使用されます。
Copilot Studio は Microsoft Entra ID を呼び出して、実際の交換を行います。
Copilot Studio にサインインします。
トップ メニューにあるコパイロット アイコンを選択し、適切なコパイロットを選択して、認証を有効にするコパイロットを選択したことを確認します。
ナビゲーション メニューの 設定 で セキュリティ を選択します。 次に、認証 カードを選択します。
トークンの交換 URL フィールドにあるコパイロットの認証アプリ登録について、API の公開 ブレードから完全なスコープ URI を入力します。 URI の形式は api://1234-4567/scope.name
です。
保存 を選択してからコパイロット コンテンツを公開します。
コパイロットが配置されているカスタム キャンバス ページを更新して、ログイン カードのリクエストを受信し、OBO トークンを交換します。
次のコードを <head> セクションの <script> タグに追加して、Microsoft 認証ライブラリ (MSAL) を構成します。
アプリケーション (クライアント) ID キャンバス アプリ登録用を使用して clientId
を更新します。 <Directory ID>
をディレクトリ (テナント) ID に置き換えます。 キャンバス アプリ登録の概要 ページからこれらの ID を取得します。
<head>
<script>
var clientApplication;
(function () {
var msalConfig = {
auth: {
clientId: '<Client ID [CanvasClientId]>',
authority: 'https://login.microsoftonline.com/<Directory ID>'
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: false
}
};
if (!clientApplication) {
clientApplication = new Msal.UserAgentApplication(msalConfig);
}
} ());
</script>
</head>
次の <script> を <body> セクションに挿入します。 このスクリプトは、 resourceUrl
現在のトークンを取得し、 OAuth プロンプトで要求されたトークンと交換するメソッドを呼び出します。
<script>
function getOAuthCardResourceUri(activity) {
if (activity &&
activity.attachments &&
activity.attachments[0] &&
activity.attachments[0].contentType === 'application/vnd.microsoft.card.oauth' &&
activity.attachments[0].content.tokenExchangeResource) {
// asking for token exchange with Microsoft Entra ID
return activity.attachments[0].content.tokenExchangeResource.uri;
}
}
function exchangeTokenAsync(resourceUri) {
let user = clientApplication.getAccount();
if (user) {
let requestObj = {
scopes: [resourceUri]
};
return clientApplication.acquireTokenSilent(requestObj)
.then(function (tokenResponse) {
return tokenResponse.accessToken;
})
.catch(function (error) {
console.log(error);
});
}
else {
return Promise.resolve(null);
}
}
</script>
次の <script> を <body> セクションに挿入します。 main
メソッド内で、このコードはコパイロットの一意識別子を使用して store
に条件を追加します。 また固有の ID を、userId
変数として生成します。
コパイロットの ID を使用して <COPILOT ID>
を更新します。 使用しているコパイロットの チャネル タブ に移動し、Copilot Studio ポータルで モバイル アプリ を選択すると、コパイロットの ID を確認できます。
<script>
(async function main() {
// Add your COPILOT ID below
var BOT_ID = "<BOT ID>";
var theURL = "https://powerva.microsoft.com/api/botmanagement/v1/directline/directlinetoken?botId=" + BOT_ID;
const {
token
} = await fetchJSON(theURL);
var directline = await fetchJSON(regionalChannelSettingsURL).then(res=> res.channelUrlsById.directline);
const directLine = window.WebChat.createDirectLine({
domain: `${directline}v3/directline`,
token
});
var userID = clientApplication.account?.accountIdentifier != null ?
("Your-customized-prefix-max-20-characters" + clientApplication.account.accountIdentifier).substr(0, 64) :
(Math.random().toString() + Date.now().toString()).substr(0, 64); // Make sure this will not exceed 64 characters
const store = WebChat.createStore({}, ({
dispatch
}) => next => action => {
const {
type
} = action;
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'startConversation',
type: 'event',
value: {
text: "hello"
}
}
});
return next(action);
}
if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
const activity = action.payload.activity;
let resourceUri;
if (activity.from && activity.from.role === 'bot' &&
(resourceUri = getOAuthCardResourceUri(activity))) {
exchangeTokenAsync(resourceUri).then(function(token) {
if (token) {
directLine.postActivity({
type: 'invoke',
name: 'signin/tokenExchange',
value: {
id: activity.attachments[0].content.tokenExchangeResource.id,
connectionName: activity.attachments[0].content.connectionName,
token,
},
"from": {
id: userID,
name: clientApplication.account.name,
role: "user"
}
}).subscribe(
id => {
if (id === 'retry') {
// copilot was not able to handle the invoke, so display the oauthCard
return next(action);
}
// else: tokenexchange successful and we do not display the oauthCard
},
error => {
// an error occurred to display the oauthCard
return next(action);
}
);
return;
} else
return next(action);
});
} else
return next(action);
} else
return next(action);
});
const styleOptions = {
// Add styleOptions to customize Web Chat canvas
hideUploadButton: true
};
window.WebChat.renderWebChat({
directLine: directLine,
store,
userID: userID,
styleOptions
},
document.getElementById('webchat')
);
})().catch(err => console.error("An error occurred: " + err));
</script>
完全なサンプル コード
詳細については、MSAL およびストア条件付きスクリプトが既に GitHub リポジトリに 含まれている完全なサンプル コードを参照してください。