Übung: Single Sign-On hinzufügen
In dieser Übung fügen Sie der Nachrichtenerweiterung einmaliges Anmelden hinzu, um Benutzerabfragen zu authentifizieren.
Konfigurieren der Registrierung von Back-End-API-Apps
Erstellen Sie zunächst eine Microsoft Entra-App-Registrierung für die Back-End-API. Für die Zwecke dieser Übung erstellen Sie eine neue, aber in einer Produktionsumgebung würden Sie eine vorhandene App-Registrierung verwenden.
In einem Browserfenster:
- Navigieren Sie zum Azure-Portal.
- Öffnen Sie das Portalmenü, und wählen Sie Microsoft Entra ID aus.
- Wählen Sie App-Registrierungen und dann Neue Registrierung aus.
- Geben Sie im Formular Anwendung registrieren die folgenden Werte an:
- Name: Products API
- Supportkontotypen: Konten in einem beliebigen Organisationsverzeichnis (Beliebiger Microsoft Entra ID-Mandant – mehrinstanzenfähig)
- Wählen Sie Registrieren aus, um die App-Registrierung zu erstellen.
- Wählen Sie im linken Menü der App-Registrierung die Option Api verfügbar machen aus.
- Wählen Sie Hinzufügen und Speichern aus, um einen neuen Anwendungs-ID-URI zu erstellen.
- Wählen Sie im Abschnitt Von dieser API definierte Bereiche die Option Bereich hinzufügen aus.
- Geben Sie im Formular Bereich hinzufügen die folgenden Werte an:
- Bereichsname: Product.Read
- Wer kann zustimmen?: Administratoren und Benutzer
- Anzeigename der Administratoreinwilligung: Produkte lesen
- Beschreibung der Administratoreinwilligung: Ermöglicht der App das Lesen von Produktdaten.
- Anzeigename der Benutzer-Zustimmung: Produkte lesen
- Beschreibung der Benutzerzustimmung: Ermöglicht der App das Lesen von Produktdaten.
- Status: Aktiviert
- Wählen Sie Bereich hinzufügen aus, um den Bereich zu erstellen.
Notieren Sie sich als Nächstes die App-Registrierungs-ID und die Bereichs-ID. Sie benötigen diese Werte, um die App-Registrierung zu konfigurieren, die zum Abrufen eines Zugriffstokens für die Back-End-API verwendet wird.
- Wählen Sie im linken Menü der App-Registrierung die Option Manifest aus.
- Kopieren Sie den AppId-Eigenschaftswert , und speichern Sie ihn zur späteren Verwendung.
- Kopieren Sie den Eigenschaftswert api.oauth2PermissionScopes[0].id , und speichern Sie ihn zur späteren Verwendung.
Da wir diese Werte im Projekt benötigen, fügen Sie sie der Umgebungsdatei hinzu.
In Visual Studio und im Projekt TeamsApp:
Öffnen Sie im Ordner env die Datei .env.local
Erstellen Sie in der Datei die folgenden Umgebungsvariablen, und legen Sie die Werte auf die App-Registrierungs-ID und die Bereichs-ID fest:
BACKEND_API_ENTRA_APP_ID=<app-registration-id> BACKEND_API_ENTRA_APP_SCOPE_ID=<scope-id>
Save your changes
Erstellen einer App-Registrierungsmanifestdatei für die Authentifizierung mit der Back-End-API
Für die Authentifizierung bei der Back-End-API benötigen Sie eine App-Registrierung, um ein Zugriffstoken zum Aufrufen der API abzurufen.
Erstellen Sie als Nächstes eine Manifestdatei für die App-Registrierung. Das Manifest definiert die API-Berechtigungsbereiche und den Umleitungs-URI für die App-Registrierung.
In Visual Studio und im Projekt TeamsApp:
Erstellen Sie im Ordner infra\entra eine Datei mit dem Namen entra.products.api.manifest.json
Fügen Sie in der Datei den folgenden Code hinzu:
{ "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" } ] }
Save your changes
Die requiredResourceAccess-Eigenschaft gibt die App-Registrierungs-ID und die Bereichs-ID der Back-End-API an.
Die replyUrlsWithType-Eigenschaft gibt den Umleitungs-URI an, der vom Bot Framework-Tokendienst verwendet wird, um das Zugriffstoken nach der Authentifizierung des Benutzers an den Tokendienst zurückzugeben.
Aktualisieren Sie als Nächstes den automatisierten Workflow, um die App-Registrierung zu erstellen und zu aktualisieren.
Im Projekt TeamsApp:
Teamsapp.local.yml öffnen
Suchen Sie in der Datei den Schritt, der die Aktion addApp/update verwendet.
Fügen Sie nach der Aktion die Aktionen aadApp/create und aadApp/update hinzu, um die App-Registrierung zu erstellen und zu aktualisieren:
- 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"
Save your changes
Die aadApp/create-Aktion erstellt eine neue App-Registrierung mit dem angegebenen Namen und der angegebenen Zielgruppe und generiert einen geheimen Clientschlüssel. Die writeToEnvironmentFile-Eigenschaft schreibt die App-Registrierungs-ID, den geheimen Clientschlüssel, die Objekt-ID, die Mandanten-ID, die Autorität und den Autoritätshost in die Umgebungsdateien. Der geheime Clientschlüssel wird verschlüsselt und sicher in der Datei env.local.user gespeichert. Dem Namen der Umgebungsvariablen für den geheimen Clientschlüssel wird SECRET_ vorangestellt. Er weist Teams Toolkit an, den Wert nicht in die Protokolle zu schreiben.
Die aadApp/update-Aktion aktualisiert die App-Registrierung mit der angegebenen Manifestdatei.
Name der Verbindungseinstellung zentralisieren
Zentralisieren Sie zunächst den Namen der Verbindungseinstellung in der Umgebungsdatei, und aktualisieren Sie die App-Konfiguration, um zur Laufzeit auf den Wert der Umgebungsvariablen zuzugreifen.
Fortfahren in Visual Studio und im Projekt TeamsApp:
Öffnen Sie im Ordner env die Datei .env.local
Fügen Sie in der Datei den folgenden Code hinzu:
CONNECTION_NAME=ProductsAPI
Teamsapp.local.yml öffnen
Suchen Sie in der Datei den Schritt, der die Aktion file/createOrUpdateJsonFile für ./appsettings verwendet. Development.json Datei. Aktualisieren Sie das Inhaltsarray, um die umgebungsvariable CONNECTION_NAME einzuschließen, und schreiben Sie den Wert in die appsettings. Development.json Datei:
- uses: file/createOrUpdateJsonFile with: target: ../ProductsPlugin/appsettings.Development.json content: BOT_ID: ${{BOT_ID}} BOT_PASSWORD: ${{SECRET_BOT_PASSWORD}} CONNECTION_NAME: ${{CONNECTION_NAME}}
Save your changes
Aktualisieren Sie als Nächstes die App-Konfiguration, um auf die umgebungsvariable CONNECTION_NAME zuzugreifen.
Im Projekt ProductsPlugin:
Config.cs öffnen
Fügen Sie in der ConfigOptions-Klasse eine neue Eigenschaft mit dem Namen CONNECTION_NAME
public class ConfigOptions { public string BOT_ID { get; set; } public string BOT_PASSWORD { get; set; } public string CONNECTION_NAME { get; set; } }
Save your changes
Program.cs öffnen
Aktualisieren Sie in der Datei den Code, der die App-Konfiguration liest, um die eigenschaft CONNECTION_NAME einzuschließen.
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;
Save your changes
Aktualisieren Sie als Nächstes den Botcode, um den Namen der Verbindungseinstellung zur Laufzeit zu verwenden.
Öffnen Sie im Ordner SucheSearchApp.cs
Erstellen Sie in der SearchApp-Klasse einen Konstruktor, der ein IConfiguration-Objekt akzeptiert und den Wert der CONNECTION_NAME-Eigenschaft einem privaten Feld namens connectionName zuweist.
public class SearchApp : TeamsActivityHandler { private readonly string connectionName; public SearchApp(IConfiguration configuration) { connectionName = configuration["CONNECTION_NAME"]; } }
Save your changes
Konfigurieren der Verbindungseinstellung für die Products-API
Für die Authentifizierung mit der Back-End-API müssen Sie eine Verbindungseinstellung in der Azure Bot-Ressource konfigurieren.
Fortfahren in Visual Studio und dem TeamsApp-Projekt:
Öffnen Sie im Ordner "infra " azure.parameters.local.json
Fügen Sie in der Datei die Parameter backendApiEntraAppClientId, productsApiEntraAppClientId, productsApiEntraAppClientSecret und connectionName hinzu.
{ "$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}}" } } }
Save your changes
Aktualisieren Sie als Nächstes die Bicep-Datei, um die neuen Parameter einzuschließen, und übergeben Sie sie an die Azure Bot-Ressource.
Öffnen Sie im Ordner infra die Datei azure.local.bicep.
Fügen Sie in der Datei nach der botAppDomain-Parameterdeklaration die Parameterdeklarationen backendApiEntraAppClientId, productsApiEntraAppClientId, productsApiEntraAppClientSecret und connectionName hinzu.
param backendApiEntraAppClientId string param productsApiEntraAppClientId string @secure() param productsApiEntraAppClientSecret string param connectionName string
Fügen Sie in der Moduldeklaration azureBotRegistration die neuen Parameter hinzu.
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 } }
Speichern Sie Ihre Änderungen.
Aktualisieren Sie abschließend die Bicep-Datei für die Botregistrierung, um die neue Verbindungseinstellung einzuschließen.
Öffnen Sie im Ordner infra/botRegistrationdie Datei azurebot.bicep.
Fügen Sie in der Datei nach der botAppDomain-Parameterdeklaration die Parameterdeklarationen backendApiEntraAppClientId, productsApiEntraAppClientId, productsApiEntraAppClientSecret und connectionName hinzu.
param backendApiEntraAppClientId string param productsApiEntraAppClientId string @secure() param productsApiEntraAppClientSecret string param connectionName string
Erstellen Sie in der Datei eine neue Ressource mit dem Namen 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}' } ] } }
Save your changes
Konfigurieren der Authentifizierung in der Nachrichtenerweiterung
Zum Authentifizieren von Benutzerabfragen in der Nachrichtenerweiterung verwenden Sie das Bot Framework SDK, um ein Zugriffstoken für den Benutzer vom Bot Framework Token Service abzurufen. Das Zugriffstoken kann dann für den Zugriff auf Daten von einem externen Dienst verwendet werden.
Um den Code zu vereinfachen, erstellen Sie eine Hilfsklasse, die die Benutzerauthentifizierung verarbeitet.
Fortfahren in Visual Studio und dem Projekt ProductsPlugin:
Erstellen Eines neuen Ordners mit dem Namen Hilfsprogramme
Erstellen Sie im Ordner Helpers eine neue Klassendatei mit dem Namen AuthHelpers.cs
Fügen Sie in der Datei den folgenden Code hinzu:
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); }
Save your changes
Die drei Hilfsmethoden in der AuthHelpers-Klasse behandeln die Benutzerauthentifizierung in der Nachrichtenerweiterung.
- Die CreateAuthResponse-Methode erstellt eine Antwort, die einen Anmeldelink auf der Benutzeroberfläche rendert. Der Anmeldelink wird mithilfe der GetSignInResourceAsync-Methode vom Tokendienst abgerufen.
- Die GetToken-Methode verwendet den Tokendienstclient, um ein Zugriffstoken für den aktuellen Benutzer abzurufen. Die -Methode verwendet einen magischen Code, um die Authentizität der Anforderung zu überprüfen.
- Die HasToken-Methode überprüft, ob die Antwort des Tokendiensts ein Zugriffstoken enthält. Wenn das Token nicht NULL oder leer ist, gibt die Methode true zurück.
Aktualisieren Sie als Nächstes den Nachrichtenerweiterungscode, um die Hilfsmethoden zum Authentifizieren von Benutzerabfragen zu verwenden.
Öffnen Sie im Ordner SucheSearchApp.cs
Fügen Sie am Anfang der Datei die folgende using-Anweisung hinzu:
using Microsoft.Bot.Connector.Authentication;
Fügen Sie in der OnTeamsMessagingExtensionQueryAsync-Methode den folgenden Code am Anfang der Methode hinzu:
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); }
Save your changes
Fügen Sie als Nächstes die Tokendienstdomäne der App-Manifestdatei hinzu, um sicherzustellen, dass der Client der Domäne vertrauen kann, wenn ein SSO-Flow initiiert wird.
Im Projekt TeamsApp:
Öffnen Sie im Ordner appPackagemanifest.json
Aktualisieren Sie in der Datei das ValidDomains-Array , und fügen Sie die Domäne des Tokendiensts hinzu:
"validDomains": [ "token.botframework.com", "${{BOT_DOMAIN}}" ]
Save your changes
Erstellen und Aktualisieren von Ressourcen
Wenn alles vorhanden ist, führen Sie den Prozess Vorbereiten von Teams-App-Abhängigkeiten aus, um neue Ressourcen zu erstellen und vorhandene ressourcen zu aktualisieren.
Fahren Sie in Visual Studio fort:
- Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt TeamsApp .
- Erweitern Sie das Menü Teams Toolkit, wählen Sie Teams-App-Abhängigkeiten vorbereiten
- Wählen Sie im Dialogfeld Microsoft 365-KontoWeiteraus.
- Wählen Sie im Dialogfeld Bereitstellen die Option Bereitstellenaus.
- Wählen Sie im Warndialogfeld Teams ToolkitBereitstellenaus.
- Wählen Sie im Dialogfeld Informationen zum Teams-Toolkit das Kreuzsymbol aus, um das Dialogfeld zu schließen.
Ausführen und Debuggen
Starten Sie mit den bereitgestellten Ressourcen eine Debugsitzung, um die Nachrichtenerweiterung zu testen.
Um eine neue Debugsitzung zu starten, drücken Sie F5 , oder wählen Sie auf der Symbolleiste Start aus.
Warten Sie, bis ein Browserfenster geöffnet wird und das Dialogfeld für die App-Installation im Microsoft Teams-Webclient angezeigt wird. Wenn Sie dazu aufgefordert werden, geben Sie die Anmeldeinformationen Ihres Microsoft 365-Kontos ein.
Wählen Sie im Dialogfeld „App-Installation“ Hinzufügen aus
Öffnen Sie einen neuen oder vorhandenen Microsoft Teams-Chat
Wählen Sie im Nachrichtenerstellungsbereich aus + , um die App-Auswahl zu öffnen.
Wählen Sie in der Liste der Apps Contoso-Produkte aus, um die Nachrichtenerweiterung zu öffnen
Geben Sie im Textfeld hello ein.
Die Meldung You'll need to sign in to use this app (Sie müssen sich anmelden, um diese App verwenden zu können ) wird angezeigt.
Folgen Sie dem Anmeldelink , um den Authentifizierungsablauf zu starten.
Zustimmung zu den angeforderten Berechtigungen und Rückgabe an Microsoft Teams
Warten Sie, bis die Suche abgeschlossen und die Ergebnisse angezeigt werden.
Wählen Sie in der Ergebnisliste Hello aus, um eine Karte in das Feld zum Verfassen von Nachrichten einzubetten.
Kehren Sie zu Visual Studio zurück, und wählen Sie auf der Symbolleiste Beenden aus, oder drücken Sie UMSCHALT + F5 , um die Debugsitzung zu beenden.