Adicionar logon único a um bot

APLICA-SE A: SDK v4

Este artigo mostra como usar o recurso SSO (logon único) em um bot. Para tal, esse recurso usa um bot de consumidor (também conhecido como bot raiz ou pai) para interagir com uma habilidade ou bot criança. Este artigo usa os termos bot raiz e bot de habilidade.

Se você incluir suporte a SSO, um usuário poderá iniciar uma sessão no bot raiz usando um provedor de identidade e não precisará fazê-lo novamente quando o controle passar para uma habilidade.

Os bots raiz e de habilidade são bots separados, sendo executados em servidores potencialmente diferentes, cada um com suas memórias e estados separados. Para obter mais informações, confira a Visão geral de habilidades e Implementação de habilidades. Para obter mais informações sobre autenticação de usuário, confira Noções básicas de autenticação do Bot Framework, Autenticação de usuário e Adicionar autenticação a um bot.

Importante

Quando você usa a autenticação do Serviço de Bot de IA do Azure com o Webchat, há algumas considerações importantes sobre segurança que precisam ser levadas em consideração. Para obter mais informações, confira a seção considerações sobre segurança no artigo de autenticação REST.

Pré-requisitos

Sobre o exemplo

Este artigo faz referência a dois bots: o RootBot e o SkillBot. O RootBot encaminha as atividades para o SkillBot. Eles modelam o seguinte cenário típico de skill:

  • Um bot raiz chama um ou mais bots de skill.
  • Os bots raiz e de skill implementam a autenticação básica descrita no artigo Adicionar autenticação a um bot.
  • O usuário faz logon no bot raiz.
  • Como o SSO já está conectado ao bot raiz, eles também estão conectados ao bot de habilidade sem precisar de uma nova interação do usuário.

Para obter uma visão geral de como o Bot Framework lida com a autenticação, confira Autenticação de usuário. Para obter mais informações de contexto sobre o SSO, confira Logon único.

O RootBot dá suporte ao SSO. Ele se comunica com o SkillBot em nome do usuário, sem que o usuário precise se autenticar novamente no _SkillBot.

Para cada projeto no exemplo, você precisa do seguinte:

  1. Um aplicativo do Microsoft Entra ID para registrar um recurso de bot no Azure.
  2. Um aplicativo provedor de identidade do Microsoft Entra ID para autenticação.

    Observação

    No momento, há suporte apenas para o provedor de identidade do Microsoft Entra ID.

Criar o recurso RootBot do Azure

  1. Crie um recurso de bot do Azure no portal do Azure para o RootBot. Siga as etapas descritas em Criar um recurso de bot no Azure.
  2. Copie e salve a ID do aplicativo e o segredo do cliente do registro do bot.

Criar a identidade do Microsoft Entra ID para o RootBot

O Microsoft Entra ID é um serviço de identidade de nuvem que permite criar aplicativos que conectam usuários com segurança usando protocolos padrão do setor, como o OAuth2.0.

  1. Crie um aplicativo de identidade para o RootBot que usa o Microsoft Entra ID para autenticar o usuário. Siga as etapas descritas em Criar provedor de identidade do Microsoft Entra ID.

  2. No painel esquerdo, escolha Manifesto.

  3. Defina accessTokenAcceptedVersion como 2.

  4. Selecione Salvar.

  5. No painel esquerdo, escolha Expor uma API.

  6. No painel direito, escolha Adicionar um escopo.

  7. No lado mais à direita da seção Adicionar um escopo, escolha Salvar e continuar.

  8. Na janela exibida, em Quem pode consentir?, escolha Administradores e usuários.

  9. Insira as outras informações necessárias.

  10. Selecione Adicionar escopo.

  11. Copie e salve o valor do escopo.

Definir configuração de conexão do OAuth para RootBot

  1. Crie uma conexão do Microsoft Entra ID no registro de bot RootBot e insira os valores conforme descritos em Microsoft Entra ID e o valor descrito abaixo.

  2. Deixe vazia a URL de troca de token.

  3. Na caixa Escopos, insira o valor de escopo RootBot que você salvou nas etapas anteriores.

    Observação

    A caixa Escopos contém a URL que o usuário inicialmente entra no bot raiz, enquanto a URL de troca de token é deixada vazia.

    Como exemplo, vamos supor que o appid do bot raiz seja rootAppId e o appid do bot de habilidade seja skillAppId. Os escopos do bot raiz serão como api://rootAppId/customScope, que é usado para logon do usuário. Os escopos desse bot raiz serão então trocados com api://skillAppId/customscope durante o SSO.

  4. Copie e salve o nome da conexão.

