Exercice - Ajouter l’authentification unique

Effectué

Dans cet exercice, vous ajoutez l’authentification unique à l’extension de message pour authentifier les requêtes utilisateur.

Capture d’écran d’un défi d’authentification dans une extension de message basée sur la recherche. Un lien vers la connexion s’affiche.

Configurer l’inscription d’applications API back-end

Tout d’abord, créez une inscription d’application Microsoft Entra pour l’API back-end. Pour les besoins de cet exercice, vous en créez un. Toutefois, dans un environnement de production, vous devez utiliser une inscription d’application existante.

Dans une fenêtre de navigateur :

  1. Accédez au Portail Azure
  2. Ouvrez le menu du portail et sélectionnez Microsoft Entra ID
  3. Sélectionnez inscriptions d'applications, puis Nouvelle inscription
  4. Dans le formulaire Inscrire une application, spécifiez les valeurs suivantes :
    1. Nom : API Products
    2. Types de comptes de support : Comptes dans n’importe quel annuaire organisationnel (tout locataire Microsoft Entra ID - Multilocataire)
  5. Sélectionnez Inscrire pour créer l’inscription de l’application.
  6. Dans le menu de gauche inscription de l’application, sélectionnez Exposer une API
  7. Sélectionnez Ajouter et enregistrer créer un URI d’ID d’application
  8. Dans la section Étendues définies par cette API, sélectionnez Ajouter une étendue.
  9. Dans le formulaire Ajouter une étendue, spécifiez les valeurs suivantes :
    1. Nom de l’étendue : Product.Read
    2. Qui peut donner son consentement ?: Administrateurs et utilisateurs
    3. Administration nom d’affichage du consentement : Lire les produits
    4. Administration description du consentement : permet à l’application de lire les données du produit
    5. Nom d’affichage du consentement de l’utilisateur : Lire les produits
    6. Description du consentement de l’utilisateur : permet à l’application de lire les données de produit
    7. État : activé
  10. Sélectionnez Ajouter une étendue pour créer l’étendue.

Notez ensuite l’ID d’inscription de l’application et l’ID d’étendue. Vous avez besoin de ces valeurs pour configurer l’inscription de l’application utilisée pour obtenir un jeton d’accès pour l’API back-end.

  1. Dans le menu de gauche inscription de l’application, sélectionnez Manifeste
  2. Copiez la valeur de la propriété appId et enregistrez-la pour une utilisation ultérieure
  3. Copiez la valeur de la propriété api.oauth2PermissionScopes[0].id et enregistrez-la pour une utilisation ultérieure

Comme nous avons besoin de ces valeurs dans le projet, ajoutez-les au fichier d’environnement.

Dans Visual Studio et le projet TeamsApp :

  1. Dans le dossier env , ouvrez .env.local

  2. Dans le fichier, créez les variables d’environnement suivantes et définissez les valeurs sur l’ID d’inscription d’application et l’ID d’étendue :

    BACKEND_API_ENTRA_APP_ID=<app-registration-id>
    BACKEND_API_ENTRA_APP_SCOPE_ID=<scope-id>
    
  3. Save your changes

Créer un fichier manifeste d’inscription d’application pour l’authentification auprès de l’API back-end

Pour vous authentifier auprès de l’API back-end, vous avez besoin d’une inscription d’application pour obtenir un jeton d’accès avec lequel appeler l’API.

Ensuite, créez un fichier manifeste d’inscription d’application. Le manifeste définit les étendues d’autorisation d’API et l’URI de redirection sur l’inscription de l’application.

Dans Visual Studio et le projet TeamsApp :

  1. Dans le dossier infra\entra , créez un fichier nommé entra.products.api.manifest.json

  2. Dans le fichier, ajoutez le code suivant :

    {
      "id": "${{PRODUCTS_API_ENTRA_APP_OBJECT_ID}}",
      "appId": "${{PRODUCTS_API_ENTRA_APP_ID}}",
      "name": "${{APP_INTERNAL_NAME}}-product-api-${{TEAMSFX_ENV}}",
      "accessTokenAcceptedVersion": 2,
      "signInAudience": "AzureADMultipleOrgs",
      "optionalClaims": {
        "idToken": [],
        "accessToken": [
          {
            "name": "idtyp",
            "source": null,
            "essential": false,
            "additionalProperties": []
          }
        ],
        "saml2Token": []
      },
      "requiredResourceAccess": [
        {
          "resourceAppId": "${{BACKEND_API_ENTRA_APP_ID}}",
          "resourceAccess": [
            {
              "id": "${{BACKEND_API_ENTRA_APP_SCOPE_ID}}",
              "type": "Scope"
            }
          ]
        }
      ],
      "oauth2Permissions": [],
      "preAuthorizedApplications": [],
      "identifierUris": [],
      "replyUrlsWithType": [
        {
          "url": "https://token.botframework.com/.auth/web/redirect",
          "type": "Web"
        }
      ]
    }
    
  3. Save your changes

