Ajouter du code pour activer l’authentification unique dans votre application bot

Avant d’ajouter du code pour activer l’authentification unique (SSO), vérifiez que vous avez configuré votre application et votre ressource de bot dans Microsoft Entra centre d’administration.

Vous devez configurer le code de votre application pour obtenir un jeton d’accès à partir de Microsoft Entra ID. Le jeton d’accès est émis au nom de l’application bot.

Remarque

Si vous avez créé votre application Teams à l’aide du Kit de ressources Microsoft Teams, vous pouvez activer l’authentification unique pour votre application en suivant les instructions du module Outils et kits de développement logiciel (SDK). Pour plus d’informations, consultez Ajouter l’authentification unique à l’application Teams. Teams Toolkit prend en charge l’authentification unique pour les applications JavaScript et TypeScript dans Visual Studio Code et dans Teams Toolkit 17.4 preview 3 pour les applications C#.

Cette section traite des sujets suivants :

  1. Mettre à jour les variables d’environnement de développement
  2. Ajouter du code pour gérer un jeton d’accès
  3. Ajouter du code pour recevoir le jeton
  4. Gérer la déconnexion de l’utilisateur de l’application

Mettre à jour les variables d’environnement de développement

Vous avez configuré la clé secrète client et le paramètre de connexion OAuth pour l’application dans Microsoft Entra ID. Vous devez configurer le code avec ces valeurs.

Pour mettre à jour les variables d’environnement de développement :

  1. Ouvrez le projet d’application de bot.

  2. Ouvrez le fichier d’environnement de votre projet.

  3. Mettez à jour les variables suivantes :

    • Pour MicrosoftAppId, mettez à jour l’ID du bot à partir de Microsoft Entra ID.
    • Pour MicrosoftAppPassword, mettez à jour la clé secrète client.
    • Pour ConnectionName, mettez à jour le nom de la connexion OAuth que vous avez configurée dans Microsoft Entra ID.
    • Pour MicrosoftAppTenantId, mettez à jour l’ID de locataire.
  4. Enregistrez le fichier.

Vous avez maintenant configuré les variables d’environnement requises pour votre application bot et l’authentification unique. Ensuite, ajoutez le code pour gérer les jetons de bot.

Ajouter du code pour gérer un jeton d’accès

La demande d’obtention du jeton est une demande de message POST utilisant le schéma de message existant. Il est inclus dans les pièces jointes d'une carte OAuthCard. Le schéma de la classe OAuthCard est défini dans Microsoft Bot Schema 4.0. Teams actualise le jeton si la TokenExchangeResource propriété est remplie sur le carte. Pour le canal Teams, seule laId propriété, qui identifie de manière unique une demande de jeton, est honorée.

Remarque

Le Microsoft Bot Framework OAuthPrompt ou MultiProviderAuthDialog est pris en charge pour l’authentification unique.

Pour mettre à jour le code de votre application :

  1. Ajoutez un extrait de code pour TeamsSSOTokenExchangeMiddleware.

    Ajoutez l’extrait de code suivant à AdapterWithErrorHandler.cs (ou la classe équivalente dans le code de votre application) :

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

    Remarque

    Vous pouvez recevoir plusieurs réponses pour une requête donnée si l’utilisateur a plusieurs points de terminaison actifs. Vous devez éliminer toutes les réponses dupliquées ou redondantes avec le jeton. Pour plus d’informations sur signin/tokenExchange, consultez TeamsSSOTokenExchangeMiddleware, classe.

  2. Utilisez l’extrait de code suivant pour demander un jeton.

    Une fois que vous avez ajouté le AdapterWithErrorHandler.cs, le code suivant doit apparaître :

        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 l’utilisateur de l’application utilise l’application pour la première fois et que le consentement de l’utilisateur est requis, la boîte de dialogue suivante s’affiche :

Boîte de dialogue de consentement pour l’authentification unique du bot

