Adicionar código para habilitar o SSO em seu aplicativo bot

Antes de adicionar código para habilitar o SSO (logon único), verifique se você configurou o recurso de aplicativo e bot em Microsoft Entra centro de administração.

Você precisa configurar o código do aplicativo para obter um token de acesso de Microsoft Entra ID. O token de acesso é emitido em nome do aplicativo bot.

Observação

Se você tiver criado seu aplicativo do Teams usando o Microsoft Teams Toolkit, poderá habilitar o SSO para seu aplicativo usando as instruções no módulo Ferramentas e SDKs. Para obter mais informações, confira Adicionar logon único ao aplicativo do Teams. O Teams Toolkit dá suporte ao SSO para aplicativos JavaScript e TypeScript em Visual Studio Code e no Teams Toolkit 17.4 versão prévia 3 para aplicativos C#.

Esta seção cobre:

  1. Atualizar variáveis de ambiente de desenvolvimento
  2. Adicionar código para manipular um token de acesso
  3. Adicionar código para receber o token
  4. Manipular o logon do usuário do aplicativo

Atualizar variáveis de ambiente de desenvolvimento

Você configurou o segredo do cliente e a configuração de conexão OAuth para o aplicativo em Microsoft Entra ID. Você deve configurar o código com esses valores.

Para atualizar as variáveis de ambiente de desenvolvimento:

  1. Abra o projeto do aplicativo bot.

  2. Abra o arquivo de ambiente do seu projeto.

  3. Atualize as seguintes variáveis:

    • Para MicrosoftAppId, atualize a ID do bot de Microsoft Entra ID.
    • Para MicrosoftAppPassword, atualize o segredo do cliente.
    • Para ConnectionName, atualize o nome da conexão OAuth configurada em Microsoft Entra ID.
    • Para MicrosoftAppTenantId, atualize a ID do locatário.
  4. Salve o arquivo.

Agora você configurou as variáveis de ambiente necessárias para seu aplicativo bot e SSO. Em seguida, adicione o código para lidar com tokens de bot.

Adicionar código para manipular um token de acesso

A solicitação para obter o token é uma solicitação de mensagem POST usando o esquema de mensagens existente. Ele está incluído nos anexos de um OAuthCard. O esquema da classe OAuthCard é definido no Microsoft Bot Schema 4.0. O Teams atualizará o token se a TokenExchangeResource propriedade for preenchida no cartão. Para o canal do Teams, somente a propriedade Id, que identifica exclusivamente uma solicitação de token, é respeitada.

Observação

O Microsoft Bot Framework OAuthPrompt ou o MultiProviderAuthDialog tem suporte para autenticação de SSO.

Para atualizar o código do aplicativo:

  1. Adicionar snippet de código para TeamsSSOTokenExchangeMiddleware.

    Adicione o snippet de código a seguir a AdapterWithErrorHandler.cs (ou a classe equivalente no código do seu aplicativo):

    base.Use(new TeamsSSOTokenExchangeMiddleware(storage, configuration["ConnectionName"]));
    

    Observação

    Você poderá receber várias respostas para uma determinada solicitação se o usuário tiver vários pontos de extremidade ativos. Você deve eliminar todas as respostas duplicadas ou redundantes com o token. Para obter mais informações sobre a entrada/tokenExchange, consulte Classe TeamsSSOTokenExchangeMiddleware.

  2. Use o snippet de código a seguir para solicitar um token.

    Depois de adicionar o AdapterWithErrorHandler.cs, o seguinte código deve aparecer:

        public class AdapterWithErrorHandler : CloudAdapter
        {
            public AdapterWithErrorHandler(
                IConfiguration configuration,
                IHttpClientFactory httpClientFactory,
                ILogger<IBotFrameworkHttpAdapter> logger,
                IStorage storage,
                ConversationState conversationState)
                : base(configuration, httpClientFactory, logger)
            {
                base.Use(new TeamsSSOTokenExchangeMiddleware(storage, configuration["ConnectionName"]));
    
                OnTurnError = async (turnContext, exception) =>
                {
                    // Log any leaked exception from the application.
                    // NOTE: In production environment, you must consider logging this to
                    // Azure Application Insights. Visit https://learn.microsoft.com/azure/bot-service/bot-builder-telemetry?view=azure-bot-service-4.0&tabs=csharp to see how
                    // to add telemetry capture to your bot.
                    logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
    
                    // Send a message to the user.
                    await turnContext.SendActivityAsync("The bot encountered an error or bug.");
                    await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");
    
                    if (conversationState != null)
                    {
                        try
                        {
                            // Delete the conversationState for the current conversation to prevent the
                            // bot from getting stuck in a error-loop caused by being in a bad state.
                            // conversationState must be thought of as similar to "cookie-state" in a Web pages.
                            await conversationState.DeleteAsync(turnContext);
                        }
                        catch (Exception e)
                        {
                            logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
                        }
                    }
    
                    // Send a trace activity, which is displayed in the Bot Framework Emulator.
                    await turnContext.TraceActivityAsync(
                        "OnTurnError Trace",
                        exception.Message,
                        "https://www.botframework.com/schemas/error",
                        "TurnError");
                };
            }
        }
    

