Compartilhar via


Configurar o Agente .NET para usar o OAuth

O OAuth para um agente de .NET é provisionado inicialmente no recurso de Bot do Azure e no registro correspondente do aplicativo. Em seguida, o runtime do agente adquire e atualiza tokens de usuário para você por meio da AgentApplication capacidade de entrada automática. A entrada automática pode ser executada globalmente (todos os tipos de atividade) ou seletivamente para que apenas determinadas rotas ou tipos de atividade solicitem um token.

Você pode registrar vários manipuladores OAuth na configuração e atribuí-los a rotas específicas ou declarar um único manipulador padrão usado em todos os lugares. Como opção, cada manipulador pode executar trocas Em Nome de (OBO) quando o lado do Azure for configurado para isso. Para obter um início rápido, consulte o exemplo AutoSignIn ou reajuste a configuração mostrada aqui em um agente existente.

As seções a seguir descrevem como configurar o UserAuthorization, decidir entre abordagens globais e por rota e buscar os tokens (standard e OBO) durante uma rodada. As diretrizes regionais também são fornecidas para implantações que não sejam dos EUA.

O agente .NET é configurado em appsettings ou por meio de código em Program.cs. Este documento detalha o uso de appsettings.

Configurações

O UserAuthorization objeto dentro AgentApplication controla como os tokens de usuário são adquiridos. O JSON a seguir mostra a estrutura hierárquica seguida por tabelas que descrevem cada propriedade para UserAuthorization e para o objeto aninhado Settings .

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "{{handler-name}}",
      "AutoSignIn": true | false,
      "Handlers": {
        "{{handler-name}}": {
          "Settings": {
            "AzureBotOAuthConnectionName": "{{azure-bot-connection-name}}",
            "OBOConnectionName": "{{connection-name}}",
            "OBOScopes": [
              "{{obo-scope}}"
            ],
            "Title": "{{signin-card-title}}",
            "Text": "{{signin-card-button-text}}",
            "InvalidSignInRetryMax": {{int}},
            "InvalidSignInRetryMessage": {{invalid-attempt-message}},
            "Timeout": {{timeout-ms}}
          }
        }
      }
    }
  }

Propriedades de Autorização do Usuário

A tabela a seguir lista as propriedades de nível UserAuthorization superior que determinam como os manipuladores são selecionados e como os tokens são adquiridos para cada atividade de entrada.

Propriedade Obrigatório Tipo Description
DefaultHandlerName Não (recomendado) cadeia Nome do manipulador usado quando AutoSignIn for avaliado como verdadeiro e nenhuma substituição por rota for especificada.
AutoSignIn Não bool ou delegado Quando verdadeiro (padrão), o agente tenta obter um token para cada atividade de entrada, podendo ser substituído no runtime por Options.AutoSignIn para filtrar os tipos de atividade.
Handlers Sim (pelo menos um) objeto (dicionário) Mapeamento do nome do manipulador para sua configuração. Cada chave precisa ser exclusiva.

Para restringir a quais atividades a entrada automática se aplica, defina um predicado semelhante a: Options.AutoSignIn = (context, ct) => Task.FromResult(context.Activity.IsType(ActivityTypes.Message));.

Propriedades de configurações

A tabela a seguir descreve o objeto aninhado Settings aplicado a um manipulador OAuth individual, controlando a apresentação de cartão de entrada, o comportamento de repetição, os tempos limite e a configuração opcional do exchange OBO.

Propriedade Obrigatório Tipo Description
AzureBotOAuthConnectionName Yes cadeia Nome da conexão OAuth definido no recurso do Bot do Azure.
OBOConnectionName Não (somente OBO) cadeia Nome de uma conexão do SDK de Agentes usada para executar uma troca de tokens em nome de outra parte.
OBOScopes Não (somente OBO) cadeia de caracteres[] Escopos solicitados durante a troca de OBO. Se for omitido com OBOConnectionName, você pode chamar ExchangeTurnTokenAsync manualmente.
Title Não cadeia Título do cartão de entrada personalizado; o padrão é entrar.
Text Não cadeia Texto do botão do cartão de acesso; o padrão é Por favor, entre.
InvalidSignInRetryMax Não int Número máximo de tentativas permitidas quando o usuário insere um código inválido; o padrão é 2.
InvalidSignInRetryMessage Não cadeia Mensagem mostrada após uma entrada de código inválida; usa como padrão o código de entrada inválido. Insira o código de 6 dígitos.
Timeout Não int (ms) Número de milissegundos antes de uma tentativa de entrada em andamento expirar. O padrão é 900000 (15 minutos).