Lorsque l’utilisateur sélectionne Continuer, l’un des événements suivants se produit :

  • Si l’interface utilisateur du bot dispose d’un bouton de connexion, le flux de connexion pour les bots est activé. Vous pouvez déterminer les autorisations qui nécessitent le consentement de l’utilisateur de l’application. Utilisez cette approche si votre application nécessite des autorisations Graph autres que openid.

  • Si le bot n’a pas de bouton de connexion sur le carte OAuth, le consentement de l’utilisateur de l’application est requis pour un ensemble minimal d’autorisations. Ce jeton est utile pour l’authentification de base et pour obtenir l’adresse e-mail de l’utilisateur de l’application.

La boîte de dialogue de consentement qui s’affiche concerne les étendues open-ID définies dans Microsoft Entra ID. L’utilisateur de l’application ne doit donner son consentement qu’une seule fois. Après avoir donné son consentement, l’utilisateur de l’application peut accéder à votre application bot et l’utiliser pour les autorisations et étendues accordées.

Remarque

Une fois que l’utilisateur de l’application a donné son consentement, il n’est plus tenu de donner son consentement pour d’autres autorisations. Si les autorisations définies dans Microsoft Entra’étendue sont modifiées, l’utilisateur de l’application peut avoir besoin de donner son consentement à nouveau. Toutefois, si l’invite de consentement ne permet pas à l’utilisateur d’accéder à l’application, l’application bot revient à se connecter carte.

Importante

Scénarios où les dialogues de consentement ne sont pas nécessaires :

  • Si l’administrateur client a donné son consentement pour le compte du locataire, les utilisateurs de l’application n’ont pas besoin d’être invités à donner leur consentement. Cela signifie que les utilisateurs de l’application ne voient pas les boîtes de dialogue de consentement et peuvent accéder à l’application en toute transparence.
  • Si votre application Microsoft Entra est inscrite dans le locataire auprès duquel vous demandez une authentification dans Teams, l’utilisateur de l’application ne peut pas être invité à donner son consentement et un jeton d’accès est immédiatement accordé. Les utilisateurs de l’application acceptent ces autorisations uniquement si l’application Microsoft Entra est inscrite dans un autre locataire.

Si vous rencontrez des erreurs, consultez Résoudre les problèmes d’authentification unique dans Teams.

Ajouter du code pour recevoir le jeton

La réponse avec le jeton est envoyée par le biais d’une activité d’appel avec le même schéma que les autres activités d’appel que les bots reçoivent aujourd’hui. La seule différence est le nom de l’appel, la connexion/tokenExchange et le champ de valeur . Le champ valeur contient l’ID, une chaîne de la requête initiale pour obtenir le jeton et le champ de jeton , une valeur de chaîne incluant le jeton.

Utilisez l’extrait de code suivant pour appeler la réponse :

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

Remarque

Les extraits de code utilisent la boîte de dialogue Cascade. Pour plus d’informations, consultez À propos des dialogues de composant et de cascade.

Valider le jeton d’accès

Les API web sur votre serveur doivent décoder le jeton d’accès et vérifier s’il est envoyé à partir du client.

Remarque

Si vous utilisez Bot Framework, il gère la validation du jeton d’accès. Si vous n’utilisez pas Bot Framework, suivez les instructions fournies dans cette section.

Pour plus d’informations sur la validation du jeton d’accès, consultez Valider les jetons.

Il existe un certain nombre de bibliothèques disponibles qui peuvent gérer la validation JWT. La validation de base inclut :

  • Vérification que le jeton est bien formé.
  • Vérification que le jeton a été émis par l’autorité prévue.
  • Vérification que le jeton est ciblé sur l’API web.

Suivez les recommandations suivantes quand vous validez le jeton :

  • Les jetons d’authentification unique valides sont émis par l’ID Microsoft Entra. La iss revendication dans le jeton doit commencer par cette valeur.
  • Le paramètre du aud1 jeton est défini sur l’ID d’application généré lors de Microsoft Entra’inscription de l’application.
  • Le paramètre du scp jeton est défini sur access_as_user.

Exemple de token

L’extrait de code suivant est une charge utile décodée classique d’un jeton d’accès :

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

Gérer la déconnexion de l’utilisateur de l’application

Utilisez l’extrait de code suivant pour gérer le jeton d’accès au cas où l’utilisateur de l’application se déconnecte :

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