Se o usuário do aplicativo estiver usando o aplicativo pela primeira vez e o consentimento do usuário for necessário, a caixa de diálogo a seguir aparecerá:

Caixa de diálogo consentimento para o SSO do bot

Quando o usuário seleciona Continuar, ocorre um dos seguintes eventos:

  • Se a interface do usuário do bot tiver um botão de entrada, o fluxo de entrada para bots será ativado. Você pode determinar as permissões que exigem o consentimento do usuário do aplicativo. Use essa abordagem se seu aplicativo exigir permissões do Graph que não openidsejam .

  • Se o bot não tiver um botão de entrada no cartão OAuth, o consentimento do usuário do aplicativo será necessário para um conjunto mínimo de permissões. Esse token é útil para autenticação básica e para obter o endereço de email do usuário do aplicativo.

A caixa de diálogo de consentimento exibida é para escopos de id aberto definidos em Microsoft Entra ID. O usuário do aplicativo deve dar consentimento apenas uma vez. Após o consentimento, o usuário do aplicativo pode acessar e usar seu aplicativo bot para as permissões e escopos concedidos.

Observação

Após o consentimento do usuário do aplicativo, eles não serão obrigados a consentir novamente para quaisquer outras permissões. Se as permissões definidas em Microsoft Entra escopo forem modificadas, o usuário do aplicativo poderá precisar consentir novamente. Se, no entanto, o prompt de consentimento não permitir que o usuário do aplicativo acesse, o aplicativo bot voltará a entrar cartão.

Importante

Cenários onde as caixas de diálogo de consentimento não são necessárias:

  • Se o administrador de locatários tiver concedido consentimento em nome do locatário, os usuários do aplicativo não precisarão ser solicitados a dar consentimento. Isso significa que os usuários do aplicativo não veem as caixas de diálogo de consentimento e podem acessar o aplicativo perfeitamente.
  • Se seu aplicativo Microsoft Entra estiver registrado no mesmo locatário do qual você está solicitando uma autenticação no Teams, o usuário do aplicativo não poderá ser solicitado a consentir e receberá imediatamente um token de acesso. Os usuários do aplicativo só consentem com essas permissões se o aplicativo Microsoft Entra estiver registrado em um locatário diferente.

Se você encontrar algum erro, consulte Solucionar problemas de autenticação de SSO no Teams.

Adicionar código para receber o token

A resposta com o token é enviada por meio de uma atividade de invocação com o mesmo esquema que outras atividades de invocação que os bots recebem hoje. A única diferença é o nome de invocação, a entrada/tokenExchange e o campo de valor . O campo valor contém a ID, uma cadeia de caracteres da solicitação inicial para obter o token e o campo token, um valor de cadeia de caracteres incluindo o token.

Use o seguinte snippet de código para invocar a resposta:

