共用方式為


將單一登錄新增至 Bot

適用於: SDK v4

本文說明如何在 Bot 中使用單一登錄 (SSO) 功能。 若要這樣做,這項功能會使用 取用者 Bot,也稱為 Bot,與 技能 Bot 互動。 本文使用根 Bot 和技能 Bot 一詞。

如果您包含 SSO 支援,使用者可以使用身分識別提供者登入根 Bot,而且當控制傳遞至技能時,不需要再次登入。

根和技能 Bot 是個別的 Bot,可在可能不同的伺服器上執行,每個伺服器都有自己的個別記憶體和狀態。 如需技能的詳細資訊,請參閱 技能概觀實作技能。 如需使用者驗證的詳細資訊,請參閱 Bot Framework 驗證基本概念使用者驗證將驗證新增至 Bot

重要

當您搭配 網路聊天 使用 Azure AI Bot Service 驗證時,必須牢記一些重要的安全性考慮。 如需詳細資訊,請參閱 REST 驗證一文中的安全性考慮 一節。

必要條件

關於範例

本文參考兩個 Bot: RootBotSkillBot。 RootBot 會將活動轉送至 SkillBot。 他們會建立此 一般 技能案例的模型:

  • Bot 會呼叫一或多個技能 Bot。
  • 根和技能 Bot 都會實作將驗證新增至 Bot 一文中所述的基本驗證。
  • 用戶登入根 Bot。
  • 由於 SSO 已登入根 Bot,因此他們已登入技能 Bot,而不需要再次進行用戶互動。

如需 Bot Framework 如何處理驗證的概觀,請參閱 用戶驗證。 如需 SSO 背景資訊,請參閱 單一登錄

RootBot 支援 SSO。 它會代表使用者與 SkillBot 通訊,而不需要使用者再次向_SkillBot進行驗證。

針對範例中的每個專案,您需要下列專案:

  1. Microsoft Entra ID 應用程式,以在 Azure 中註冊 Bot 資源。
  2. 用於驗證的Microsoft Entra ID 識別提供者應用程式。

    注意

    目前僅 支援Microsoft Entra ID 識別提供者。

建立 Azure RootBot 資源

  1. 在的 Azure 入口網站 RootBot建立 Azure Bot 資源。 請遵循建立 Azure Bot 資源中所述的步驟。
  2. 複製並儲存 Bot 註冊 應用程式識別碼客戶端密碼

建立 RootBot 的Microsoft專案識別碼身分識別

Microsoft Entra ID 是雲端身分識別服務,可讓您建置應用程式,以使用 OAuth2.0 等業界標準通訊協定安全地登入使用者。

  1. RootBot 建立身分識別應用程式,以使用 Microsoft Entra 識別碼來驗證使用者。 請遵循建立 Microsoft Entra ID 識別提供者中所述的步驟。

  2. 在左窗格中,選取 [ 指令清單]。

  3. 設定 accessTokenAcceptedVersion 為 2。

  4. 選取 [儲存]。

  5. 在左窗格中,選取 [ 公開 API]。

  6. 在右窗格中,選取 [新增範圍]。

  7. 在最右邊 的 [新增範圍] 區段上,選取 [ 儲存並繼續]。

  8. 在顯示的視窗中,於 [誰可以同意?] 底下,選取 [系統管理員和使用者]。

  9. 輸入其餘的必要資訊。

  10. 選取新增範圍

  11. 複製並儲存範圍值。

建立 RootBot 的 OAuth 連線設定

  1. 在 Bot 註冊中 RootBot 建立Microsoft Entra ID 連線,並輸入值,如 Microsoft Entra ID 和以下所述的值所述。

  2. 令牌交換 URL 保留空白。

  3. 在 [ 範圍] 方塊中 ,輸入 RootBot 您在先前步驟中儲存的範圍值。

    注意

    範圍包含使用者一開始登入根 Bot 的 URL,而令牌交換 URL 則保留空白。

    例如,假設根 Bot appidrootAppId ,而技能 Bot appidskillAppId。 根 Bot 的範圍 看起來會像 api://rootAppId/customScope,用來登入使用者。 接著, 此根 Bot 的範圍 會在 SSO 期間與 api://skillAppId/customscope 交換。

  4. 複製並儲存連接的名稱。

建立 Azure SkillBot 資源

  1. 在的 Azure 入口網站 SkillBot建立 Azure Bot 資源。 請遵循建立 Azure Bot 資源中所述的步驟。
  2. 複製並儲存 Bot 註冊 應用程式識別碼客戶端密碼

建立 SkillBot 的Microsoft Entra ID 身分識別

