Compartir a través de


Adición de código para habilitar el inicio de sesión único en la aplicación bot

Antes de agregar código para habilitar el inicio de sesión único (SSO), asegúrese de que ha configurado la aplicación y el recurso del bot en Microsoft Entra centro de administración.

Debe configurar el código de la aplicación para obtener un token de acceso de Microsoft Entra id. El token de acceso se emite en nombre de la aplicación bot.

Nota:

Si ha creado la aplicación de Teams con Microsoft Teams Toolkit, puede habilitar el inicio de sesión único para la aplicación mediante las instrucciones del módulo Herramientas y SDK. Para obtener más información, consulte Agregar inicio de sesión único a la aplicación Teams. Teams Toolkit admite el inicio de sesión único para aplicaciones de JavaScript y TypeScript en Visual Studio Code y en la versión preliminar 3 del kit de herramientas de Teams 17.4 para aplicaciones de C#.

En esta sección se describen estos temas:

  1. Actualización de variables de entorno de desarrollo
  2. Adición de código para controlar un token de acceso
  3. Agregar código para recibir el token
  4. Controlar el cierre de sesión del usuario de la aplicación

Actualización de variables de entorno de desarrollo

Ha configurado el secreto de cliente y la configuración de conexión de OAuth para la aplicación en Microsoft Entra identificador. Debe configurar el código con estos valores.

Para actualizar las variables de entorno de desarrollo:

  1. Abra el proyecto de aplicación del bot.

  2. Abra el archivo de entorno del proyecto.

  3. Actualice las siguientes variables:

    • Para MicrosoftAppId, actualice el identificador del bot desde Microsoft Entra id.
    • Para MicrosoftAppPassword, actualice el secreto de cliente.
    • Para ConnectionName, actualice el nombre de la conexión de OAuth que configuró en Microsoft Entra identificador.
    • Para MicrosoftAppTenantId, actualice el identificador de inquilino.
  4. Guarde el archivo.

Ahora ha configurado las variables de entorno necesarias para la aplicación de bot y el inicio de sesión único. A continuación, agregue el código para controlar los tokens de bot.

Adición de código para controlar un token de acceso

La solicitud para obtener el token es una solicitud de mensaje POST mediante el esquema de mensaje existente. Se incluye en los datos adjuntos de OAuthCard. El esquema de la clase OAuthCard se define en Microsoft Bot Schema 4.0. Teams actualiza el token si la TokenExchangeResource propiedad se rellena en la tarjeta. Para los canales de Microsoft Teams, solo se respeta la propiedad Id, que identifica de forma única una solicitud de token.

Nota:

El Microsoft Bot Framework OAuthPrompt o MultiProviderAuthDialog es compatible con la autenticación de inicio de sesión único.

Para actualizar el código de la aplicación:

  1. Agregue el fragmento de código para TeamsSSOTokenExchangeMiddleware.

    Agregue el siguiente fragmento de código a (o la AdapterWithErrorHandler.cs clase equivalente en el código de la aplicación):

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

    Nota:

    Puede recibir varias respuestas para una solicitud determinada si el usuario tiene varios puntos de conexión activos. Debe eliminar todas las respuestas duplicadas o redundantes con el token. Para obtener más información sobre signin/tokenExchange, vea TeamsSSOTokenExchangeMiddleware (Clase).

  2. Use el siguiente fragmento de código para solicitar un token.

    Después de agregar AdapterWithErrorHandler.cs, debe aparecer el código siguiente:

        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");
                };
            }
        }
    

Si el usuario de la aplicación usa la aplicación por primera vez y se requiere el consentimiento del usuario, aparece el siguiente cuadro de diálogo:

Cuadro de diálogo consentimiento para el inicio de sesión único del bot