public MainDialog(IConfiguration configuration, ILogger<MainDialog> logger)
            : base(nameof(MainDialog), configuration["ConnectionName"])
        {
            AddDialog(new OAuthPrompt(
                nameof(OAuthPrompt),
                new OAuthPromptSettings
                {
                    ConnectionName = ConnectionName,
                    Text = "Please Sign In",
                    Title = "Sign In",
                    Timeout = 300000, // User has 5 minutes to login (1000 * 60 * 5)
                    EndOnInvalidMessage = true
                }));

            AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));

            AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
            {
                PromptStepAsync,
                LoginStepAsync,
            }));

            // The initial child Dialog to run.
            InitialDialogId = nameof(WaterfallDialog);
        }


private async Task<DialogTurnResult> PromptStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            return await stepContext.BeginDialogAsync(nameof(OAuthPrompt), null, cancellationToken);
        }

private async Task<DialogTurnResult> LoginStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {

            var tokenResponse = (TokenResponse)stepContext.Result;
            if (tokenResponse?.Token != null)
            {
                var token = tokenResponse.Token;

                // On successful login, the token contains sign in token.
            }
            else 
            {
                await stepContext.Context.SendActivityAsync(MessageFactory.Text("Login was not successful please try again."), cancellationToken);
            }            

            return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
        }

Observação

Os snippets de código usam a Caixa de Diálogo Cascata. Para obter mais informações, consulte Sobre caixas de diálogo sobre componentes e cascatas.

Validar o token de acesso

As APIs Web no servidor devem decodificar o token de acesso e verificar se ele é enviado do cliente.

Observação

Se você usar o Bot Framework, ele manipulará a validação do token de acesso. Se você não usar o Bot Framework, siga as diretrizes fornecidas nesta seção.

Para obter mais informações sobre como validar o token de acesso, consulte Validar tokens.

Há diversas bibliotecas disponíveis que podem lidar com a validação de JWT. A validação básica inclui:

  • Verificando se o token está bem formado.
  • Verificando se o token foi emitido pela autoridade pretendida.
  • Verificando se o token está direcionado à API web.

Ao validar o token, lembre-se das seguintes diretrizes:

  • Tokens SSO válidos são emitidos por Microsoft Entra ID. A iss declaração no token deve começar com esse valor.
  • O parâmetro do aud1 token é definido como a ID do aplicativo gerada durante Microsoft Entra registro do aplicativo.
  • O parâmetro do scp token está definido como access_as_user.

Token de acesso de exemplo

O snippet de código a seguir é uma carga decodificada típica de um token de acesso:

{
    aud: "2c3caa80-93f9-425e-8b85-0745f50c0d24",
    iss: "https://login.microsoftonline.com/fec4f964-8bc9-4fac-b972-1c1da35adbcd/v2.0",
    iat: 1521143967,
    nbf: 1521143967,
    exp: 1521147867,
    aio: "ATQAy/8GAAAA0agfnU4DTJUlEqGLisMtBk5q6z+6DB+sgiRjB/Ni73q83y0B86yBHU/WFJnlMQJ8",
    azp: "e4590ed6-62b3-5102-beff-bad2292ab01c",
    azpacr: "0",
    e_exp: 262800,
    name: "Mila Nikolova",
    oid: "6467882c-fdfd-4354-a1ed-4e13f064be25",
    preferred_username: "milan@contoso.com",
    scp: "access_as_user",
    sub: "XkjgWjdmaZ-_xDmhgN1BMP2vL2YOfeVxfPT_o8GRWaw",
    tid: "fec4f964-8bc9-4fac-b972-1c1da35adbcd",
    uti: "MICAQyhrH02ov54bCtIDAA",
    ver: "2.0"
}

Manipular o logon do usuário do aplicativo

