Partager via


Configurer votre assistant .NET pour utiliser OAuth

OAuth pour un assistant .NET est d'abord mis en place sur votre ressource Azure Bot et l'enregistrement d'application correspondant. Le runtime de l’assistant acquiert et actualise ensuite les jetons utilisateur pour vous via la AgentApplication fonctionnalité de connexion automatique. La connexion automatique peut s’exécuter globalement (tous les types d’activité) ou de manière sélective afin que seuls certains itinéraires ou types d’activité demandent un jeton.

Vous pouvez inscrire plusieurs gestionnaires OAuth dans la configuration et les affecter à des itinéraires spécifiques, ou déclarer un seul gestionnaire par défaut utilisé partout. Chaque gestionnaire peut éventuellement effectuer des échanges au nom de lorsque le côté Azure est configuré pour cela. Pour un démarrage rapide, consultez l’exemple AutoSignIn ou réaménager la configuration indiquée ici dans un agent existant.

Les sections suivantes décrivent comment configurer UserAuthorization, choisir entre les approches globales et par itinéraire et récupérer des jetons (standard et OBO) pendant un tour. Des conseils régionaux sont également fournis pour les déploiements non américains.

L’agent .NET est configuré dans appsettings ou via du code dans Program.cs. Ce document détaille l’utilisation de appsettings.

Paramètres

L’objet UserAuthorization à l’intérieur AgentApplication contrôle la façon dont les jetons utilisateur sont acquis. Le code JSON suivant montre la structure hiérarchique suivie de tables qui décrivent chaque propriété pour UserAuthorization et pour l’objet imbriqué Settings .

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "{{handler-name}}",
      "AutoSignIn": true | false,
      "Handlers": {
        "{{handler-name}}": {
          "Settings": {
            "AzureBotOAuthConnectionName": "{{azure-bot-connection-name}}",
            "OBOConnectionName": "{{connection-name}}",
            "OBOScopes": [
              "{{obo-scope}}"
            ],
            "Title": "{{signin-card-title}}",
            "Text": "{{signin-card-button-text}}",
            "InvalidSignInRetryMax": {{int}},
            "InvalidSignInRetryMessage": {{invalid-attempt-message}},
            "Timeout": {{timeout-ms}}
          }
        }
      }
    }
  }

Propriétés UserAuthorization

Le tableau suivant répertorie les propriétés de niveau UserAuthorization supérieur qui déterminent la façon dont les gestionnaires sont sélectionnés et comment les jetons sont acquis pour chaque activité entrante.

Propriété Obligatoire Type Descriptif
DefaultHandlerName Non (recommandé) ficelle Nom du gestionnaire utilisé quand il AutoSignIn prend la valeur true et qu’aucun remplacement par routage n’est spécifié.
AutoSignIn Non bool ou délégué Lorsque la valeur est true (valeur par défaut), l’agent tente d’acquérir un jeton pour chaque activité entrante ; cette action peut être remplacée au moment de l’exécution, en utilisant Options.AutoSignIn pour filtrer les types d’activité.
Handlers Oui (au moins un) objet (dictionnaire) Correspondance du nom du gestionnaire à sa configuration. Chaque clé doit être unique.

Pour restreindre les activités auxquelles la connexion automatique s’applique, définissez un prédicat similaire à : Options.AutoSignIn = (context, ct) => Task.FromResult(context.Activity.IsType(ActivityTypes.Message));.

Propriétés des paramètres

Le tableau suivant décrit l’objet imbriqué Settings appliqué à un gestionnaire OAuth individuel, le contrôle de la présentation de carte de connexion, le comportement de nouvelle tentative, les délais d’expiration et la configuration d’échange OBO facultative.

Propriété Obligatoire Type Descriptif
AzureBotOAuthConnectionName Oui ficelle Nom de connexion OAuth défini sur la ressource Azure Bot.
OBOConnectionName Non (OBO uniquement) ficelle Nom d’une connexion du Kit de développement logiciel (SDK) Assistants utilisée pour effectuer un échange de jetons on-Behalf-Of.
OBOScopes Non (OBO uniquement) chaîne de caractères[] Étendues demandées pendant l’échange OBO ; s’il est omis avec OBOConnectionName vous pouvez appeler ExchangeTurnTokenAsync manuellement.
Title Non ficelle Par défaut, titre de la carte de connexion personnalisée : Se connecter.
Text Non ficelle Texte du bouton de carte de connexion ; par défaut défini sur Se connecter.
InvalidSignInRetryMax Non int Nombre maximal de nouvelles tentatives autorisées lorsque l’utilisateur entre un code non valide ; la valeur par défaut est 2.
InvalidSignInRetryMessage Non ficelle Message affiché après une entrée de code non valide ; la valeur par défaut est le code de connexion non valide. Entrez le code à 6 chiffres.
Timeout Non int (ms) Nombre de millisecondes avant l’expiration d’une tentative de connexion en cours. La valeur par défaut est 900000 (15 minutes).