Cuando el usuario selecciona Continuar, se produce uno de los siguientes eventos:

  • Si la interfaz de usuario del bot tiene un botón de inicio de sesión, se activa el flujo de inicio de sesión de los bots. Puede determinar los permisos que requieren el consentimiento del usuario de la aplicación. Use este enfoque si la aplicación requiere permisos de Graph distintos de openid.

  • Si el bot no tiene un botón de inicio de sesión en la tarjeta de OAuth, se requiere el consentimiento del usuario de la aplicación para un conjunto mínimo de permisos. Este token es útil para la autenticación básica y para obtener la dirección de correo electrónico del usuario de la aplicación.

El cuadro de diálogo de consentimiento que aparece es para los ámbitos de id. abierto definidos en Microsoft Entra id. El usuario de la aplicación solo debe dar su consentimiento una vez. Después de dar su consentimiento, el usuario de la aplicación puede acceder a la aplicación de bot y usarla para los permisos y ámbitos concedidos.

Nota:

Una vez que el usuario de la aplicación da su consentimiento, no es necesario que vuelva a dar su consentimiento para ningún otro permiso. Si se modifican los permisos definidos en Microsoft Entra ámbito, es posible que el usuario de la aplicación tenga que dar su consentimiento de nuevo. Sin embargo, si el símbolo del consentimiento no permite que el usuario de la aplicación acceda, la aplicación bot vuelve a la tarjeta de inicio de sesión.

Importante

Escenarios en los que no se necesitan cuadros de diálogo de consentimiento:

  • Si el administrador de inquilinos ha concedido el consentimiento en nombre del inquilino, no es necesario solicitar consentimiento a los usuarios de la aplicación. Esto significa que los usuarios de la aplicación no ven los diálogos de consentimiento y pueden acceder a la aplicación sin problemas.
  • Si la aplicación de Microsoft Entra está registrada en el mismo inquilino desde el que solicita una autenticación en Teams, no se puede pedir al usuario de la aplicación que dé su consentimiento y se le conceda un token de acceso de inmediato. Los usuarios de la aplicación dan su consentimiento a estos permisos solo si la aplicación de Microsoft Entra está registrada en un inquilino diferente.

Si encuentra algún error, consulte Solución de problemas de autenticación de SSO en Teams.

Agregar código para recibir el token

La respuesta con el token se envía a través de una actividad de invocación con el mismo esquema que otras actividades de invocación que los bots reciben hoy en día. La única diferencia es el nombre de invocación, el inicio de sesión o tokenExchange y el campo de valor . El campo valor contiene el identificador, una cadena de la solicitud inicial para obtener el token y el campo token, un valor de cadena que incluye el token.

Use el siguiente fragmento de código para invocar la respuesta:

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);
        }

Nota:

Los fragmentos de código usan el cuadro de diálogo Cascada. Para obtener más información, vea Acerca de los diálogos de componente y cascada.

Validar el token de acceso

Las API web del servidor deben descodificar el token de acceso y comprobar si se envían desde el cliente.

Nota:

Si usa Bot Framework, controla la validación del token de acceso. Si no usa Bot Framework, siga las instrucciones que se indican en esta sección.

Para obtener más información sobre cómo validar el token de acceso, consulte Validación de tokens.

Hay muchas bibliotecas disponibles que pueden encargarse de la validación JWT. La validación básica incluye:

  • Comprobación de que el token está bien formado.
  • Comprobación de que el token fue emitido por la autoridad prevista.
  • Comprobación de que el token está destinado a la API web.

Tenga en cuenta las siguientes instrucciones para validar el token:

  • Los tokens de SSO válidos se emiten mediante Microsoft Entra identificador. La iss notificación del token debe comenzar con este valor.
  • El parámetro del aud1 token se establece en el identificador de aplicación generado durante Microsoft Entra registro de la aplicación.
  • El parámetro del scp token se establece en access_as_user.

Ejemplo de token de acceso

El siguiente fragmento de código es una carga descodificada típica de un token de acceso:

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

Controlar el cierre de sesión del usuario de la aplicación

Use el siguiente fragmento de código para controlar el token de acceso en caso de que el usuario de la aplicación se registre:

    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;
        }