Use o seguinte snippet de código para manipular o token de acesso caso o usuário do aplicativo faça logon:

    private async Task<DialogTurnResult> InterruptAsync(DialogContext innerDc, 
    CancellationToken cancellationToken = default(CancellationToken))
        {
            if (innerDc.Context.Activity.Type == ActivityTypes.Message)
            {
                var text = innerDc.Context.Activity.Text.ToLowerInvariant();

                // Allow logout anywhere in the command.
                if (text.IndexOf("logout") >= 0)
                {
                    // The UserTokenClient encapsulates the authentication processes.
                    var userTokenClient = innerDc.Context.TurnState.Get<UserTokenClient>();
                    await userTokenClient.SignOutUserAsync(
                    innerDc.Context.Activity.From.Id, 
                    ConnectionName, 
                    innerDc.Context.Activity.ChannelId, 
                    cancellationToken
                    ).ConfigureAwait(false);

                    await innerDc.Context.SendActivityAsync(MessageFactory.Text("You have been signed out."), cancellationToken);
                    return await innerDc.CancelAllDialogsAsync(cancellationToken);
                }
            }

            return null;
        }

Exemplo de código

Nome de exemplo Descrição C# Node.js
Início rápido do SSO de conversa de bot Este código de exemplo mostra como começar a usar o SSO em um bot para o Microsoft Teams. View View

Observação

OnTeamsMessagingExtensionQueryAsync e OnTeamsAppBasedLinkQueryAsync do TeamsMessagingExtensionsSearchAuthConfigBot.cs arquivo são os únicos manipuladores SSO com suporte. Não há suporte para outros manipuladores de SSO.

Esta seção cobre:

  1. Atualizar variáveis de ambiente de desenvolvimento
  2. Adicionar código para solicitar um token
  3. Adicionar código para receber o token
  4. Adicionar token ao Bot Framework Token Store
  5. Manipular o logon do usuário do aplicativo

Atualizar variáveis de ambiente de desenvolvimento

Você configurou o segredo do cliente e a configuração de conexão OAuth para o aplicativo em Microsoft Entra ID. Você deve configurar o código do aplicativo com essas variáveis.

Para atualizar as variáveis de ambiente de desenvolvimento:

  1. Abra o projeto do aplicativo.

  2. Abra o ./env arquivo do seu projeto.

  3. Atualize as seguintes variáveis:

    • Para MicrosoftAppId, atualize a ID de registro do Bot de Microsoft Entra ID.
    • Para MicrosoftAppPassword, atualize o segredo do cliente de registro de bot.
    • Para ConnectionName, atualize o nome da conexão OAuth configurada em Microsoft Entra ID.
    • Para MicrosoftAppTenantId, atualize a ID do locatário.
  4. Salve o arquivo.

Agora você configurou as variáveis de ambiente necessárias para seu aplicativo bot e SSO. Em seguida, adicione o código para manipular tokens.

Adicionar código para solicitar um token

A solicitação para obter o token é uma solicitação de mensagem POST usando o esquema de mensagens existente. Ele está incluído nos anexos de um OAuthCard. O esquema da classe OAuthCard é definido no Microsoft Bot Schema 4.0. O Teams atualizará o token se a TokenExchangeResource propriedade for preenchida no cartão. Para o canal do Teams, somente a propriedade Id, que identifica exclusivamente uma solicitação de token, é respeitada.

Observação

O Microsoft Bot Framework OAuthPrompt ou o MultiProviderAuthDialog tem suporte para autenticação de SSO.

