ボットが展開されているページまたはアプリで既にサインインしている場合、シングル サインオン (SSO) により Web サイトのチャットボットは顧客をサインインさせることができます。
Power Virtual Agents プレビューでは、カスタム Web サイト チャネルでのみ SSO がサポートされています。 次のチャネルではサポートされていません。
- Azure ボット サービス
- デモ Web サイト
- Facebook
- Microsoft Teams
- Mobile app
またはボットが作成されたとき:
- Teams、SharePoint Web サイト、または Power Apps ポータルに公開済み
- Dynamics 365 Customer Service と統合済み
カスタム Web サイト用のアプリ登録を作成する
SSO を有効にするには、異なる 2 つのアプリ登録が必要です。
- ボットでの Azure Active Directory (Azure AD) ユーザー認証を有効にする認証アプリ登録
- カスタム Web ページの SSO を有効にするキャンバス アプリの登録
セキュリティ上の理由から、ボットとカスタム Web サイトの両方に対して同じアプリ登録を再利用することはお勧めしません。
- Azure AD を使用してユーザー認証を構成するの指示に従って、認証アプリの登録を作成します。
- もう一度同じ指示に従って、キャンバス アプリの登録として機能する 2 つ目のアプリ登録を作成します。
- この記事に戻ります。
キャンバス アプリの登録を作成した後は、認証にアクセスし、プラットフォームの追加を選択します。
プラットフォームの構成の下で、プラットフォームの追加、次に Web を選択します。
リダイレクト URI の下で、http://contoso.com/index.html
などの Web ページの URL を入力します。
暗黙的な許可とハイブリッド フロー セクションで、アクセス トークン (暗黙的なフローに使用) と ID トークン (暗黙的およびハイブリッド フローに使用) の両方をオンにします。
構成を選択します。
ご利用のボットのトークン エンドポイント URL を確認する
Power Virtual Agents で、設定に移動し、次にチャネルを選択します。
モバイル アプリを選択します。
トークン エンドポイントの下で、コピーを選択します。
Web ページで SSO を構成する
Power Virtual Agents GitHub リポジトリで提供されるコードを使用して、リダイレクト URL の Web ページを作成します。 GitHub リポジトリからコードをコピーし、以下の手順に従って変更します。
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
ブラウザーがポップアップをブロックしている場合、またシークレットまたはプライベートブラウザー ウィンドウを使用している場合は、ログインするよう求められます。 それ以外の場合は、ログインは検証コードを使用して完了します。
新しいブラウザー タブが開きます。
新しいタブに切り替えて、検証コードをコピーします。
ボットのあるタブに戻り、ボットの会話に検証コードを貼り付けます。
たとえば、ボットは社内のイントラネットまたはユーザーが既にサインインしているアプリでホストされます。
Power Virtual Agents の SSO を構成する、4 つの主な手順があります:
Azure AD でカスタム キャンバス用のアプリ登録を作成します。
ボットのカスタム スコープを定義します。
SSO を有効にするように Power Virtual Agents で認証を構成します。
SSO を有効にするように、カスタム キャンバス HTML コードを構成します。
重要
ボットが次のいずれかである場合、SSO は現在サポートされていません:
サポート対象のチャネル
次の表は、現在 SSO をサポートしているチャネルの詳細です。 追加のチャネルのサポートは Power Virtual Agents アイデア フォーラムで 提案できます。
1 Teams チャネルも有効にしている場合は、Teams チャネルの SSO の構成 説明書の構成手順に従う必要があります。 そのページの指示に従って Teams SSO 設定を構成しないと、ユーザーは Teams チャネルを使用するときに常に認証に失敗します。
2 ライブ チャット チャネルのみがサポートされています。 詳細については、Dynamics 365 Customer Service のハンドオフを構成する を参照してください。
技術的な概要
次の図は、ユーザーが Power Virtual Agents でログイン プロンプト (SSO) を表示せずにサインインする方法を示します:
ボット ユーザーは、サインイン トピックをトリガーする フレーズを入力します。 サインイン トピックは、ユーザーをサインインしてユーザーの認証されたトークン (AuthToken
変数) を使用するように設計されています。
Power Virtual Agents はログイン プロンプトを送信して、ユーザーが構成された ID プロバイダーでサインインできるようにします。
ボットのカスタム キャンバス はサインイン プロンプトを傍受し、代理 (OBO) トークンを Azure AD から要求します。 キャンバスはトークンをボットに送信します。
OBO トークンの受信時に、ボットは OBO トークンを「アクセス トークン」に交換し、アクセス トークンの値を使用して AuthToken
変数を入力します。 IsLoggedIn
変数はこの時点でも設定されます。
Azure AD でカスタム キャンバス用のアプリ登録を作成する
SSO を有効にするには、2 つの個別のアプリ登録が必要です。
重要
ボットのユーザー認証とカスタム キャンバスの両方に同じアプリ登録を利用することはできません。
ボットのキャンバス用アプリ登録を作成する
Azure ポータルにサインインします。
アプリ登録 に移動して、アイコンを選択するか、上部の検索バーで検索します。
新規登録を選択します。
登録の名前を入力してください。 登録しているキャンバスのボットの名前を使用し、"キャンバス" を含めて認証用のアプリ登録と区別するのに役立ちます。
たとえば、ボットが "Contoso 営業ヘルプ" と呼ばれている場合、アプリ登録に "ContosoSalesCanvas" などの名前を付ける場合があります。
サポートされているアカウントの種類 からアカウントの種類を選択します。 任意の組織ディレクトリ内のアカウント (任意の Azure AD ディレクトリ - マルチテナント型) と個人の Microsoft アカウント (Skype、Xbox など)の選択を推奨します。
次のステップでその情報を入力するので、今回はリダイレクト URI セクションを空白のままにします。 登録を選択します。
登録が完了した後、概観ページが開きます。 マニフェストにアクセスします。 accessTokenAcceptedVersion
が 2
に設定されていることを確認します。 そうでない場合は、2
に変更し、保存を選択します。
リダイレクト URL の追加
登録を開いた状態で、認証にアクセスし、プラットフォームの追加を選択します。
プラットフォームの構成ブレードで、Web を選択します。
リダイレクト URI で、チャット キャンバスがホストされているページに完全な URL を追加します。 暗示的な許可セクションで、ID トークンおよびアクセス トークン チェックボックスを選択します。
構成を選択して変更を確認します。
API アクセス許可に移動します。 <テナント名>に管理者の承認を付与するを選択してから、はいを選択します。
重要
ユーザーが各アプリケーションに同意するのを防ぐには、グローバル管理者、アプリケーション管理者、またはクラウド アプリケーション管理者がアプリの登録にテナント全体の同意を付与する 必要があります。
ボットのカスタム スコープを定義する
認証アプリ登録内でキャンバス アプリ登録用の API を公開することにより、カスタム スコープを定義します。 スコープ により、ユーザーと管理者の役割およびアクセス権を決定できます。
この手順では、認証用の認証アプリ登録とカスタム キャンバス用のアプリ登録の間に信頼関係が作成されます。
認証を構成したとき に作成したアプリ登録を開きます。
API アクセス許可に移動し、ボットに適切なアクセス許可が追加されていることを確認してください。 <テナント名>に管理者の承認を付与するを選択してから、はいを選択します。
重要
ユーザーが各アプリケーションに同意するのを防ぐには、グローバル管理者、アプリケーション管理者、またはクラウド アプリケーション管理者がアプリの登録にテナント全体の同意を付与する 必要があります。
API を公開するに移動してからスコープの追加を選択します。
スコープの名前と、ユーザーが SSO 画面にアクセスしたときに表示される表示情報を入力します。 スコープの追加を選択します。
クライアント アプリケーションの追加を選択します。
アプリケーション (クライアント) ID を、キャンバス アプリ登録の概要ページからクライアント ID フィールドに入力します。 作成した一覧表示スコープのチェックボックスを選択します。
アプリケーションの追加を選択します。
Power Virtual Agents 認証設定ページの トークン交換 URL は、Bot Framework を通じて要求されたアクセス トークンに対する OBO トークンを交換するために使用されます。
Power Virtual Agents は Azure AD を呼び出して、実際の交換を行います。
Power Virtual Agents にサインインします。
トップ メニューにあるボット アイコンを選択し、適切なボットを選択して、認証を有効にするボットを選択したことを確認します。
ナビゲーション メニューの 設定 で セキュリティ を選択します。 次に、認証 カードを選択します。
トークンの交換 URL フィールドにあるボットの認証アプリ登録について、API の公開ブレードから完全スコープ URI を入力します。 URL の形式は、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 AAD
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 を使用して <BOT ID>
を更新します。 使用しているチャンネル タブに移動し、Power Virtual Agents ポータルでモバイル アプリを選択することにより、ボットの ID を確認できます。
<script>
(async function main() {
// Add your BOT 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);
const directLine = window.WebChat.createDirectLine({
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') {
// bot 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 リポジトリ に含まれている完全なサンプル コードを検索できます。