Criar o recurso SkillBot do Azure

  1. Crie um recurso de bot do Azure no portal do Azure para o SkillBot. Siga as etapas descritas em Criar um recurso de bot no Azure.
  2. Copie e salve a ID do aplicativo e o segredo do cliente do registro do bot.

Criar identidade no Microsoft Entra ID para o SkillBot

O Microsoft Entra ID é um serviço de identidade de nuvem que permite criar aplicativos que conectam usuários com segurança usando protocolos padrão do setor, como o OAuth2.0.

  1. Crie um aplicativo de identidade para o SkillBot que utiliza o Microsoft Entra ID para autenticar o bot. Siga as etapas descritas em Criar provedor de identidade do Microsoft Entra ID.

  2. No painel esquerdo, escolha Manifesto.

  3. Defina accessTokenAcceptedVersion como 2.

  4. Selecione Salvar.

  5. No painel esquerdo, escolha Expor uma API.

  6. No painel direito, escolha Adicionar um escopo.

  7. No lado mais à direita da seção Adicionar um escopo, escolha Salvar e continuar.

  8. Na janela exibida, em Quem pode consentir?, selecione Administradores e usuários.

  9. Insira as outras informações necessárias.

  10. Selecione Adicionar escopo.

  11. Copie e salve o valor do escopo.

  12. Selecione Adicionar um aplicativo cliente. Na seção na extrema direita, na caixa ID do cliente, insira a ID do aplicativo da Identidade do RootBot que você salvou anteriormente. Certifique-se de usar a identidade do RootBot, e não a ID do aplicativo de registro.

    Observação

    Para aplicativos cliente, o Serviço de Bot de IA do Azure não oferece suporte a um único início de sessão com o provedor de identidade B2C do Microsoft Entra ID.

  13. Em Escopo autorizado, marque a caixa pelo valor de escopo.

  14. Selecione Adicionar aplicativo.

  15. Selecione Permissões de API no painel de navegação esquerdo. A melhor prática é definir explicitamente as permissões de API para o aplicativo.

    1. No painel direito, escolha Adicionar uma permissão.

    2. Selecione as APIs da Microsoft e do Microsoft Graph.

    3. Escolha Permissões delegadas e verifique se as permissões necessárias estão selecionadas. Este exemplo requer as permissões relacionadas abaixo.

      Observação

      As permissões marcadas como CONSENTIMENTO DO ADMINISTRADOR NECESSÁRIO exigirão que um usuário e um administrador de locatário façam logon.

      • openid
      • profile
      • User.Read
      • User.ReadBasic.All
    4. Selecione Adicionar Permissões.

Criar uma configuração de conexão OAuth para o SkillBot

  1. Crie uma conexão do Microsoft Entra ID no registro de bot SkillBot e insira os valores conforme descritos em Microsoft Entra ID e os valores descritos abaixo.

  2. Na caixa URL de Troca de Token, insira o valor de escopo SkillBot que você salvou nas etapas anteriores.

  3. Na caixa Escopos, insira os valores a seguir separados por espaços em branco: profileUser.ReadUser.ReadBasic.Allopenid.

  4. Copie e salve o nome da conexão em um arquivo.

Testar a conexão

  1. Escolha a entrada de conexão para abrir a conexão que você criou.
  2. Escolha Testar Conectividade na parte superior do painel Configuração da Conexão do Provedor de Serviços.
  3. Na primeira vez, deve abrir uma nova guia do navegador listando as permissões que seu aplicativo está solicitando e solicitará que você aceite.
  4. Selecione Aceitar.
  5. Essa ação deve redirecionar você para uma página de Teste de Conectividade para <nome-da-sua-conexão> bem-sucedida.

Para obter mais informações, confira Visão geral do Microsoft Entra ID para desenvolvedores (v1.0) e Visão geral da plataforma de identidade da Microsoft (v2.0). Para obter informações sobre as diferenças entre os pontos de extremidade v1 e v2, confira Por que atualizar para a plataforma de identidade da Microsoft (v2.0)?. Para obter informações completas, confira a Plataforma de identidade da Microsoft (anteriormente, Microsoft Entra ID para desenvolvedores).

Preparar os exemplos de códigos

Você deve atualizar o arquivo appsettings.json nos dois exemplos, como descrito abaixo.

  1. No repositório do GitHub, clone o exemplo SSO com Consumidor de Habilidade Simples e Habilidade.

  2. Abra o arquivo appsettings.json do projeto SkillBot. No arquivo salvo, atribua os seguintes valores:

    {
        "MicrosoftAppId": "<SkillBot registration app ID>",
        "MicrosoftAppPassword": "<SkillBot registration password>",
        "ConnectionName": "<SkillBot connection name>",
        "AllowedCallers": [ "<RootBot registration app ID>" ]
    }
    
    
  3. Abra o arquivo appsettings.json do projeto RootBot. No arquivo salvo, atribua os seguintes valores:

    {
        "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"
                }
            ]
    }
    