Para atualizar o código do aplicativo:

  1. Adicionar snippet de código para TeamsSSOTokenExchangeMiddleware.

    Adicione o snippet de código a seguir a AdapterWithErrorHandler.cs (ou a classe equivalente no código do seu aplicativo):

    base.Use(new TeamsSSOTokenExchangeMiddleware(storage, configuration["ConnectionName"]));
    

    Observação

    Você poderá receber várias respostas para uma determinada solicitação se o usuário tiver vários pontos de extremidade ativos. Você deve eliminar todas as respostas duplicadas ou redundantes com o token. Para obter mais informações sobre a entrada/tokenExchange, consulte Classe TeamsSSOTokenExchangeMiddleware.

  2. Use o snippet de código a seguir para solicitar um token.

    Depois de adicionar o AdapterWithErrorHandler.cs, o seguinte código deve aparecer:

        public class AdapterWithErrorHandler : CloudAdapter
        {
            public AdapterWithErrorHandler(
                IConfiguration configuration,
                IHttpClientFactory httpClientFactory,
                ILogger<IBotFrameworkHttpAdapter> logger,
                IStorage storage,
                ConversationState conversationState)
                : base(configuration, httpClientFactory, logger)
            {
                base.Use(new TeamsSSOTokenExchangeMiddleware(storage, configuration["ConnectionName"]));
    
                OnTurnError = async (turnContext, exception) =>
                {
                    // Log any leaked exception from the application.
                    // NOTE: In production environment, you must consider logging this to
                    // Azure Application Insights. Visit https://learn.microsoft.com/en-us/azure/bot-service/bot-builder-telemetry?view=azure-bot-service-4.0&tabs=csharp to see how
                    // to add telemetry capture to your bot.
                    logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
    
                    // Send a message to the user.
                    await turnContext.SendActivityAsync("The bot encountered an error or bug.");
                    await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");
    
                    if (conversationState != null)
                    {
                        try
                        {
                            // Delete the conversationState for the current conversation to prevent the
                            // bot from getting stuck in an error-loop caused by being in a bad state.
                            // ConversationState must be thought of as similar to "cookie-state" in a Web pages.
                            await conversationState.DeleteAsync(turnContext);
                        }
                        catch (Exception e)
                        {
                            logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
                        }
                    }
    
                    // Send a trace activity, which will be displayed in the Bot Framework Emulator.
                    await turnContext.TraceActivityAsync(
                        "OnTurnError Trace",
                        exception.Message,
                        "https://www.botframework.com/schemas/error",
                        "TurnError");
                };
            }
        }
    

Se o usuário do aplicativo estiver usando seu aplicativo pela primeira vez, ele será obrigado a consentir com a autenticação do SSO.

Autenticação SSO para aplicativo de extensão de mensagem

Quando o usuário do aplicativo seleciona o nome de usuário, a permissão é concedida e ele pode usar o aplicativo.

Autenticação SSO concluída para aplicativo de extensão de mensagem

A caixa de diálogo de consentimento exibida é para escopos de id aberto definidos em Microsoft Entra ID. O usuário do aplicativo deve dar consentimento apenas uma vez. Após o consentimento, o usuário do aplicativo pode acessar e usar seu aplicativo de extensão de mensagem para as permissões e escopos concedidos.

Importante

Cenários onde as caixas de diálogo de consentimento não são necessárias:

  • Se o administrador de locatários tiver concedido consentimento em nome do locatário, os usuários do aplicativo não precisarão ser solicitados a dar consentimento. Isso significa que os usuários do aplicativo não veem as caixas de diálogo de consentimento e podem acessar o aplicativo perfeitamente.

Se você encontrar algum erro, consulte Solucionar problemas de autenticação de SSO no Teams.

Adicionar código para receber o token

A resposta com o token é enviada por meio de uma atividade de invocação com o mesmo esquema que outras atividades de invocação que os bots recebem hoje. A única diferença é o nome de invocação, a entrada/tokenExchange e o campo de valor . O campo valor contém a ID, uma cadeia de caracteres da solicitação inicial para obter o token e o campo token, um valor de cadeia de caracteres incluindo o token.

Use o seguinte exemplo de snippet de código para invocar a resposta:

public MainDialog(IConfiguration configuration, ILogger<MainDialog> logger)
            : base(nameof(MainDialog), configuration["ConnectionName"])
        {
            AddDialog(new OAuthPrompt(
                nameof(OAuthPrompt),
                new OAuthPromptSettings
                {
                    ConnectionName = ConnectionName,
                    Text = "Please Sign In",
                    Title = "Sign In",
                    Timeout = 300000, // User has 5 minutes to login (1000 * 60 * 5)
                    EndOnInvalidMessage = true
                }));

            AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));

            AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
            {
                PromptStepAsync,
                LoginStepAsync,
            }));

            // The initial child Dialog to run.
            InitialDialogId = nameof(WaterfallDialog);
        }