Microsoft Entra ID 是雲端身分識別服務,可讓您建置應用程式,以使用 OAuth2.0 等業界標準通訊協定安全地登入使用者。

  1. SkillBot 建立識別應用程式,以使用 Microsoft Entra 識別碼來驗證 Bot。 請遵循建立 Microsoft Entra ID 識別提供者中所述的步驟。

  2. 在左窗格中,選取 [ 指令清單]。

  3. 設定 accessTokenAcceptedVersion 為 2。

  4. 選取 [儲存]。

  5. 在左窗格中,選取 [ 公開 API]。

  6. 在右窗格中,選取 [新增範圍]。

  7. 在最右邊 的 [新增範圍] 區段中,選取 [ 儲存並繼續]。

  8. 在顯示的視窗中,於 [誰可以同意?] 底下,選取 [系統管理員和使用者]。

  9. 輸入其餘的必要資訊。

  10. 選取新增範圍

  11. 複製並儲存範圍值。

  12. 選取新增用戶端應用程式。 在最右邊的區段中,於 [用戶端標識符] 方塊中,輸入您之前儲存的 RootBot 身分識別應用程式識別碼。 請確定您使用 RootBot 身分識別,而不是註冊應用程式識別碼。

    注意

    針對用戶端應用程式,Azure AI Bot Service 不支援搭配 Microsoft Entra ID B2C 識別提供者的單一唱對。

  13. 在 [授權的範圍] 底下,依範圍值核取方塊。

  14. 選取新增應用程式

  15. 在左側瀏覽窗格中,選取 [API 許可權]。 最佳做法是明確設定應用程式的 API 許可權。

    1. 在右窗格中,選取 [ 新增許可權]。

    2. 選取 [Microsoft API ],然後 Microsoft Graph

    3. 選擇 [委派的許可權 ],並確定已選取所需的許可權。 此範例需要下列許可權。

      注意

      任何標示為 「需要 管理員同意」的許可權都需要使用者和租用戶系統管理員登入。

      • openid
      • profile
      • User.Read
      • User.ReadBasic.All
    4. 選取新增權限

建立 SkillBot 的 OAuth 連線設定

  1. 在 Bot 註冊中 SkillBot 建立Microsoft Entra ID 連線,並輸入值,如 Microsoft Entra ID 和以下所述的值所述。

  2. 在 [ 令牌交換 URL] 方塊中,輸入 SkillBot 您在先前步驟中儲存的範圍值。

  3. 在 [範圍] 方塊中,輸入下列以空白分隔的值: openidprofile User.ReadBasic.All User.Read

  4. 複製並儲存至連接名稱的檔案。

測試連線

  1. 選取連線項目以開啟您所建立的連接。
  2. 選取 [服務提供者連線設定] 窗格頂端的 [測試連線]。
  3. 第一次,這應該會開啟新的瀏覽器索引標籤,其中列出您的應用程式要求的許可權,並提示您接受。
  4. 選取 [接受]。
  5. 然後,這應該會將您重新導向至 [測試連線] 至 <您的連線名稱> [ 成功] 頁面。

如需詳細資訊,請參閱適用於開發人員的Microsoft專案標識碼概觀和 Microsoft 身分識別平台 (v2.0) 概觀。 如需 v1 和 v2 端點之間差異的相關信息,請參閱為什麼更新為 Microsoft 身分識別平台 (v2.0)?。 如需完整資訊,請參閱 Microsoft 身分識別平台(先前Microsoft開發人員的 Entra 標識符)。

準備範例程序代碼

您必須更新 appsettings.json 這兩個範例中的檔案,如下所示。

  1. 從 GitHub 存放 庫複製具有簡單技能取用者和技能 範例的 SSO。

  2. SkillBot開啟項目appsettings.json檔。 從儲存的檔案指派下列值:

    {
        "MicrosoftAppId": "<SkillBot registration app ID>",
        "MicrosoftAppPassword": "<SkillBot registration password>",
        "ConnectionName": "<SkillBot connection name>",
        "AllowedCallers": [ "<RootBot registration app ID>" ]
    }
    
    
  3. RootBot開啟項目appsettings.json檔。 從儲存的檔案指派下列值:

    {
        "MicrosoftAppId": "<RootBot registration app ID>",
        "MicrosoftAppPassword": "<RootBot registration password>",
        "ConnectionName": "<RootBot connection name>",
        "SkillHostEndpoint": "http://localhost:3978/api/skills/",
        "BotFrameworkSkills": [
                {
                "Id": "SkillBot",
                "AppId": "<SkillBot registration app ID>",
                "SkillEndpoint": "http://localhost:39783/api/messages"
                }
            ]
    }
    

測試範例

使用下列項目進行測試:

  • RootBot 命令

    • login 可讓使用者使用 RootBot登入 Microsoft Entra ID 註冊。 登入之後,SSO 也會負責登入 SkillBot 。 使用者不需要再次登入。
    • token 會顯示使用者的令牌。
    • logout 將使用者登出 RootBot
  • SkillBot 命令

    • skill loginRootBot允許 代表使用者登入 SkillBot。 如果用戶已經登入,除非 SSO 失敗,否則不會顯示登入卡。
    • skill token 會從 SkillBot顯示使用者的令牌。
    • skill logout 將用戶註銷 SkillBot

注意

使用者第一次嘗試使用 SSO 進行技能時,可能會看到要登入的 OAuth 卡片。 這是因為他們尚未同意技能的 Microsoft Entra ID 應用程式。 若要避免這種情況,他們可以為 Microsoft Entra ID 應用程式所要求的任何圖形許可權授與系統管理員同意。

