Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Avant d’ajouter du code pour activer l’authentification unique (SSO), veillez à configurer votre ressource d’application et de bot dans le centre d’administration Microsoft Entra.
Remarque
OnTeamsMessagingExtensionQueryAsync et OnTeamsAppBasedLinkQueryAsync à partir du TeamsMessagingExtensionsSearchAuthConfigBot.cs fichier sont les seuls gestionnaires SSO pris en charge. Les autres gestionnaires SSO ne sont pas pris en charge.
Cet article couvre les sujets suivants :
- Mettre à jour les variables d’environnement de développement
- Ajouter le code pour demander un jeton
- Ajouter le code pour recevoir le jeton
- Ajouter un jeton au magasin de jetons de Bot Framework
- Gérer la déconnexion de l’utilisateur de l’application
Mettre à jour les variables d’environnement de développement
Vous avez configuré le secret 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 :
Ouvrez le projet d’application.
Ouvrez le
./envfichier de votre projet.Mettez à jour les variables suivantes :
- Pour
MicrosoftAppId, mettez à jour l’ID d’inscription du bot à partir de Microsoft Entra ID. - Pour
MicrosoftAppPassword, mettez à jour le secret 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 client.
- Pour
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 le 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 renseignée sur la 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 :
Ajouter un extrait de code pour
TeamsSSOTokenExchangeMiddleware.Ajoutez l’extrait
AdapterWithErrorHandler.csde code suivant (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 la classe TeamsSSOTokenExchangeMiddleware.
Utilisez l’extrait de code suivant pour demander un jeton.
Après avoir 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"); }; } }
Boîte de dialogue de consentement pour l’obtention du jeton d’accès
Si l’utilisateur de l’application utilise votre application pour la première fois, il doit donner son consentement à l’authentification SSO.
Lorsque l’utilisateur de l’application sélectionne le nom d’utilisateur, l’autorisation est accordée et il peut utiliser 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 d’extension de message et l’utiliser pour les autorisations et les étendues accordées.
Importante
Scénarios où les dialogues de consentement ne sont pas nécessaires :
- Si l’administrateur a accordé son consentement au nom du client, 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 de manière transparente.
Si vous rencontrez des erreurs, consultez Résoudre les problèmes d’authentification SSO dans Teams.
Ajouter le 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 réside dans le nom d’appel, la connexion/tokenExchange et le champ 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 robot de dialogue en cascade. Pour plus d’informations sur la boîte de dialogue en cascade, voir À propos des boîtes de dialogue de composant et en cascade.
Vous recevez le jeton dans OnTeamsMessagingExtensionQueryAsync le gestionnaire dans la turnContext.Activity.Value charge utile ou dans le OnTeamsAppBasedLinkQueryAsync, selon le scé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)
{
// Process the token.
}
}
Valider le jeton d’accès
Les API web de votre serveur doivent décoder le jeton d’accès et vérifier s’il provient 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 SSO valides sont émis par Microsoft Entra ID. La
issrevendication dans le jeton doit commencer par cette valeur. - Le paramètre du jeton est défini sur l’ID d’application généré lors de l’inscription de l’application
aud1Microsoft Entra. - Le paramètre du
scpjeton est défini suraccess_as_user.
Exemple de token
L’extrait de code suivant est une charge utile décodée typique 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 de 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 TeamsMessagingExtensionsSearchAuthConfigBot.cs d’extrait de code suivant (ou le fichier équivalent dans le code de votre application) pour mettre à jour ou ajouter le jeton dans le Store :
Remarque
Vous trouverez l’exemple TeamsMessagingExtensionsSearchAuthConfigBot.cs dans l’authentification unique par onglet, bot et extension de message (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);
}
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 fails for any reason,
// tokenExchangeResponse remains null and a failure invoke response is sent.
}
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éconnecterait :
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 des exemples de SDK v3 pour l’authentification des bots.
| Exemple de nom | Description | .NET | Node.js | Python | Manifeste |
|---|---|---|---|---|---|
| Authentification de bot | Cet exemple d’application montre comment un bot peut utiliser l’authentification Teams. | View | View | View | N/A |
| SSO d’onglet, de bot et d’extension de message | Cet exemple d’application illustre l’intégration de l’authentification unique Teams pour les onglets, les bots et les extensions de message à l’aide de C# et de Microsoft Entra ID pour l’authentification sécurisée. | View | View | N/A | View |
| Extension d’onglet, de bot et de message | Cet exemple présente l’authentification Microsoft Entra ID et Facebook via des bots, des onglets et des extensions de message dans Microsoft Teams. | View | View | N/A | View |