Quel type utiliser ?

Utilisez le tableau suivant pour déterminer quelle approche correspond à votre scénario.

Option À utiliser lorsque
Connexion automatique Vous souhaitez que chaque activité entrante acquiert automatiquement un jeton, ou que vous souhaitez un sous-ensemble filtré (par exemple uniquement les messages ou tous les événements sauf les événements) en fournissant un prédicat à UserAuthorizationOptions.AutoSignIn.
Par route Seuls les gestionnaires de routage spécifiques ont besoin de jetons ou d’itinéraires différents doivent utiliser différentes connexions OAuth (et donc des jetons différents). Ceci est cumulatif avec la connexion automatique globale. Si les deux sont activés, le tour de jeu a accès aux jetons de chacun.

Utiliser le jeton dans le code (non-OBO)

Cette section explique comment récupérer et utiliser le jeton utilisateur retourné directement par votre connexion OAuth du bot Azure sans effectuer un échange d'authentification déléguée. Déterminez d’abord si vous préférez la connexion automatique globale ou les gestionnaires par itinéraire ; ensuite, à l’intérieur de votre gestionnaire d’activités, appelez UserAuthorization.GetTurnTokenAsync le plus tard possible afin que le SDK puisse actualiser le jeton s’il est proche de l’expiration. Les exemples suivants illustrent les deux modèles.

Configuration de connexion automatique uniquement

Utilisez cette configuration lorsque la connexion automatique globale doit acquérir un jeton pour chaque activité entrante sans avoir à spécifier de gestionnaires par routage.

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "auto",
      "Handlers": {
        "auto": {
          "Settings": {
            "AzureBotOAuthConnectionName": "teams_sso",
          }
        }
      }
    }
  },

Votre code d’assistant ressemblerait à ceci :

public class MyAgent : AgentApplication
{
    public MyAgent(AgentApplicationOptions options) : base(options)
    {
        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
    }

    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var token = await UserAuthorization.GetTurnTokenAsync(turnContext);

        // use the token 
    }
}

Configuration par itinéraire uniquement

Utilisez une configuration par itinéraire lorsque vous souhaitez un contrôle affiné : seuls les itinéraires que vous marquez explicitement obtiennent des jetons. La configuration par itinéraire réduit la récupération de jetons inutile, permet à différents itinéraires de cibler des connexions OAuth distinctes (et par conséquent des ressources ou des étendues différentes) et vous permet de combiner des itinéraires authentifiés et non authentifiés au sein du même agent. Dans l’exemple suivant, la connexion automatique globale est désactivée et un seul messageOauth gestionnaire est attaché uniquement à l’itinéraire du message.

  "AgentApplication": {
    "UserAuthorization": {
      "AutoSignIn": false,
      "Handlers": {
        "messageOauth": {
          "Settings": {
            "AzureBotOAuthConnectionName": "teams_sso",
          }
        }
      }
    }
  },

Votre code d’assistant ressemblerait à ceci :

public class MyAgent : AgentApplication
{
    public MyAgent(AgentApplicationOptions options) : base(options)
    {
        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last, autoSignInHandlers: ["messageOauth"]);
    }

    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var token = await UserAuthorization.GetTurnTokenAsync(turnContext, "messageOauth");

        // use the token
    }
}

Utilisez GetTurnTokenAsync.

Appelez GetTurnTokenAsync chaque fois que vous avez besoin du jeton utilisateur pendant un tour. Vous pouvez l’appeler plusieurs fois. Appelez-le immédiatement avant d’utiliser afin que la logique d’actualisation (si nécessaire) soit gérée de manière transparente.

Utiliser le jeton dans le code (OBO)