Ejemplo de código

Ejemplo de nombre Descripción C# Node.js
Inicio rápido del inicio rápido de bot conversation SSO En este código de ejemplo se muestra cómo empezar a usar sso en un bot para Microsoft Teams. View View

Nota:

OnTeamsMessagingExtensionQueryAsync y OnTeamsAppBasedLinkQueryAsync desde el TeamsMessagingExtensionsSearchAuthConfigBot.cs archivo son los únicos controladores de SSO que se admiten. No se admiten otros controladores de SSO.

En esta sección se describen estos temas:

  1. Actualización de variables de entorno de desarrollo
  2. Agregar código para solicitar un token
  3. Agregar código para recibir el token
  4. Adición de un token al almacén de tokens de Bot Framework
  5. Controlar el cierre de sesión del usuario de la aplicación

Actualización de variables de entorno de desarrollo

Ha configurado el secreto de cliente y la configuración de conexión de OAuth para la aplicación en Microsoft Entra identificador. Debe configurar el código de la aplicación con estas variables.

Para actualizar las variables de entorno de desarrollo:

  1. Abra el proyecto de aplicación.

  2. Abra el ./env archivo del proyecto.

  3. Actualice las siguientes variables:

    • Para MicrosoftAppId, actualice el identificador de registro del bot desde Microsoft Entra id.
    • Para MicrosoftAppPassword, actualice el secreto de cliente de registro de bots.
    • Para ConnectionName, actualice el nombre de la conexión de OAuth que configuró en Microsoft Entra identificador.
    • Para MicrosoftAppTenantId, actualice el identificador de inquilino.
  4. Guarde el archivo.

Ahora ha configurado las variables de entorno necesarias para la aplicación de bot y el inicio de sesión único. A continuación, agregue el código para controlar tokens.

Agregar código para solicitar un token

La solicitud para obtener el token es una solicitud de mensaje POST mediante el esquema de mensaje existente. Se incluye en los datos adjuntos de OAuthCard. El esquema de la clase OAuthCard se define en Microsoft Bot Schema 4.0. Teams actualiza el token si la TokenExchangeResource propiedad se rellena en la tarjeta. Para los canales de Microsoft Teams, solo se respeta la propiedad Id, que identifica de forma única una solicitud de token.

Nota:

El Microsoft Bot Framework OAuthPrompt o MultiProviderAuthDialog es compatible con la autenticación de inicio de sesión único.

Para actualizar el código de la aplicación:

  1. Agregue el fragmento de código para TeamsSSOTokenExchangeMiddleware.

    Agregue el siguiente fragmento de código a (o la AdapterWithErrorHandler.cs clase equivalente en el código de la aplicación):

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

    Nota:

    Puede recibir varias respuestas para una solicitud determinada si el usuario tiene varios puntos de conexión activos. Debe eliminar todas las respuestas duplicadas o redundantes con el token. Para obtener más información sobre signin/tokenExchange, vea TeamsSSOTokenExchangeMiddleware (Clase).

  2. Use el siguiente fragmento de código para solicitar un token.

    Después de agregar AdapterWithErrorHandler.cs, debe aparecer el código siguiente:

        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");
                };
            }
        }
    

Si el usuario de la aplicación usa la aplicación por primera vez, se le pedirá que dé su consentimiento para la autenticación sso.

Autenticación de SSO para la aplicación de extensión de mensaje

Cuando el usuario de la aplicación selecciona el nombre de usuario, se concede el permiso y puede usar la aplicación.

Autenticación de SSO completada para la aplicación de extensión de mensaje

El cuadro de diálogo de consentimiento que aparece es para los ámbitos de id. abierto definidos en Microsoft Entra id. El usuario de la aplicación solo debe dar su consentimiento una vez. Después de dar su consentimiento, el usuario de la aplicación puede acceder a la aplicación de extensión de mensajes y usarla para los permisos y ámbitos concedidos.

Importante

