Partilhar via


Adicionar código para ativar o SSO na sua aplicação de bot

Antes de adicionar código para ativar o início de sessão único (SSO), certifique-se de que configurou o recurso de aplicação e bot no centro de administração do Microsoft Entra.

Tem de configurar o código da sua aplicação para obter um token de acesso a partir do Microsoft Entra ID. O token de acesso é emitido em nome da aplicação de bot.

Observação

Se criou a sua aplicação teams com o Microsoft Teams Toolkit, pode ativar o SSO para a sua aplicação com as instruções no módulo Ferramentas e SDKs. Para obter mais informações, consulte Adicionar início de sessão único à aplicação Teams. O Teams Toolkit suporta o SSO para aplicações JavaScript e TypeScript no Visual Studio Code e no Teams Toolkit 17.4 preview 3 para aplicações C#.

Esta seção cobre:

  1. Atualizar variáveis de ambiente de desenvolvimento
  2. Adicionar código para processar um token de acesso
  3. Adicionar código para receber o token
  4. Processar o início de sessão do utilizador da aplicação

Atualizar variáveis de ambiente de desenvolvimento

Configurou o segredo do cliente e a definição de ligação OAuth para a aplicação no Microsoft Entra ID. Tem de configurar o código com estes valores.

Para atualizar as variáveis de ambiente de desenvolvimento:

  1. Abra o projeto da aplicação de bot.

  2. Abra o ficheiro de ambiente do projeto.

  3. Atualize as seguintes variáveis:

    • Para MicrosoftAppId, atualize o ID do bot a partir do Microsoft Entra ID.
    • Para MicrosoftAppPassword, atualize o segredo do cliente.
    • Para ConnectionName, atualize o nome da ligação OAuth que configurou no Microsoft Entra ID.
    • Para MicrosoftAppTenantId, atualize o ID do inquilino.
  4. Salve o arquivo.

Configurou agora as variáveis de ambiente necessárias para a aplicação bot e o SSO. Em seguida, adicione o código para processar tokens de bot.

Adicionar código para processar um token de acesso

O pedido para obter o token é um pedido de mensagem POST com o esquema de mensagem existente. Ele está incluído nos anexos de um OAuthCard. O esquema da classe OAuthCard é definido no Microsoft Bot Schema 4.0. O Teams atualiza o token se a TokenExchangeResource propriedade estiver 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 da sua aplicação:

  1. Adicionar fragmento de código para TeamsSSOTokenExchangeMiddleware.

    Adicione o seguinte fragmento de código a (ou à AdapterWithErrorHandler.cs classe equivalente no código da sua aplicação):

    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. Tem de eliminar todas as respostas duplicadas ou redundantes com o token. Para obter mais informações sobre o início de sessão/tokenExchange, veja TeamsSSOTokenExchangeMiddleware Class (Classe TeamsSSOTokenExchangeMiddleware).

  2. Utilize o seguinte fragmento de código para pedir um token.

    Depois de adicionar o AdapterWithErrorHandler.cs, tem de ser apresentado o seguinte código:

        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 utilizador da aplicação estiver a utilizar a aplicação pela primeira vez e for necessário o consentimento do utilizador, será apresentada a seguinte caixa de diálogo:

Caixa de diálogo Consentimento do SSO do bot

Quando o utilizador seleciona Continuar, ocorre um dos seguintes eventos:

  • Se a IU do bot tiver um botão de início de sessão, o fluxo de início de sessão para bots é ativado. Pode determinar as permissões que requerem o consentimento do utilizador da aplicação. Utilize esta abordagem se a sua aplicação necessitar de permissões do Graph diferentes de openid.

  • Se o bot não tiver um botão de início de sessão no cartão OAuth, o consentimento do utilizador da aplicação é necessário para um conjunto mínimo de permissões. Este token é útil para autenticação básica e para obter o endereço de e-mail do utilizador da aplicação.

A caixa de diálogo de consentimento apresentada destina-se a âmbitos open-id definidos no ID do Microsoft Entra. O usuário do aplicativo deve dar consentimento apenas uma vez. Após o consentimento, o utilizador da aplicação pode aceder e utilizar a aplicação bot para obter as permissões e âmbitos concedidos.

Observação