private async Task<DialogTurnResult> PromptStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            return await stepContext.BeginDialogAsync(nameof(OAuthPrompt), null, cancellationToken);
        }

private async Task<DialogTurnResult> LoginStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            
            var tokenResponse = (TokenResponse)stepContext.Result;
            if (tokenResponse?.Token != null)
            {
                var token = tokenResponse.Token;

                // On successful login, the token contains sign in token.
            }
            else 
            {
                await stepContext.Context.SendActivityAsync(MessageFactory.Text("Login was not successful please try again."), cancellationToken);
            }            

            return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
        }

Observação

Os snippets de código usam o bot caixa de diálogo Cascata. Para obter mais informações sobre a caixa de diálogo Cascata, consulte Sobre caixas de diálogo sobre componentes e cascatas.

Você recebe o token no OnTeamsMessagingExtensionQueryAsync manipulador na turnContext.Activity.Value carga ou no OnTeamsAppBasedLinkQueryAsync, dependendo de qual cenário você está habilitando o SSO.

JObject valueObject=JObject.FromObject(turnContext.Activity.Value);
if(valueObject["authentication"] !=null)
 {
    JObject authenticationObject=JObject.FromObject(valueObject["authentication"]);
    if(authenticationObject["token"] !=null)
 }

Validar o token de acesso

As APIs Web no servidor devem decodificar o token de acesso e verificar se ele é enviado do cliente.

Observação

Se você usar o Bot Framework, ele manipulará a validação do token de acesso. Se você não usar o Bot Framework, siga as diretrizes nesta seção.

Para obter mais informações sobre como validar o token de acesso, consulte Validar tokens.

Há diversas bibliotecas disponíveis que podem lidar com a validação de JWT. A validação básica inclui:

  • Verificando se o token está bem formado.
  • Verificando se o token foi emitido pela autoridade pretendida.
  • Verificando se o token está direcionado à API web.

Ao validar o token, lembre-se das seguintes diretrizes:

  • Tokens SSO válidos são emitidos por Microsoft Entra ID. A iss declaração no token deve começar com esse valor.
  • O parâmetro do aud1 token é definido como a ID do aplicativo gerada durante Microsoft Entra registro do aplicativo.
  • O parâmetro do scp token está definido como access_as_user.

Token de acesso de exemplo

O snippet de código a seguir é uma carga decodificada típica de um token de acesso:

{
    aud: "2c3caa80-93f9-425e-8b85-0745f50c0d24",
    iss: "https://login.microsoftonline.com/fec4f964-8bc9-4fac-b972-1c1da35adbcd/v2.0",
    iat: 1521143967,
    nbf: 1521143967,
    exp: 1521147867,
    aio: "ATQAy/8GAAAA0agfnU4DTJUlEqGLisMtBk5q6z+6DB+sgiRjB/Ni73q83y0B86yBHU/WFJnlMQJ8",
    azp: "e4590ed6-62b3-5102-beff-bad2292ab01c",
    azpacr: "0",
    e_exp: 262800,
    name: "Mila Nikolova",
    oid: "6467882c-fdfd-4354-a1ed-4e13f064be25",
    preferred_username: "milan@contoso.com",
    scp: "access_as_user",
    sub: "XkjgWjdmaZ-_xDmhgN1BMP2vL2YOfeVxfPT_o8GRWaw",
    tid: "fec4f964-8bc9-4fac-b972-1c1da35adbcd",
    uti: "MICAQyhrH02ov54bCtIDAA",
    ver: "2.0"
}

Adicionar token ao Bot Framework Token Store

Se você estiver usando a conexão OAuth, deverá atualizar ou adicionar o token no repositório de Tokens do Bot Framework. Adicione o seguinte exemplo de snippet de código a TeamsMessagingExtensionsSearchAuthConfigBot.cs (ou o arquivo equivalente no código do aplicativo) para atualizar ou adicionar o token na loja:

Observação

Você pode encontrar o exemplo TeamsMessagingExtensionsSearchAuthConfigBot.cs no SSO de Tab, Bot e Extensão de Mensagem (ME).