La propriété requiredResourceAccess spécifie l’ID d’inscription de l’application et l’ID d’étendue de l’API back-end.

La propriété replyUrlsWithType spécifie l’URI de redirection utilisé par bot Framework Token Service pour retourner le jeton d’accès au service de jeton après l’authentification de l’utilisateur.

Ensuite, mettez à jour le workflow automatisé pour créer et mettre à jour l’inscription de l’application.

Dans le projet TeamsApp :

  1. Ouvrir teamsapp.local.yml

  2. Dans le fichier, recherchez l’étape qui utilise l’action addApp/update

  3. Après l’action, ajoutez les actions aadApp/create et aadApp/update pour créer et mettre à jour l’inscription de l’application :

      - uses: aadApp/create
        with:
            name: ${{APP_INTERNAL_NAME}}-products-api-${{TEAMSFX_ENV}}
            generateClientSecret: true
            signInAudience: AzureADMultipleOrgs
        writeToEnvironmentFile:
            clientId: PRODUCTS_API_ENTRA_APP_ID
            clientSecret: SECRET_PRODUCTS_API_ENTRA_APP_CLIENT_SECRET
            objectId: PRODUCTS_API_ENTRA_APP_OBJECT_ID
            tenantId: PRODUCTS_API_ENTRA_APP_TENANT_ID
            authority: PRODUCTS_API_ENTRA_APP_OAUTH_AUTHORITY
            authorityHost: PRODUCTS_API_ENTRA_APP_OAUTH_AUTHORITY_HOST
    
      - uses: aadApp/update
        with:
            manifestPath: "./infra/entra/entra.products.api.manifest.json"
            outputFilePath : "./infra/entra/build/entra.products.api.${{TEAMSFX_ENV}}.json"
    
  4. Save your changes

L’action aadApp/create crée une inscription d’application avec le nom et l’audience spécifiés et génère une clé secrète client. La propriété writeToEnvironmentFile écrit l’ID d’inscription de l’application, la clé secrète client, l’ID d’objet, l’ID de locataire, l’autorité et l’hôte d’autorité dans les fichiers d’environnement. La clé secrète client est chiffrée et stockée de manière sécurisée dans le fichier env.local.user . Le nom de la variable d’environnement pour la clé secrète client est précédé de SECRET_, il indique à Teams Toolkit de ne pas écrire la valeur dans les journaux.

L’action aadApp/update met à jour l’inscription de l’application avec le fichier manifeste spécifié.

Centraliser le nom du paramètre de connexion

Tout d’abord, centralisez le nom du paramètre de connexion dans le fichier d’environnement et mettez à jour la configuration de l’application pour accéder à la valeur de la variable d’environnement au moment de l’exécution.

Continuez dans Visual Studio et dans le projet TeamsApp :

  1. Dans le dossier env , ouvrez .env.local

  2. Dans le fichier, ajoutez le code suivant :

    CONNECTION_NAME=ProductsAPI
    
  3. Ouvrir teamsapp.local.yml

  4. Dans le fichier, recherchez l’étape qui utilise l’action file/createOrUpdateJsonFile ciblant ./appsettings. Development.json fichier. Mettez à jour le tableau de contenu pour inclure la variable d’environnement CONNECTION_NAME et écrire la valeur dans les appsettings. Development.json fichier :

      - uses: file/createOrUpdateJsonFile
        with:
          target: ../ProductsPlugin/appsettings.Development.json
          content:
            BOT_ID: ${{BOT_ID}}
            BOT_PASSWORD: ${{SECRET_BOT_PASSWORD}}
            CONNECTION_NAME: ${{CONNECTION_NAME}}
    
  5. Save your changes

Ensuite, mettez à jour la configuration de l’application pour accéder à la variable d’environnement CONNECTION_NAME .