Após o consentimento do utilizador da aplicação, não é necessário dar novamente consentimento para quaisquer outras permissões. Se as permissões definidas no âmbito do Microsoft Entra forem modificadas, o utilizador da aplicação poderá ter de consentir novamente. No entanto, se o pedido de consentimento não permitir que o utilizador da aplicação aceda, a aplicação de bot volta ao cartão de início de sessã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. Isto significa que os utilizadores da aplicação não veem as caixas de diálogo de consentimento e podem aceder à aplicação de forma totalmente integrada.
  • Se a sua aplicação Microsoft Entra estiver registada no mesmo inquilino a partir do qual está a pedir uma autenticação no Teams, o utilizador da aplicação não pode ser convidado a consentir e é-lhe concedido imediatamente um token de acesso. Os utilizadores da aplicação só consentem estas permissões se a aplicação Microsoft Entra estiver registada num inquilino diferente.

Se encontrar erros, veja Resolver 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 da invocação, o início de sessão/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.

Utilize o seguinte fragmento 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 fragmentos de código utilizam a Caixa de Diálogo de Cascata. Para obter mais informações, veja Acerca das caixas de diálogo sobre componentes e cascata.

Validar o token de acesso

As APIs Web no servidor têm de descodificar o token de acesso e verificar se foram enviadas do cliente.

Observação

Se utilizar o Bot Framework, este processa a validação do token de acesso. Se não utilizar o Bot Framework, siga as diretrizes indicadas nesta secção.

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

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

  • Verificar se o token está bem formado.
  • Verificar se o token foi emitido pela autoridade pretendida.
  • Verificar se o token está direcionado para a API Web.

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

  • Os tokens de SSO válidos são emitidos pelo ID do Microsoft Entra. A iss afirmação no token tem de começar com este valor.
  • O parâmetro do token está definido como o ID da aplicação gerado durante o registo da aud1 aplicação Microsoft Entra.
  • O parâmetro do scp token está definido como access_as_user.

Token de acesso de exemplo

O fragmento de código seguinte é um payload normal descodificado 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"
}

Processar o início de sessão do utilizador da aplicação

Utilize o seguinte fragmento de código para processar o token de acesso, caso o utilizador da aplicação termine a sessão:

    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ção do bot Este código de exemplo mostra como começar a utilizar o SSO num bot para o Microsoft Teams. View View

Observação

OnTeamsMessagingExtensionQueryAsync e OnTeamsAppBasedLinkQueryAsync do TeamsMessagingExtensionsSearchAuthConfigBot.cs ficheiro são os únicos processadores de SSO suportados. Outros processadores de SSO não são suportados.

Esta seção cobre:

  1. Atualizar variáveis de ambiente de desenvolvimento
  2. Adicionar código para pedir um token
  3. Adicionar código para receber o token
  4. Adicionar token ao Arquivo de Tokens do Bot Framework
  5. Processar o início de sessão do utilizador da aplicação

Atualizar variáveis de ambiente de desenvolvimento

Configurou o segredo do cliente e a definição de ligação OAuth para a aplicação no Microsoft Entra ID. Tem de configurar o código da aplicação com estas variáveis.

Para atualizar as variáveis de ambiente de desenvolvimento:

  1. Abra o projeto da aplicação.

  2. Abra o ./env ficheiro do projeto.

  3. Atualize as seguintes variáveis:

    • Para MicrosoftAppId, atualize o ID de registo do Bot a partir do ID do Microsoft Entra.
    • Para MicrosoftAppPassword, atualize o segredo do cliente de registo do Bot.
    • Para ConnectionName, atualize o nome da ligação OAuth que configurou no Microsoft Entra ID.
    • Para MicrosoftAppTenantId, atualize o ID do inquilino.
  4. Salve o arquivo.

Configurou agora as variáveis de ambiente necessárias para a aplicação bot e o SSO. Em seguida, adicione o código para processar tokens.

Adicionar código para pedir um token