Testar os exemplos

Use o seguinte para testar:

  • Comandos de RootBot

    • O login permite que o usuário entre no registro do Microsoft Entra ID usando o RootBot. Depois de conectado, o SSO também entra no SkillBot. O usuário não precisa entrar novamente.
    • token exibe o token do usuário.
    • logout desconecta o usuário do RootBot.
  • Comandos de SkillBot

    • skill login permite que o RootBot entre no SkillBot em nome do usuário. O usuário não será exibido no cartão de entrada, se já tiver se conectado, a menos que o SSO falhe.
    • skill token exibe o token do usuário de SkillBot.
    • skill logout desconecta o usuário do SkillBot

Observação

Na primeira vez que os usuários tentarem o SSO em um skill, eles poderão receber um cartão OAuth para fazer logon. Isso ocorre porque eles ainda não deram consentimento para o aplicativo do Microsoft Entra ID da habilidade. Para evitar isso, eles podem conceder consentimento do administrador para qualquer permissão de gráfico solicitada pelo aplicativo Microsoft Entra ID.

Caso ainda não tenha feito isso, instale o Bot Framework Emulator. Confira também Depurar com o Emulator.

Você precisará configurar o Emulator para que o logon de exemplo do bot funcione. Siga as etapas abaixo, conforme mostrado em Configurar o Emulator para autenticação.

Após configurar o mecanismo de autenticação, é possível executar o teste real do exemplo do bot.

  1. No Visual Studio, abra a solução SSOWithSkills.sln e configure-a para iniciar a depuração com vários processos.

  2. Execute o bot em seu computador local. Observe que, no arquivo appsettings.json do projeto RootBot, você tem as seguintes configurações:

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

    Observação

    Essas configurações implicam que RootBot e SkillBot estão em execução no computador local. O Emulator se comunica com RootBot na porta 3978 e RootBot se comunica com SkillBot na porta 39783. Assim que você inicia a depuração, duas janelas de navegador padrão são abertas. Uma na porta 3978 e a outra na porta 39783.

  3. Inicie o Emulador.

  4. É necessário fornecer a ID e a senha do aplicativo de registro do RootBot ao se conectar ao bot.

  5. Digite hi para iniciar a conversa.

  6. Digite login. O RootBot exibirá o cartão de autenticação para Entrar no AAD.

    Example of a sign-in card.

  7. Selecione Entrar. A caixa de diálogo pop-up Confirmar Abertura de URL é exibida.

    Screenshot of the 'open URL' confirmation message.

  8. Selecione Confirmar. Você será conectado, e o token RootBot será exibido.

  9. Digite token para exibir o token novamente.

    Example of a message displaying the root token.

    Agora você está pronto para se comunicar com o SkillBot. Ao entrar usando o RootBot, você não precisará fornecer suas credenciais novamente até sair. Isso demonstra que o SSO está funcionando.

  10. Digite skill login na caixa do Emulator. O logon não será solicitado novamente. Em vez disso, o token do SkillBot é exibido.

  11. Digite skill token para exibir o token novamente.

  12. Agora você pode digitar skill logout para se desconectar do SkillBot. Em seguida, digite logout para sair do SimpleRootBoot.

Informações adicionais

O diagrama de sequência de tempo a seguir aplica-se aos exemplos usados no artigo e mostra a interação entre os vários componentes envolvidos. ABS significa Serviço de Bot de IA do Azure.

Sequence diagram illustrating the skill token flow.

  1. Na primeira vez, o usuário digita o comando login para o RootBot.
  2. O RootBot envia um OAuthCard solicitando que o usuário entre.
  3. O usuário digita as credenciais de autenticação, que são enviadas para o ABS (Serviço de Bot de IA do Azure).
  4. O ABS envia o token de autenticação, gerado com base nas credenciais do usuário, para o RootBot.
  5. O RootBot exibe o token da raiz para o usuário.
  6. O usuário digita o comando skill login para o SkillBot.
  7. O SkillBot envia um OAuthCard para o RootBot.
  8. O RootBot solicita um token intercambiável do ABS.
  9. O SSO envia o token de habilidade do SkillBot para o RootBot.
  10. O RootBot exibe o token do skill para o usuário. Observe que o token do skill foi gerado sem que o usuário precisasse entrar no SKillBot. Isso acontece por causa do SSO.

O exemplo a seguir mostra como a troca de token acontece. O código é do arquivo 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;
}