Dans le projet ProductsPlugin :

  1. Ouvrir Config.cs

  2. Dans la classe ConfigOptions , ajoutez une nouvelle propriété nommée CONNECTION_NAME

    public class ConfigOptions
    {
      public string BOT_ID { get; set; }
      public string BOT_PASSWORD { get; set; }
      public string CONNECTION_NAME { get; set; }
    }
    
  3. Save your changes

  4. Ouvrir Program.cs

  5. Dans le fichier , mettez à jour le code qui lit la configuration de l’application pour inclure la propriété CONNECTION_NAME

    var config = builder.Configuration.Get<ConfigOptions>();
    builder.Configuration["MicrosoftAppType"] = "MultiTenant";
    builder.Configuration["MicrosoftAppId"] = config.BOT_ID;
    builder.Configuration["MicrosoftAppPassword"] = config.BOT_PASSWORD;
    builder.Configuration["ConnectionName"] = config.CONNECTION_NAME;
    
  6. Save your changes

Ensuite, mettez à jour le code du bot pour utiliser le nom du paramètre de connexion au moment de l’exécution.

  1. Dans le dossier Rechercher , ouvrez SearchApp.cs

  2. Dans la classe SearchApp , créez un constructeur qui accepte un objet IConfiguration et affecte la valeur de la propriété CONNECTION_NAME à un champ privé nommé connectionName

    public class SearchApp : TeamsActivityHandler
    {
      private readonly string connectionName;
    
      public SearchApp(IConfiguration configuration)
      {
        connectionName = configuration["CONNECTION_NAME"];
      }  
    }
    
  3. Save your changes

Configurer le paramètre de connexion de l’API Products

Pour vous authentifier auprès de l’API back-end, vous devez configurer un paramètre de connexion dans la ressource Azure Bot.

Continuez dans Visual Studio et le projet TeamsApp :

  1. Dans le dossier infra , ouvrez azure.parameters.local.json

  2. Dans le fichier, ajoutez les paramètres backendApiEntraAppClientId, productsApiEntraAppClientId, productsApiEntraAppClientSecret et connectionName

    {
      "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "resourceBaseName": {
          "value": "bot-${{RESOURCE_SUFFIX}}-${{TEAMSFX_ENV}}"
        },
        "botEntraAppClientId": {
          "value": "${{BOT_ID}}"
        },
        "botDisplayName": {
          "value": "${{APP_DISPLAY_NAME}}"
        },
        "botAppDomain": {
          "value": "${{BOT_DOMAIN}}"
        },
        "backendApiEntraAppClientId": {
          "value": "${{BACKEND_API_ENTRA_APP_ID}}"
        },
        "productsApiEntraAppClientId": {
          "value": "${{PRODUCTS_API_ENTRA_APP_ID}}"
        },
        "productsApiEntraAppClientSecret": {
          "value": "${{SECRET_PRODUCTS_API_ENTRA_APP_CLIENT_SECRET}}"
        },
        "connectionName": {
          "value": "${{CONNECTION_NAME}}"
        }
      }
    }
    
  3. Save your changes

Ensuite, mettez à jour le fichier Bicep pour inclure les nouveaux paramètres et passez-les à la ressource Azure Bot.

  1. Dans le dossier infra, ouvrez le fichier nommé azure.local.bicep.

  2. Dans le fichier, après la déclaration du paramètre botAppDomain, ajoutez les déclarations de paramètre backendApiEntraAppClientId, productsApiEntraAppClientId, productsApiEntraAppClientSecret et connectionName

    param backendApiEntraAppClientId string
    param productsApiEntraAppClientId string
    @secure()
    param productsApiEntraAppClientSecret string
    param connectionName string
    
  3. Dans la déclaration du module azureBotRegistration , ajoutez les nouveaux paramètres

    module azureBotRegistration './botRegistration/azurebot.bicep' = {
      name: 'Azure-Bot-registration'
      params: {
        resourceBaseName: resourceBaseName
        botEntraAppClientId: botEntraAppClientId
        botAppDomain: botAppDomain
        botDisplayName: botDisplayName
        backendApiEntraAppClientId: backendApiEntraAppClientId
        productsApiEntraAppClientId: productsApiEntraAppClientId
        productsApiEntraAppClientSecret: productsApiEntraAppClientSecret
        connectionName: connectionName
      }
    }
    
  4. Enregistrez vos modifications.