protected override async Task<InvokeResponse> OnInvokeActivityAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken)
     {
         JObject valueObject = JObject.FromObject(turnContext.Activity.Value);
         if (valueObject["authentication"] != null)
         {
             JObject authenticationObject = JObject.FromObject(valueObject["authentication"]);
             if (authenticationObject["token"] != null)
             {
                 //If the token is NOT exchangeable, then return 412 to require user consent.
                 if (await TokenIsExchangeable(turnContext, cancellationToken))
                 {
                     return await base.OnInvokeActivityAsync(turnContext, cancellationToken).ConfigureAwait(false);
                 }
                 else
                 {
                     var response = new InvokeResponse();
                     response.Status = 412;
                     return response;
                 }
             }
         }
         return await base.OnInvokeActivityAsync(turnContext, cancellationToken).ConfigureAwait(false);
     }
     private async Task<bool> TokenIsExchangeable(ITurnContext turnContext, CancellationToken cancellationToken)
     {
         TokenResponse tokenExchangeResponse = null;
         try
         {
             JObject valueObject = JObject.FromObject(turnContext.Activity.Value);
             var tokenExchangeRequest =
             ((JObject)valueObject["authentication"])?.ToObject<TokenExchangeInvokeRequest>();
             var userTokenClient = turnContext.TurnState.Get<UserTokenClient>();
             tokenExchangeResponse = await userTokenClient.ExchangeTokenAsync(
                             turnContext.Activity.From.Id,
                              _connectionName,
                              turnContext.Activity.ChannelId,
                              new TokenExchangeRequest
              {
                  Token = tokenExchangeRequest.Token,
              },
               cancellationToken).ConfigureAwait(false);
         }
 #pragma warning disable CA1031 //Do not catch general exception types (ignoring, see comment below)
         catch
 #pragma warning restore CA1031 //Do not catch general exception types
         {
             //ignore exceptions.
             //if token exchange failed for any reason, tokenExchangeResponse above remains null, and a failure invoke response is sent to the caller.
             //This ensures the caller knows that the invoke has failed.
         }
         if (tokenExchangeResponse == null || string.IsNullOrEmpty(tokenExchangeResponse.Token))
         {
             return false;
         }
         return true;
     }

Manipular o logon do usuário do aplicativo

Use o seguinte snippet de código para manipular o token de acesso caso o usuário do aplicativo faça logon:

    private async Task<DialogTurnResult> InterruptAsync(DialogContext innerDc, 
    CancellationToken cancellationToken = default(CancellationToken))
        {
            if (innerDc.Context.Activity.Type == ActivityTypes.Message)
            {
                var text = innerDc.Context.Activity.Text.ToLowerInvariant();

                // Allow logout anywhere in the command.
                if (text.IndexOf("logout") >= 0)
                {
                    // The UserTokenClient encapsulates the authentication processes.
                    var userTokenClient = innerDc.Context.TurnState.Get<UserTokenClient>();
                    await userTokenClient.SignOutUserAsync(
    innerDc.Context.Activity.From.Id, 
    ConnectionName, 
    innerDc.Context.Activity.ChannelId, 
    cancellationToken
    ).ConfigureAwait(false);

                    await innerDc.Context.SendActivityAsync(MessageFactory.Text("You have been signed out."), cancellationToken);
                    return await innerDc.CancelAllDialogsAsync(cancellationToken);
                }
            }

            return null;
        }

Exemplo de código

Esta seção fornece o exemplo de SDK de autenticação de bot v3.

Nome de exemplo Descrição .NET Node.js Python Manifesto
Autenticação de bot Este exemplo mostra como começar a usar a autenticação em um bot para o Teams. View View View View
SSO de guia, bot e extensão de mensagem (ME) Este exemplo mostra o SSO para a extensão de guia, bot e mensagem – pesquisa, ação, unfurl de link. View Exibir NA Exibir
Guia, bot e extensão de mensagem Este exemplo mostra como marcar autenticação no bot, na guia e na extensão de mensagens com o SSO View View NA Exibir

Próxima etapa