Exemple de code

Exemple de nom Description C# Node.js
Démarrage rapide de l’authentification unique de conversation de bot Cet exemple de code montre comment bien démarrer avec l’authentification unique dans un bot pour Microsoft Teams. View View

Remarque

OnTeamsMessagingExtensionQueryAsync et OnTeamsAppBasedLinkQueryAsync du TeamsMessagingExtensionsSearchAuthConfigBot.cs fichier sont les seuls gestionnaires d’authentification unique pris en charge. Les autres gestionnaires d’authentification unique ne sont pas pris en charge.

Cette section traite des sujets suivants :

  1. Mettre à jour les variables d’environnement de développement
  2. Ajouter du code pour demander un jeton
  3. Ajouter du code pour recevoir le jeton
  4. Ajouter un jeton au magasin de jetons Bot Framework
  5. Gérer la déconnexion de l’utilisateur de l’application

Mettre à jour les variables d’environnement de développement

Vous avez configuré la clé secrète client et le paramètre de connexion OAuth pour l’application dans Microsoft Entra ID. Vous devez configurer le code de votre application avec ces variables.

Pour mettre à jour les variables d’environnement de développement :

  1. Ouvrez le projet d’application.

  2. Ouvrez le ./env fichier de votre projet.

  3. Mettez à jour les variables suivantes :

    • Pour MicrosoftAppId, mettez à jour l’ID d’inscription du bot à partir de Microsoft Entra’ID.
    • Pour MicrosoftAppPassword, mettez à jour la clé secrète client d’inscription du bot.
    • Pour ConnectionName, mettez à jour le nom de la connexion OAuth que vous avez configurée dans Microsoft Entra ID.
    • Pour MicrosoftAppTenantId, mettez à jour l’ID de locataire.
  4. Enregistrez le fichier.

Vous avez maintenant configuré les variables d’environnement requises pour votre application bot et l’authentification unique. Ensuite, ajoutez le code pour la gestion des jetons.

Ajouter du code pour demander un jeton

La demande d’obtention du jeton est une demande de message POST utilisant le schéma de message existant. Il est inclus dans les pièces jointes d'une carte OAuthCard. Le schéma de la classe OAuthCard est défini dans Microsoft Bot Schema 4.0. Teams actualise le jeton si la TokenExchangeResource propriété est remplie sur le carte. Pour le canal Teams, seule laId propriété, qui identifie de manière unique une demande de jeton, est honorée.

Remarque

Le Microsoft Bot Framework OAuthPrompt ou MultiProviderAuthDialog est pris en charge pour l’authentification unique.

Pour mettre à jour le code de votre application :

  1. Ajoutez un extrait de code pour TeamsSSOTokenExchangeMiddleware.

    Ajoutez l’extrait de code suivant à AdapterWithErrorHandler.cs (ou la classe équivalente dans le code de votre application) :

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

    Remarque

    Vous pouvez recevoir plusieurs réponses pour une requête donnée si l’utilisateur a plusieurs points de terminaison actifs. Vous devez éliminer toutes les réponses dupliquées ou redondantes avec le jeton. Pour plus d’informations sur signin/tokenExchange, consultez TeamsSSOTokenExchangeMiddleware, classe.

  2. Utilisez l’extrait de code suivant pour demander un jeton.

    Une fois que vous avez ajouté le AdapterWithErrorHandler.cs, le code suivant doit apparaître :

        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 l’utilisateur de l’application utilise votre application pour la première fois, il doit donner son consentement pour l’authentification unique.

Authentification unique pour l’application d’extension de message

Lorsque l’utilisateur de l’application sélectionne le nom d’utilisateur, l’autorisation est accordée et il peut utiliser l’application.

Authentification unique terminée pour l’application d’extension de message

La boîte de dialogue de consentement qui s’affiche concerne les étendues open-ID définies dans Microsoft Entra ID. L’utilisateur de l’application ne doit donner son consentement qu’une seule fois. Après avoir donné son consentement, l’utilisateur de l’application peut accéder à votre application d’extension de message et l’utiliser pour les autorisations et étendues accordées.

Importante

