Partilhar via


Configure o seu Agente .NET para usar OAuth

O OAuth para um agente .NET é primeiro aprovisionado no seu recurso de Bot do Azure e no registo da aplicação correspondente. Em seguida, o runtime do agente adquire e atualiza tokens de utilizador para si através da capacidade de início de sessão automática AgentApplication. O início de sessão automático pode ser executado 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. Cada processador tem a opção de executar operações On-Behalf-Of (OBO) quando o lado do Azure estiver configurado para tal. Para um início rápido, consulte o exemplo de AutoSignIn ou adapte a configuração mostrada aqui em um agente existente.

As secções a seguir descrevem como configurar UserAuthorization, decidir entre abordagens globais e por rota e obter tokens (standard e OBO) durante um turno. Também são fornecidas orientações regionais para implantações fora dos EUA.

O agente .NET é configurado em appsettings ou via código em Program.cs. Este documento detalha usando 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 de 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 (de caracteres) Nome do processador utilizado quando AutoSignIn avaliado como true e nenhuma substituição por rota é especificada.
AutoSignIn Não bool ou delegado Quando true (predefinido), o agente tenta adquirir um token para cada atividade de entrada; pode ser substituído em runtime com Options.AutoSignIn para filtrar tipos de atividade.
Handlers Sim (pelo menos um) objeto (dicionário) Mapeamento do nome do processador para a sua configuração. Todas as chaves têm de ser exclusivas.

Para restringir a que atividades o início de sessão automático 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 do cartão de autenticação, o comportamento de nova tentativa, os tempos limite e a configuração opcional do OBO Exchange.

Propriedade Obrigatório Tipo Description
AzureBotOAuthConnectionName Yes cadeia (de caracteres) Nome da conexão OAuth definido no recurso Bot do Azure.
OBOConnectionName Não (apenas OBO) cadeia (de caracteres) Nome de uma ligação do SDK de agentes usada para executar uma troca de token "On‑Behalf‑Of".
OBOScopes Não (apenas OBO) cadeia (de carateres)[] Âmbitos solicitados durante a troca OBO; caso sejam omitidos com OBOConnectionName, pode-se chamar ExchangeTurnTokenAsync manualmente.
Title Não cadeia (de caracteres) Título do cartão de início de sessão personalizado; predefinido como Entrar.
Text Não cadeia (de caracteres) Texto do botão do cartão de login; o padrão é Fazer login.
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 (de caracteres) Mensagem mostrada após um código inserido inválido; o padrão é Código de início de sessão inválido. Introduza o código de 6 dígitos necessário.
Timeout Não int (ms) Número de milissegundos antes de uma tentativa de início de sessão em curso expirar. O padrão é 900000 (15 minutos).

Que tipo usar?

Use a tabela a seguir para decidir qual abordagem se encaixa no seu cenário.

Escolha Utilizar quando
Início de sessão automático Você deseja que cada atividade de entrada adquira automaticamente um token ou deseja 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 conexões OAuth diferentes (e, portanto, tokens diferentes). Isto é adicional ao login automático global. Se ambos estiverem ativados, o turno terá acesso aos tokens de cada um.

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

Esta secção mostra como obter e usar o token de utilizador devolvido diretamente pela sua ligação OAuth do Bot do Azure sem executar uma troca On‑Behalf‑Of. Decida primeiro se prefere o início de sessão automático global ou os controladores por rota; em seguida, dentro do controlador de atividades, execute UserAuthorization.GetTurnTokenAsync o mais tardiamente possível para que o SDK possa atualizar o token se este estiver prestes a expirar. Os exemplos a seguir ilustram ambos os padrões.

Configuração exclusiva para início de sessão automático

Utilize esta configuração quando o logon automático global deve adquirir um token para cada atividade de entrada sem precisar definir manipuladores para cada rota.

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

O código do agente ficaria mais ou menos assim:

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 apenas por rota

Use uma configuração por rota quando quiser um controle refinado: somente as rotas marcadas explicitamente adquirem tokens. A configuração por rota reduz a recuperação desnecessária de tokens, permite que rotas diferentes direcionem 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 início de sessão automático global está desativado e apenas um único processador messageOauth é anexado à rota da mensagem.

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

O código do agente ficaria mais ou menos assim:

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

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

Usar o token no código (OBO)

O On-Behalf-Of (OBO) depende do início de sessão inicial do utilizador devolvendo um token permutá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 pode ser api://botid-{{clientId}}/defaultScopes). Em seguida, o SDK de agentes executa uma troca de biblioteca de autenticação da Microsoft (MSAL) usando uma conexão configurada identificada por OBOConnectionName e a lista de OBOScopes. Quando ambos OBOConnectionName e OBOScopes estão presentes na configuração, a troca ocorre automaticamente, e você obtém o token final através do GetTurnTokenAsync. Se algum deles estiver faltando, você pode executar a troca explicitamente em tempo de execução com ExchangeTurnTokenAsync, permitindo que você resolva a conexão ou a lista de escopo dinamicamente.

OBO em configuração

Use esse padrão quando conhecer o recurso a jusante e os âmbitos necessários no momento da configuração. Quando fornece ambos OBOConnectionName e OBOScopes, o SDK executa automaticamente a troca On‑Behalf‑Of durante o início de sessão. Isso significa que as chamadas subsequentes para GetTurnTokenAsync retornam o token OBO diretamente, sem necessidade de 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 ficaria mais ou menos assim:

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 OBO em runtime

Utilize uma troca em runtime quando o recurso a jusante, os âmbitos ou até mesmo a ligação que deve ser utilizada não possam ser definidos na configuração—por exemplo, quando os âmbitos dependem de inquilino, função de utilizador ou um sinalizador de características. Neste modelo, configura (opcionalmente) o OBOConnectionName e, em seguida, chama ExchangeTurnTokenAsync com os âmbitos que decide no momento do turno, recebendo um token trocado que 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 ficaria mais ou menos assim:

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, é necessário atualizar o endpoint do serviço de token usado 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