Escenarios en los que no se necesitan cuadros de diálogo de consentimiento:

  • Si el administrador de inquilinos ha concedido el consentimiento en nombre del inquilino, no es necesario solicitar consentimiento a los usuarios de la aplicación. Esto significa que los usuarios de la aplicación no ven los diálogos de consentimiento y pueden acceder a la aplicación sin problemas.

Si encuentra algún error, consulte Solución de problemas de autenticación de SSO en Teams.

Agregar código para recibir el token

La respuesta con el token se envía a través de una actividad de invocación con el mismo esquema que otras actividades de invocación que los bots reciben hoy en día. La única diferencia es el nombre de invocación, el inicio de sesión o tokenExchange y el campo de valor . El campo valor contiene el identificador, una cadena de la solicitud inicial para obtener el token y el campo token, un valor de cadena que incluye el token.

Use el siguiente ejemplo de fragmento de código para invocar la respuesta:

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);
        }

Nota:

Los fragmentos de código usan el bot De diálogo de cascada. Para obtener más información sobre el cuadro de diálogo Cascada, vea Acerca de los diálogos de componentes y cascadas.

Recibirá el token en OnTeamsMessagingExtensionQueryAsync el controlador en la turnContext.Activity.Value carga o en OnTeamsAppBasedLinkQueryAsync, en función del escenario para el que va a habilitar el inicio de sesión único.

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

Validar el token de acceso

Las API web del servidor deben descodificar el token de acceso y comprobar si se envían desde el cliente.

Nota:

Si usa Bot Framework, controla la validación del token de acceso. Si no usa Bot Framework, siga las instrucciones de esta sección.

Para obtener más información sobre cómo validar el token de acceso, consulte Validación de tokens.

Hay muchas bibliotecas disponibles que pueden encargarse de la validación JWT. La validación básica incluye:

  • Comprobación de que el token está bien formado.
  • Comprobación de que el token fue emitido por la autoridad prevista.
  • Comprobación de que el token está destinado a la API web.

Tenga en cuenta las siguientes instrucciones para validar el token:

  • Los tokens de SSO válidos se emiten mediante Microsoft Entra identificador. La iss notificación del token debe comenzar con este valor.
  • El parámetro del aud1 token se establece en el identificador de aplicación generado durante Microsoft Entra registro de la aplicación.
  • El parámetro del scp token se establece en access_as_user.

Ejemplo de token de acceso

El siguiente fragmento de código es una carga descodificada típica de un token de acceso:

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

Adición de un token al almacén de tokens de Bot Framework

Si usa la conexión de OAuth, debe actualizar o agregar el token en el almacén de tokens de Bot Framework. Agregue el siguiente ejemplo de fragmento de código a TeamsMessagingExtensionsSearchAuthConfigBot.cs (o al archivo equivalente en el código de la aplicación) para actualizar o agregar el token en el almacén:

Nota:

Puede encontrar el ejemplo TeamsMessagingExtensionsSearchAuthConfigBot.cs en Inicio de sesión único de Tab, Bot y Extensión de mensaje (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;
     }

Controlar el cierre de sesión del usuario de la aplicación

Use el siguiente fragmento de código para controlar el token de acceso en caso de que el usuario de la aplicación se registre:

    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;
        }

Ejemplo de código

En esta sección se proporciona el ejemplo del SDK de autenticación de bot v3.

Ejemplo de nombre Descripción .NET Node.js Python Manifiesto
Autenticación del bot En este ejemplo se muestra cómo empezar a usar la autenticación en un bot para Teams. View View View View
Inicio de sesión único de pestaña, bot y extensión de mensaje (ME) En este ejemplo se muestra el inicio de sesión único para la pestaña, el bot y la extensión de mensaje: búsqueda, acción, desenlazclar vínculo. View Ver ND Ver
Pestaña, bot y extensión de mensaje En este ejemplo se muestra cómo comprobar la autenticación en la extensión bot, tab y message con SSO View Ver ND View

Paso siguiente