Que tipo deve ser usado?

Use a tabela a seguir para decidir qual abordagem se ajusta ao seu cenário.

Opção Usar quando
Entrada automática Você deseja que todas as atividades de entrada adquiram automaticamente um token ou que você queira um subconjunto filtrado (por exemplo, apenas mensagens ou tudo, exceto eventos) fornecendo um predicado para UserAuthorizationOptions.AutoSignIn.
Por rota Somente manipuladores de rotas específicos precisam de tokens ou rotas diferentes devem usar diferentes conexões OAuth (e, portanto, tokens diferentes). Isso é cumulativo com o login automático global. Se ambos estiverem habilitados, cada turno terá acesso aos tokens de cada um.

Usar o token no código (não OBO)

Esta seção mostra como recuperar e usar o token de usuário retornado diretamente pela conexão OAuth do Azure Bot sem executar uma troca do tipo "On-Behalf-Of". Decida primeiro se você prefere manipuladores globais de entrada automática ou por rota; em seguida, dentro do manipulador de atividades, chame UserAuthorization.GetTurnTokenAsync o mais tarde possível para que o SDK possa atualizar o token se ele estiver perto da expiração. Os exemplos a seguir ilustram ambos os padrões.

Configuração de login automático somente

Use esta configuração quando o login automático global deve adquirir um token para cada atividade recebida sem a necessidade de especificar manipuladores por rota.

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "auto",
      "Handlers": {
        "auto": {
          "Settings": {
            "AzureBotOAuthConnectionName": "teams_sso",
          }
        }
      }
    }
  },

O código do agente seria semelhante a este:

public class MyAgent : AgentApplication
{
    public MyAgent(AgentApplicationOptions options) : base(options)
    {
        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
    }

    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var token = await UserAuthorization.GetTurnTokenAsync(turnContext);

        // use the token 
    }
}

Configuração somente por rota

Use uma configuração por rota quando quiser um controle detalhado: apenas as rotas que você marca explicitamente adquirem tokens. A configuração por rota reduz a recuperação de token desnecessária, permite rotas diferentes para direcionar conexões OAuth distintas (e, portanto, recursos ou escopos diferentes) e permite misturar rotas autenticadas e não autenticadas dentro do mesmo agente. No exemplo a seguir, o acesso automático global está desativado e um único manipulador messageOauth está anexado apenas à rota da mensagem.

  "AgentApplication": {
    "UserAuthorization": {
      "AutoSignIn": false,
      "Handlers": {
        "messageOauth": {
          "Settings": {
            "AzureBotOAuthConnectionName": "teams_sso",
          }
        }
      }
    }
  },

O código do agente seria semelhante a este:

public class MyAgent : AgentApplication
{
    public MyAgent(AgentApplicationOptions options) : base(options)
    {
        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last, autoSignInHandlers: ["messageOauth"]);
    }

    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var token = await UserAuthorization.GetTurnTokenAsync(turnContext, "messageOauth");

        // use the token
    }
}

Utilize GetTurnTokenAsync

Chame GetTurnTokenAsync sempre que precisar do token de usuário durante um turno. Você pode invocá-lo várias vezes. Chame-o imediatamente antes do uso para que a lógica de atualização (se necessário) seja tratada de forma transparente.

Usar o token no código (não OBO)