Scénarios où les dialogues de consentement ne sont pas nécessaires :

  • Si l’administrateur client a donné son consentement pour le compte du locataire, les utilisateurs de l’application n’ont pas besoin d’être invités à donner leur consentement. Cela signifie que les utilisateurs de l’application ne voient pas les boîtes de dialogue de consentement et peuvent accéder à l’application en toute transparence.

Si vous rencontrez des erreurs, consultez Résoudre les problèmes d’authentification unique dans Teams.

Ajouter du code pour recevoir le jeton

La réponse avec le jeton est envoyée par le biais d’une activité d’appel avec le même schéma que les autres activités d’appel que les bots reçoivent aujourd’hui. La seule différence est le nom de l’appel, la connexion/tokenExchange et le champ de valeur . Le champ valeur contient l’ID, une chaîne de la requête initiale pour obtenir le jeton et le champ de jeton , une valeur de chaîne incluant le jeton.

Utilisez l’exemple d’extrait de code suivant pour appeler la réponse :

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

Remarque

Les extraits de code utilisent le bot Waterfall Dialog. Pour plus d’informations sur le dialogue en cascade, consultez À propos des dialogues de composant et de cascade.

Vous recevez le jeton dans OnTeamsMessagingExtensionQueryAsync le gestionnaire dans la turnContext.Activity.Value charge utile ou dans le , selon le OnTeamsAppBasedLinkQueryAsyncscénario pour lequel vous activez l’authentification unique.

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

Valider le jeton d’accès

Les API web sur votre serveur doivent décoder le jeton d’accès et vérifier s’il est envoyé à partir du client.

Remarque

Si vous utilisez Bot Framework, il gère la validation du jeton d’accès. Si vous n’utilisez pas Bot Framework, suivez les instructions de cette section.

Pour plus d’informations sur la validation du jeton d’accès, consultez Valider les jetons.

Il existe un certain nombre de bibliothèques disponibles qui peuvent gérer la validation JWT. La validation de base inclut :

  • Vérification que le jeton est bien formé.
  • Vérification que le jeton a été émis par l’autorité prévue.
  • Vérification que le jeton est ciblé sur l’API web.

Suivez les recommandations suivantes quand vous validez le jeton :

  • Les jetons d’authentification unique valides sont émis par l’ID Microsoft Entra. La iss revendication dans le jeton doit commencer par cette valeur.
  • Le paramètre du aud1 jeton est défini sur l’ID d’application généré lors de Microsoft Entra’inscription de l’application.
  • Le paramètre du scp jeton est défini sur access_as_user.

Exemple de token

L’extrait de code suivant est une charge utile décodée classique d’un jeton d’accès :

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

Ajouter un jeton au magasin de jetons Bot Framework

Si vous utilisez la connexion OAuth, vous devez mettre à jour ou ajouter le jeton dans le magasin de jetons Bot Framework. Ajoutez l’exemple d’extrait de code suivant à TeamsMessagingExtensionsSearchAuthConfigBot.cs (ou au fichier équivalent dans le code de votre application) pour mettre à jour ou ajouter le jeton dans le magasin :

Remarque

Vous trouverez l’exemple TeamsMessagingExtensionsSearchAuthConfigBot.cs dans Tab, Bot et Message Extension (ME) SSO.

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

Gérer la déconnexion de l’utilisateur de l’application

Utilisez l’extrait de code suivant pour gérer le jeton d’accès au cas où l’utilisateur de l’application se déconnecte :

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

Exemple de code

Cette section fournit un exemple de Kit de développement logiciel (SDK) d’authentification de bot v3.

Exemple de nom Description .NET Node.js Python Manifeste
Authentification de bot Cet exemple montre comment bien démarrer avec l’authentification dans un bot pour Teams. View View View View
Authentification unique tabulation, bot et extension de message (ME) Cet exemple montre l’authentification unique pour l’onglet, le bot et l’extension de message : recherche, action, déploiement de lien. View View N/A View
Extension d’onglet, de bot et de message Cet exemple montre comment case activée l’authentification dans le bot, l’onglet et l’extension de message avec l’authentification unique View View N/A View

Étape suivante