如果您尚未這麼做,請安裝 Bot Framework 模擬器。 另 請參閱使用模擬器進行偵錯。

您必須將模擬器設定為 Bot 範例登入才能運作。 使用下列步驟:如設定模擬器以進行驗證所示

設定驗證機制之後,您可以執行實際的 Bot 範例測試。

  1. 在 Visual Studio 中SSOWithSkills.sln,開啟方案,並將其設定為使用多個進程開始偵錯。

  2. 在本機電腦上開始偵錯。 請注意,在項目appsettings.json檔中RootBot,您有下列設定:

    "SkillHostEndpoint": "http://localhost:3978/api/skills/"
    "SkillEndpoint": "http://localhost:39783/api/messages"
    

    注意

    這些設定表示在本機電腦上同時 RootBot 執行 和 SkillBot 。 模擬器會在埠 3978 上與 RootBot 通訊,並在 RootBot 埠 39783 上與 SkillBot 通訊。 一旦您開始偵錯,就會開啟兩個默認瀏覽器視窗。 埠 3978 上的一個,另一個位於埠 39783。

  3. 啟動模擬器。

  4. 當您連線到 Bot 時,請輸入註冊 RootBot 應用程式識別碼和密碼。

  5. 輸入 hi 以開始交談。

  6. 輸入 登入RootBot會顯示登入 AAD 驗證卡。

    登入卡片的範例。

  7. 選取 [登入]。 快顯對話框 [確認開啟 URL ] 隨即顯示。

    [開啟 URL] 確認訊息的螢幕快照。

  8. 選取確認。 您將登入,並 RootBot 顯示令牌。

  9. 輸入 Token 以再次顯示令牌。

    顯示根令牌的訊息範例。

    現在您已準備好與 SkillBot通訊。 使用 簽署 RootBot之後,您不需要再次提供認證,直到註銷為止。這示範 SSO 運作正常。

  10. 在 [模擬器] 方塊中輸入 技能登入 。 系統不會要求您再次登入。 而是會顯示 SkillBot 令牌。

  11. 輸入 技能令牌 以再次顯示令牌。

  12. 現在您可以輸入 技能註銷 以登出 SkillBot。 然後輸入 註銷 以登出 SimpleRootBoot

其他資訊

下列時序圖適用於本文中使用的範例,並顯示涉及的各種元件之間的互動。 ABS 代表 Azure AI Bot Service

說明技能令牌流程的循序圖。

  1. 使用者第一次輸入 login RootBot命令。
  2. RootBot傳送 OAuthCard,要求使用者登入。
  3. 使用者輸入傳送至 ABS 的驗證認證(Azure AI Bot Service)。
  4. ABS 會將根據使用者的認證產生的驗證令牌傳送至 RootBot
  5. RootBot 會顯示使用者要查看的根令牌。
  6. 用戶輸入 skill login SkillBot命令。
  7. SkillBot 會將 OAuthCard 傳送RootBot
  8. RootBot 會向 ABS 要求可交換的令牌
  9. SSO 會將 SkillBot 技能令牌傳送至 RootBot
  10. RootBot 會顯示使用者的技能令牌。 請注意,已產生技能令牌,而不需要使用者登入 SKillBot。 這是因為 SSO。

下列範例示範令牌交換的發生方式。 程式代碼來自 TokenExchangeSkillHandler.cs 檔案。

private async Task<bool> InterceptOAuthCards(ClaimsIdentity claimsIdentity, Activity activity)
{
    var oauthCardAttachment = activity.Attachments?.FirstOrDefault(a => a?.ContentType == OAuthCard.ContentType);
    if (oauthCardAttachment != null)
    {
        var targetSkill = GetCallingSkill(claimsIdentity);
        if (targetSkill != null)
        {
            var oauthCard = ((JObject)oauthCardAttachment.Content).ToObject<OAuthCard>();

            if (!string.IsNullOrWhiteSpace(oauthCard?.TokenExchangeResource?.Uri))
            {
                using (var context = new TurnContext(_adapter, activity))
                {
                    context.TurnState.Add<IIdentity>("BotIdentity", claimsIdentity);

                    // AAD token exchange
                    try
                    {
                        var result = await _tokenExchangeProvider.ExchangeTokenAsync(
                            context,
                            _connectionName,
                            activity.Recipient.Id,
                            new TokenExchangeRequest() { Uri = oauthCard.TokenExchangeResource.Uri }).ConfigureAwait(false);

                        if (!string.IsNullOrEmpty(result?.Token))
                        {
                            // If token above is null, then SSO has failed and hence we return false.
                            // If not, send an invoke to the skill with the token. 
                            return await SendTokenExchangeInvokeToSkill(activity, oauthCard.TokenExchangeResource.Id, result.Token, oauthCard.ConnectionName, targetSkill, default).ConfigureAwait(false);
                        }
                    }
                    catch
                    {
                        // Show oauth card if token exchange fails.
                        return false;
                    }

                    return false;
                }
            }
        }
    }
    return false;
}