Enfin, mettez à jour le fichier Bicep d’inscription du bot pour inclure le nouveau paramètre de connexion.

  1. Dans le dossier infra/botRegistration, ouvrez azurebot.bicep.

  2. Dans le fichier, après la déclaration du paramètre botAppDomain, ajoutez les déclarations de paramètre backendApiEntraAppClientId, productsApiEntraAppClientId, productsApiEntraAppClientSecret et connectionName

    param backendApiEntraAppClientId string
    param productsApiEntraAppClientId string
    @secure()
    param productsApiEntraAppClientSecret string
    param connectionName string
    
  3. Dans le fichier, créez une ressource nommée botServicesProductsApiConnection

    resource botServicesProductsApiConnection 'Microsoft.BotService/botServices/connections@2022-09-15' = {
      parent: botService
      name: connectionName
      location: 'global'
      properties: {
        serviceProviderDisplayName: 'Azure Active Directory v2'
        serviceProviderId: '30dd229c-58e3-4a48-bdfd-91ec48eb906c'
        clientId: productsApiEntraAppClientId
        clientSecret: productsApiEntraAppClientSecret
        scopes: 'api://${backendApiEntraAppClientId}/Product.Read'
        parameters: [
          {
            key: 'tenantID'
            value: 'common'
          }
          {
            key: 'tokenExchangeUrl'
            value: 'api://${botAppDomain}/botid-${botEntraAppClientId}'
          }
        ]
      }
    }
    
  4. Save your changes

Configurer l’authentification dans l’extension de message

Pour authentifier les requêtes utilisateur dans l’extension de message, vous utilisez le Kit de développement logiciel (SDK) Bot Framework afin d’obtenir un jeton d’accès pour l’utilisateur à partir du service d’émission de jetons Bot Framework. Le jeton d’accès peut ensuite être utilisé pour accéder aux données à partir d’un service externe.

Pour simplifier le code, créez une classe d’assistance qui gère l’authentification utilisateur.

Continuez dans Visual Studio et le projet ProductsPlugin :

  1. Créer un dossier nommé Helpers

  2. Dans le dossier Helpers , créez un fichier de classe nommé AuthHelpers.cs

  3. Dans le fichier, ajoutez le code suivant :

    using Microsoft.Bot.Connector.Authentication;
    using Microsoft.Bot.Schema;
    using Microsoft.Bot.Schema.Teams;
    
    internal static class AuthHelpers
    {
        internal static async Task<MessagingExtensionResponse> CreateAuthResponse(UserTokenClient userTokenClient, string connectionName, Activity activity, CancellationToken cancellationToken)
        {
            var resource = await userTokenClient.GetSignInResourceAsync(connectionName, activity, null, cancellationToken);
    
            return new MessagingExtensionResponse
            {
                ComposeExtension = new MessagingExtensionResult
                {
                    Type = "auth",
                    SuggestedActions = new MessagingExtensionSuggestedAction
                    {
                        Actions = [
                            new() {
                                Type = ActionTypes.OpenUrl,
                                Value = resource.SignInLink,
                                Title = "Sign In",
                            },
                        ],
                    },
                },
            };
        }
    
        internal static async Task<TokenResponse> GetToken(UserTokenClient userTokenClient, string state, string userId, string channelId, string connectionName, CancellationToken cancellationToken)
        {
            var magicCode = string.Empty;
    
            if (!string.IsNullOrEmpty(state))
            {
                if (int.TryParse(state, out var parsed))
                {
                    magicCode = parsed.ToString();
                }
            }
    
            return await userTokenClient.GetUserTokenAsync(userId, connectionName, channelId, magicCode, cancellationToken);
        }
    
        internal static bool HasToken(TokenResponse tokenResponse) => tokenResponse != null && !string.IsNullOrEmpty(tokenResponse.Token);
    }
    
  4. Save your changes

Les trois méthodes d’assistance de la classe AuthHelpers gèrent l’authentification utilisateur dans l’extension de message.

  • La méthode CreateAuthResponse construit une réponse qui affiche un lien de connexion dans l’interface utilisateur. Le lien de connexion est récupéré à partir du service de jeton à l’aide de la méthode GetSignInResourceAsync .
  • La méthode GetToken utilise le client de service de jeton pour obtenir un jeton d’accès pour l’utilisateur actuel. La méthode utilise un code magique pour vérifier l’authenticité de la requête.
  • La méthode HasToken vérifie si la réponse du service de jeton contient un jeton d’accès. Si le jeton n’est pas null ou vide, la méthode retourne true.