O pedido para obter o token é um pedido de mensagem POST com o esquema de mensagem existente. Ele está incluído nos anexos de um OAuthCard. O esquema da classe OAuthCard é definido no Microsoft Bot Schema 4.0. O Teams atualiza o token se a TokenExchangeResource propriedade estiver 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 da sua aplicação:

  1. Adicionar fragmento de código para TeamsSSOTokenExchangeMiddleware.

    Adicione o seguinte fragmento de código a (ou à AdapterWithErrorHandler.cs classe equivalente no código da sua aplicação):

    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. Tem de eliminar todas as respostas duplicadas ou redundantes com o token. Para obter mais informações sobre o início de sessão/tokenExchange, veja TeamsSSOTokenExchangeMiddleware Class (Classe TeamsSSOTokenExchangeMiddleware).

  2. Utilize o seguinte fragmento de código para pedir um token.

    Depois de adicionar o AdapterWithErrorHandler.cs, tem de ser apresentado o seguinte código:

        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 utilizador da aplicação estiver a utilizar a sua aplicação pela primeira vez, terá de consentir a autenticação SSO.

Autenticação SSO para a aplicação de extensão de mensagem

Quando o utilizador da aplicação seleciona o nome de utilizador, a permissão é concedida e pode utilizar a aplicação.

Autenticação SSO concluída para a aplicação de extensão de mensagens

A caixa de diálogo de consentimento apresentada destina-se a âmbitos open-id definidos no ID do Microsoft Entra. O usuário do aplicativo deve dar consentimento apenas uma vez. Após o consentimento, o utilizador da aplicação pode aceder e utilizar a sua aplicação de extensão de mensagem para as permissões e âmbitos 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. Isto significa que os utilizadores da aplicação não veem as caixas de diálogo de consentimento e podem aceder à aplicação de forma totalmente integrada.

Se encontrar erros, veja Resolver 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 da invocação, o início de sessão/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.

Utilize o seguinte exemplo de fragmento 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 fragmentos de código utilizam o bot de Caixa de Diálogo cascata. Para obter mais informações sobre a Caixa de Diálogo de Cascata, consulte Acerca do componente e das caixas de diálogo de cascata.

Recebe o token no OnTeamsMessagingExtensionQueryAsync processador no turnContext.Activity.Value payload ou no , consoante o cenário para o OnTeamsAppBasedLinkQueryAsyncqual está a ativar 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 têm de descodificar o token de acesso e verificar se foram enviadas do cliente.

Observação

Se utilizar o Bot Framework, este processa a validação do token de acesso. Se não utilizar o Bot Framework, siga as diretrizes nesta secção.

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

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

  • Verificar se o token está bem formado.
  • Verificar se o token foi emitido pela autoridade pretendida.
  • Verificar se o token está direcionado para a API Web.

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

  • Os tokens de SSO válidos são emitidos pelo ID do Microsoft Entra. A iss afirmação no token tem de começar com este valor.
  • O parâmetro do token está definido como o ID da aplicação gerado durante o registo da aud1 aplicação Microsoft Entra.
  • O parâmetro do scp token está definido como access_as_user.

Token de acesso de exemplo

O fragmento de código seguinte é um payload normal descodificado 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 Arquivo de Tokens do Bot Framework

Se estiver a utilizar a ligação OAuth, tem de atualizar ou adicionar o token no arquivo de Tokens do Bot Framework. Adicione o seguinte exemplo de fragmento de código a TeamsMessagingExtensionsSearchAuthConfigBot.cs (ou ao ficheiro equivalente no código da aplicação) para atualizar ou adicionar o token no arquivo:

Observação

Pode encontrar o exemplo TeamsMessagingExtensionsSearchAuthConfigBot.cs no SSO de Tecla de Tabulação, Bot e Extensão de Mensagens (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;
     }

Processar o início de sessão do utilizador da aplicação

Utilize o seguinte fragmento de código para processar o token de acesso, caso o utilizador da aplicação termine a sessão:

    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 secção fornece o exemplo do SDK v3 de autenticação do bot.

Nome de exemplo Descrição .NET Node.js Python Manifesto
Autenticação de bot Este exemplo mostra como começar a utilizar a autenticação num bot para o Teams. View View View View
SSO da Tecla de Tabulação, bot e Extensão de mensagem (ME) Este exemplo mostra o SSO para a extensão de tabulação, bot e mensagem – pesquisa, ação, unfurl de ligação. View View NA View
Separador, bot e extensão mensagem Este exemplo mostra como verificar a autenticação no bot, no separador e na extensão de mensagens com o SSO View View NA View

Próxima etapa