On-Behalf-Of (OBO) s’appuie sur la première connexion de l’utilisateur retournant un jeton pouvant être échangé. Cela nécessite que les étendues de la connexion OAuth incluent une étendue qui correspond à une étendue exposée par l’API en aval (par exemple, si l’étendue exposée est defaultScopes, l’étendue configurée peut être api://botid-{{clientId}}/defaultScopes). Le SDK Agents effectue ensuite un échange MSAL en utilisant une connexion configurée identifiée par OBOConnectionName et une liste de OBOScopes. Lorsque OBOConnectionName et OBOScopes sont présents dans la configuration, l’échange se produit automatiquement et vous obtenez le jeton final via GetTurnTokenAsync. Si l'un des deux est manquant, vous pouvez effectuer l’échange explicitement au moment de l’exécution avec ExchangeTurnTokenAsync, ce qui vous permet de résoudre dynamiquement la liste de connexions ou d’étendues.

OBO dans la configuration

Utilisez ce modèle lorsque vous connaissez la ressource et les étendues en aval dont vous avez besoin au moment de la configuration. Lorsque vous fournissez à la fois OBOConnectionName et OBOScopes, le Kit de développement logiciel (SDK) effectue automatiquement l’échange On-Behalf-Of pendant la connexion. Cela signifie que les appels suivants pour GetTurnTokenAsync permettent de retourner directement le jeton OBO sans code d'exécution supplémentaire nécessaire.

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "auto",
      "Handlers": {
        "auto": {
          "Settings": {
            "AzureBotOAuthConnectionName": "teams_sso",
            "OBOConnectionName": "ServiceConnection",
            "OBOScopes": [
              "https://myservicescope.com/.default"
            ]
          }
        }
      }
    }
  },
  "Connections": {
    "ServiceConnection": {
      "Settings": {
        "AuthType": "FederatedCredentials",
        "AuthorityEndpoint": "https://login.microsoftonline.com/{{TenantId}}",
        "ClientId": "{{ClientId}}",
        "FederatedClientId": "{{ManagedIdentityClientId}}",
        "Scopes": [
          "https://api.botframework.com/.default"
        ]
      }
    }
  },

Votre code d’assistant ressemblerait à ceci :

public class MyAgent : AgentApplication
{
    public MyAgent(AgentApplicationOptions options) : base(options)
    {
        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
    }

    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var token = await UserAuthorization.GetTurnTokenAsync(turnContext);

        // use the token
    }
}

OBO Exchange au moment de l’exécution

Utilisez un échange d’exécution lorsque la ressource en aval, les étendues ou même la connexion que vous devez utiliser ne peuvent pas être corrigées dans la configuration, par exemple lorsque les étendues dépendent du locataire, du rôle d’utilisateur ou d’un indicateur de fonctionnalité. Dans ce modèle, vous configurez (facultativement) le OBOConnectionName, puis appelez la fonction ExchangeTurnTokenAsync avec les étendues que vous décidez au moment de l’exécution, et vous recevez un jeton échangé que vous pouvez appliquer immédiatement.

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "auto",
      "Handlers": {
        "auto": {
          "Settings": {
            "AzureBotOAuthConnectionName": "teams_sso",
            "OBOConnectionName": "ServiceConnection"
          }
        }
      }
    }
  },
  "Connections": {
    "ServiceConnection": {
      "Settings": {
        "AuthType": "FederatedCredentials",
        "AuthorityEndpoint": "https://login.microsoftonline.com/{{TenantId}}",
        "ClientId": "{{ClientId}}",
        "FederatedClientId": "{{ManagedIdentityClientId}}",
        "Scopes": [
          "https://api.botframework.com/.default"
        ]
      }
    }
  },

Votre code d’assistant ressemblerait à ceci :

public class MyAgent : AgentApplication
{
    public MyAgent(AgentApplicationOptions options) : base(options)
    {
        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
    }

    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var scopes = GetScopes();

        var exchangedToken = await UserAuthorization.ExchangeTurnTokenAsync(turnContext, exchangeScopes: scopes);

        // use the token
    }
}

Paramètres OAuth régionaux

Pour les régions autres que les États-Unis, vous devez mettre à jour le point de terminaison du service de token utilisé par votre agent.

Ajoutez les éléments suivants à appsettings.json:

"RestChannelServiceClientFactory": {
   "TokenServiceEndpoint": "{{service-endpoint-uri}}"
}

Pour service-endpoint-url, utilisez la valeur appropriée du tableau suivant pour les bots cloud public avec résidence des données dans la région spécifiée.

URI Région
https://europe.api.botframework.com Europe
https://unitedstates.api.botframework.com États-Unis
https://india.api.botframework.com Inde