Ensuite, mettez à jour le code d’extension de message pour utiliser les méthodes d’assistance pour authentifier les requêtes utilisateur.

  1. Dans le dossier Rechercher , ouvrez SearchApp.cs

  2. En haut du fichier, ajoutez l’instruction using suivante :

    using Microsoft.Bot.Connector.Authentication;
    
  3. Dans la méthode OnTeamsMessagingExtensionQueryAsync , ajoutez le code suivant au début de la méthode :

    var userTokenClient = turnContext.TurnState.Get<UserTokenClient>();
    var tokenResponse = await AuthHelpers.GetToken(userTokenClient, query.State, turnContext.Activity.From.Id, turnContext.Activity.ChannelId, connectionName, cancellationToken);
    
    if (!AuthHelpers.HasToken(tokenResponse))
    {
        return await AuthHelpers.CreateAuthResponse(userTokenClient, connectionName, (Activity)turnContext.Activity, cancellationToken);
    }
    
  4. Save your changes

Ensuite, ajoutez le domaine Token Service au fichier manifeste de l’application pour vous assurer que le client peut approuver le domaine lors du lancement d’un flux d’authentification unique.

Dans le projet TeamsApp :

  1. Dans le dossier appPackage , ouvrez manifest.json

  2. Dans le fichier, mettez à jour le tableau validDomains , puis ajoutez le domaine du service de jeton :

    "validDomains": [
        "token.botframework.com",
        "${{BOT_DOMAIN}}"
    ]
    
  3. Save your changes

Créer et mettre à jour des ressources

Une fois tout ce qui est maintenant en place, exécutez le processus Préparer les dépendances d’application Teams pour créer de nouvelles ressources et mettre à jour celles existantes.

Continuez dans Visual Studio :

  1. Dans Explorateur de solutions, cliquez avec le bouton droit sur le projet TeamsApp
  2. Développez le menu Kit de ressources Teams, sélectionnez Préparer les dépendances de l’application Teams.
  3. Dans la boîte de dialogue Compte Microsoft 365 , sélectionnez Continuer
  4. Dans la boîte de dialogue Provisionner , sélectionnez Provisionner
  5. Dans la boîte de dialogue d’avertissement du Kit de ressources Teams , sélectionnez Provisionner
  6. Dans la boîte de dialogue Informations du Kit de ressources Teams , sélectionnez l’icône en forme de croix pour fermer la boîte de dialogue

Exécuter et déboguer

Une fois les ressources approvisionnées, démarrez une session de débogage pour tester l’extension de message.

  1. Pour démarrer une nouvelle session de débogage, appuyez sur F5 ou sélectionnez Démarrer dans la barre d’outils

  2. Attendez qu’une fenêtre de navigateur s’ouvre et que la boîte de dialogue d’installation de l’application s’affiche dans le client web Microsoft Teams. Si vous y êtes invité, entrez les informations d’identification de votre compte Microsoft 365.

  3. Dans la boîte de dialogue d’installation de l’application, sélectionnez Ajouter

  4. Ouvrir une conversation Microsoft Teams nouvelle ou existante

  5. Dans la zone de composition des messages, sélectionnez + pour ouvrir le sélecteur d’application

  6. Dans la liste des applications, sélectionnez Produits Contoso pour ouvrir l’extension de message

  7. Dans la zone de texte, entrez hello

  8. Un message vous indiquant que vous devez vous connecter pour utiliser cette application s’affiche

    Capture d’écran d’un défi d’authentification dans une extension de message basée sur la recherche. Un lien vers la connexion s’affiche.

  9. Suivez le lien de connexion pour démarrer le flux d’authentification

  10. Consentement aux autorisations demandées et retour à Microsoft Teams

    Capture d’écran de Microsoft Entra boîte de dialogue de consentement d’autorisation d’API.

  11. Attendez que la recherche se termine et que les résultats s’affichent

  12. Dans la liste des résultats, sélectionnez hello pour incorporer un carte dans la zone de rédaction du message

Revenez à Visual Studio et sélectionnez Arrêter dans la barre d’outils ou appuyez sur Maj + F5 pour arrêter la session de débogage.