On-Behalf-Of (OBO) depende do login inicial do usuário retornando um token trocável. Isso requer que os escopos da conexão OAuth incluam um que corresponda a um escopo exposto pela API downstream (por exemplo, se o escopo exposto for defaultScopes, o escopo configurado poderá ser api://botid-{{clientId}}/defaultScopes). Em seguida, o SDK de Agentes executa uma troca da MSAL (Biblioteca de Autenticação da Microsoft) usando uma conexão configurada identificada por OBOConnectionName e a lista de OBOScopes. Quando ambos OBOConnectionNameOBOScopes estiverem presentes na configuração, a troca ocorrerá automaticamente e você obterá o token final por meio GetTurnTokenAsync. Se qualquer um estiver ausente, você poderá executar a troca explicitamente no runtime com ExchangeTurnTokenAsync, permitindo que você resolva a conexão ou a lista de escopo dinamicamente.

OBO na configuração

Use esse padrão quando souber o recurso downstream e os escopos necessários no momento da configuração. Quando você fornece ambos OBOConnectionName e OBOScopes, o SDK executa automaticamente a troca Em nome de durante a entrada. Isso significa que chamadas subsequentes para GetTurnTokenAsync retornam o token OBO diretamente, sem necessidade de nenhum código adicional em tempo de execução.

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "auto",
      "Handlers": {
        "auto": {
          "Settings": {
            "AzureBotOAuthConnectionName": "teams_sso",
            "OBOConnectionName": "ServiceConnection",
            "OBOScopes": [
              "https://myservicescope.com/.default"
            ]
          }
        }
      }
    }
  },
  "Connections": {
    "ServiceConnection": {
      "Settings": {
        "AuthType": "FederatedCredentials",
        "AuthorityEndpoint": "https://login.microsoftonline.com/{{TenantId}}",
        "ClientId": "{{ClientId}}",
        "FederatedClientId": "{{ManagedIdentityClientId}}",
        "Scopes": [
          "https://api.botframework.com/.default"
        ]
      }
    }
  },

O código do agente seria semelhante a este:

public class MyAgent : AgentApplication
{
    public MyAgent(AgentApplicationOptions options) : base(options)
    {
        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
    }

    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var token = await UserAuthorization.GetTurnTokenAsync(turnContext);

        // use the token
    }
}

Troca de OBO no runtime

Use uma troca no runtime quando o recurso downstream, os escopos ou até mesmo a conexão que você deve usar não podem ser fixos na configuração, por exemplo, quando os escopos dependem do locatário, do papel do usuário ou de um sinalizador de recurso. Nesse modelo, você configura (opcionalmente) o OBOConnectionNamee, em seguida, chama ExchangeTurnTokenAsync com os escopos que você decide em tempo de turno, recebendo um token trocado que você pode aplicar imediatamente.

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "auto",
      "Handlers": {
        "auto": {
          "Settings": {
            "AzureBotOAuthConnectionName": "teams_sso",
            "OBOConnectionName": "ServiceConnection"
          }
        }
      }
    }
  },
  "Connections": {
    "ServiceConnection": {
      "Settings": {
        "AuthType": "FederatedCredentials",
        "AuthorityEndpoint": "https://login.microsoftonline.com/{{TenantId}}",
        "ClientId": "{{ClientId}}",
        "FederatedClientId": "{{ManagedIdentityClientId}}",
        "Scopes": [
          "https://api.botframework.com/.default"
        ]
      }
    }
  },

O código do agente seria semelhante a este:

public class MyAgent : AgentApplication
{
    public MyAgent(AgentApplicationOptions options) : base(options)
    {
        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
    }

    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var scopes = GetScopes();

        var exchangedToken = await UserAuthorization.ExchangeTurnTokenAsync(turnContext, exchangeScopes: scopes);

        // use the token
    }
}

Configurações regionais do OAuth

Para regiões fora dos EUA, você precisa atualizar o endpoint do serviço de token utilizado pelo seu agente.

Adicione o seguinte a appsettings.json:

"RestChannelServiceClientFactory": {
   "TokenServiceEndpoint": "{{service-endpoint-uri}}"
}

Para service-endpoint-url, use o valor apropriado da tabela a seguir para bots de nuvem pública com residência de dados na região especificada.

URI Região
https://europe.api.botframework.com Europa
https://unitedstates.api.botframework.com Estados Unidos
https://india.api.botframework.com Índia