Zum Inhalt

Microsoft Teams-Integration

Ihrer Installation von Drovio Server kann eine Microsoft Teams-Integration hinzugefügt werden. Sie erlaubt Benutzern, Drovio-Sitzungen aus Microsoft Teams heraus zu starten und ihnen beizutreten, über das Verfassenfeld oder per Bot-Befehl. Sie wird als JAR-Datei ausgeliefert, die Sie zu Drovio Server hinzufügen und anschließend konfigurieren. Sie müssen einen Azure Bot sowie eine Anwendung in Microsoft Entra ID erstellen.

Den Bot in Azure registrieren

Die Registrierung des Bots kann über das Azure-Portal, die Azure CLI oder Terraform erfolgen. Alle drei führen zum selben Ergebnis: eine Anwendungsregistrierung, ein Client Secret und eine Azure-Bot-Ressource mit aktiviertem Teams-Kanal.

Die Ressource Azure Bot erstellen

Wählen Sie im Azure-Portal Create a resource, suchen Sie Azure Bot und klicken Sie dann auf Create.

Feld Wert
Bot handle Ein eindeutiger Name, zum Beispiel Drovio
Subscription Das Abonnement, das belastet werden soll
Resource group Eine neue Gruppe, zum Beispiel Drovio
Pricing tier Free (F0)
Type of app Single Tenant
Creation type Create new Microsoft App ID

Den Bot auf Ihren Server verweisen lassen

Öffnen Sie die Ressource und dann Settings und Configuration. Tragen Sie unter Messaging endpoint Folgendes ein:

https://<your server>/msteams/api/messages

Öffentlicher Endpunkt

Die Route /msteams/api/messages muss von den Servern von Microsoft aus per HTTPS erreichbar sein. Wenn Ihr Drovio Server hinter einer Firewall oder einem Reverse-Proxy steht, achten Sie darauf, diesen Pfad zum Internet hin zu öffnen.

Übernehmen Sie die Einstellung, gehen Sie dann zu Settings und Channels und fügen Sie Microsoft Teams hinzu.

Die drei Werte erfassen, die das Plugin benötigt

Klicken Sie weiterhin unter Settings und Configuration auf Manage Password neben der Microsoft App ID. Damit öffnet sich die Anwendungsregistrierung in Microsoft Entra ID.

Notieren Sie im Bereich Overview:

Wert in Azure Verwendet als
Application (client) ID client_id
Directory (tenant) ID tenant_id

Gehen Sie anschließend zu Certificates & secrets, Registerkarte Client secrets, und klicken Sie auf New client secret. Kopieren Sie die Spalte Value sofort: Sie wird nur einmal angezeigt, und Sie müssen ein neues Secret erzeugen, wenn Sie sie verpassen. Das ist das client_secret.

Die API bereitstellen und Zugriff auf Graph gewähren

Klicken Sie unter Expose an API auf Set neben der Application ID URI und dann auf Save.

Fügen Sie unter API permissions eine Berechtigung für Microsoft Graph hinzu, wählen Sie Application permissions und dort die beiden weiter unten aufgeführten Berechtigungen. Erteilen Sie ihnen die Administratorzustimmung.

Die Redirect-URI eintragen

Nur nötig, wenn Sie die App über die Administrationsoberfläche veröffentlichen möchten, statt sie selbst hochzuladen.

Wählen Sie unter Authentication die Option Add a platform, dann Web, und fügen Sie die Redirect-URI hinzu:

https://<your server>/admin/access/msteams/publish/callback

Fehlt sie, scheitert die Veröffentlichung mit AADSTS500113: No reply address is registered for the application. Wenn der Zugriff auf die Administration auf diesem Server per IP-Adresse eingeschränkt ist, muss auch die Adresse zugelassen sein, von der aus der Browser zurückkommt, sonst wird der Rückweg mit einem 403 abgewiesen.

Ersetzen Sie <your server> durch die öffentliche URL Ihrer Instanz und wählen Sie Ihre eigene Ressourcengruppe und Region.

Hier kommt die Anwendung vor dem Bot

Das Portal erstellt die Anwendungsregistrierung und den Bot in einem einzigen Formular. Die CLI kann das nicht: az bot create verlangt die Anwendungs-ID als Pflichtargument, die Registrierung muss also zuerst vorhanden sein. Das Endergebnis ist identisch.

Legen Sie zuerst die fünf Namen fest, der Rest der Befehle lässt sich anschließend unverändert einfügen:

Variable Was sie benennt
SERVER Die öffentliche URL Ihres Drovio Server
APP_NAME Der Anzeigename der Anwendungsregistrierung
BOT_NAME Die Bot-Ressource, die azureweit frei sein muss
GROUP Die Ressourcengruppe, die den Bot enthält
LOCATION Die Region der Ressourcengruppe
SERVER=https://<your server>
APP_NAME=Drovio
BOT_NAME=Drovio
GROUP=Drovio
LOCATION=westeurope

Erstellen Sie die Anwendungsregistrierung, ihren Dienstprinzipal, ihre Application ID URI und ihr Client Secret:

APP_ID=$(az ad app create \
  --display-name "$APP_NAME" \
  --sign-in-audience AzureADMyOrg \
  --web-redirect-uris "$SERVER/admin/access/msteams/publish/callback" \
  --query appId --output tsv)

TENANT_ID=$(az account show --query tenantId --output tsv)

az ad sp create --id "$APP_ID"

az ad app update --id "$APP_ID" --identifier-uris "api://$APP_ID"

CLIENT_SECRET=$(az ad app credential reset --id "$APP_ID" --append \
  --display-name drovio-server --query password --output tsv)

Die Zeile az ad sp create entspricht dem Schritt, den das Portal vor Ihnen verbirgt. Sie erstellt den Dienstprinzipal, dem die Berechtigungen erteilt werden, und ohne ihn scheitert die Administratorzustimmung. Die Identifier-URI ist das Ziel, auf das das Teams-Manifest verweist. Das Client Secret wird nur einmal angezeigt, bewahren Sie also auf, was der letzte Befehl erfasst.

Fordern Sie die beiden Graph-Berechtigungen an, über ihren Namen aufgelöst, damit kein Bezeichner abgetippt werden muss. Die Zustimmung folgt später, am Ende dieser Registerkarte:

GRAPH_ID=00000003-0000-0000-c000-000000000000

USER_READ=$(az ad sp show --id $GRAPH_ID \
  --query "appRoles[?value=='User.Read.All'].id | [0]" --output tsv)
CATALOG_READ=$(az ad sp show --id $GRAPH_ID \
  --query "appRoles[?value=='AppCatalog.Read.All'].id | [0]" --output tsv)

az ad app permission add --id "$APP_ID" --api $GRAPH_ID \
  --api-permissions "$USER_READ=Role" "$CATALOG_READ=Role"

Dieser Befehl gibt einen Hinweis aus, der Sie zum Ausführen von az ad app permission grant auffordert: Ignorieren Sie ihn, dieser Befehl betrifft delegierte Berechtigungen, während es sich hier um zwei Anwendungsberechtigungen handelt.

Dann die Bot-Ressource selbst und ihr Teams-Kanal:

az group create --name "$GROUP" --location "$LOCATION"

az bot create \
  --name "$BOT_NAME" \
  --resource-group "$GROUP" \
  --app-type SingleTenant \
  --appid "$APP_ID" \
  --tenant-id "$TENANT_ID" \
  --endpoint "$SERVER/msteams/api/messages" \
  --sku F0

az bot msteams create --name "$BOT_NAME" --resource-group "$GROUP"

echo "client_id     $APP_ID (Application ID)"
echo "tenant_id     $TENANT_ID (Directory ID)"
echo "client_secret $CLIENT_SECRET"

Die Zustimmung zuletzt erteilen

Die Zustimmung ist der letzte Schritt, und sie muss überprüft werden. Microsoft Entra ID benötigt die Anwendungsregistrierung, ihren Dienstprinzipal und die angeforderten Berechtigungen in propagiertem Zustand, bevor es darauf einwirken kann. Zu früh ausgeführt, meldet der Befehl keinen Fehler und erteilt nichts:

az ad app permission admin-consent --id "$APP_ID"

SP_ID=$(az ad sp show --id "$APP_ID" --query id --output tsv)
az rest --method GET \
  --url "https://graph.microsoft.com/v1.0/servicePrincipals/$SP_ID/appRoleAssignments" \
  --query "length(value)" --output tsv

Der letzte Befehl muss 2 ausgeben. Gibt er 0 aus, warten Sie eine Minute und führen Sie beide erneut aus. Das Erteilen der Zustimmung erfordert die Rolle Privileged Role Administrator oder Global Administrator.

Das Portal ist der zuverlässige Ausweg

Bleibt der Zähler bei 0, öffnen Sie die Anwendungsregistrierung in Microsoft Entra ID, gehen Sie zu API permissions und klicken Sie auf Grant admin consent for <Ihr Tenant>. Die Spalte Status zeigt dann Granted an, und der obige Befehl gibt 2 aus.

Dieselbe Einrichtung für eine Infrastruktur, die bereits als Code beschrieben ist. Sie setzt den Provider azuread in Version 3 oder höher voraus, mit der die kleinen, kombinierbaren Anwendungsressourcen eingeführt wurden. Die folgenden Dateien bilden ein einziges Root-Modul.

terraform {
  required_version = ">= 1.0.0, < 2.0.0"

  required_providers {
    azuread = {
      source  = "hashicorp/azuread"
      version = "~> 3.0"
    }
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
  }
}
provider "azurerm" {
  subscription_id = var.subscription_id
  features {}
}
variable "subscription_id" {
  description = "Azure subscription hosting the bot resource"
  type        = string
}

variable "server_url" {
  description = "Public URL of the Drovio Server instance, without a trailing slash"
  type        = string
}
data "azuread_client_config" "current" {}

data "azuread_application_published_app_ids" "well_known" {}

data "azuread_service_principal" "msgraph" {
  client_id = data.azuread_application_published_app_ids.well_known.result["MicrosoftGraph"]
}
resource "azuread_application_registration" "drovio" {
  display_name     = "Drovio"
  sign_in_audience = "AzureADMyOrg"
}

resource "azuread_application_identifier_uri" "drovio" {
  application_id = azuread_application_registration.drovio.id
  identifier_uri = "api://${azuread_application_registration.drovio.client_id}"
}

resource "azuread_application_redirect_uris" "drovio" {
  application_id = azuread_application_registration.drovio.id
  type           = "Web"
  redirect_uris  = ["${var.server_url}/admin/access/msteams/publish/callback"]
}

resource "azuread_application_api_access" "drovio" {
  application_id = azuread_application_registration.drovio.id
  api_client_id  = data.azuread_application_published_app_ids.well_known.result["MicrosoftGraph"]

  role_ids = [
    data.azuread_service_principal.msgraph.app_role_ids["User.Read.All"],
    data.azuread_service_principal.msgraph.app_role_ids["AppCatalog.Read.All"],
  ]
}

resource "azuread_application_password" "drovio" {
  application_id = azuread_application_registration.drovio.id
}

resource "azuread_service_principal" "drovio" {
  client_id = azuread_application_registration.drovio.client_id
}

# The two assignments below are the admin consent
resource "azuread_app_role_assignment" "user_read_all" {
  app_role_id         = data.azuread_service_principal.msgraph.app_role_ids["User.Read.All"]
  principal_object_id = azuread_service_principal.drovio.object_id
  resource_object_id  = data.azuread_service_principal.msgraph.object_id
}

resource "azuread_app_role_assignment" "app_catalog_read_all" {
  app_role_id         = data.azuread_service_principal.msgraph.app_role_ids["AppCatalog.Read.All"]
  principal_object_id = azuread_service_principal.drovio.object_id
  resource_object_id  = data.azuread_service_principal.msgraph.object_id
}

resource "azurerm_resource_group" "drovio" {
  name     = "Drovio"
  location = "West Europe"
}

resource "azurerm_bot_service_azure_bot" "drovio" {
  name                    = "Drovio"
  resource_group_name     = azurerm_resource_group.drovio.name
  location                = "global"
  sku                     = "F0"
  microsoft_app_id        = azuread_application_registration.drovio.client_id
  microsoft_app_type      = "SingleTenant"
  microsoft_app_tenant_id = data.azuread_client_config.current.tenant_id
  endpoint                = "${var.server_url}/msteams/api/messages"
}

resource "azurerm_bot_channel_ms_teams" "drovio" {
  bot_name            = azurerm_bot_service_azure_bot.drovio.name
  location            = azurerm_bot_service_azure_bot.drovio.location
  resource_group_name = azurerm_resource_group.drovio.name
}
output "client_id" {
  description = "Application (client) ID, for the plugin configuration"
  value       = azuread_application_registration.drovio.client_id
}

output "tenant_id" {
  description = "Directory (tenant) ID, for the plugin configuration"
  value       = data.azuread_client_config.current.tenant_id
}

output "client_secret" {
  description = "Client secret, for the plugin configuration"
  value       = azuread_application_password.drovio.value
  sensitive   = true
}

Drei Dinge, die Sie vor dem Anwenden wissen sollten:

  • Das Client Secret landet im Terraform-State, der damit ein Anmeldedatum für Ihren Tenant enthält und entsprechend geschützt werden muss. Entfernen Sie die Ressource azuread_application_password und erstellen Sie das Secret von Hand, wenn das dort, wo Sie Ihren State ablegen, nicht akzeptabel ist.
  • Die beiden Ressourcen azuread_app_role_assignment leisten das, was Grant admin consent im Portal tut. Die Identität, die Terraform ausführt, benötigt die Rolle Privileged Role Administrator oder Global Administrator, um sie anzulegen.
  • azurerm_bot_service_azure_bot ist die Azure-Bot-Ressource. Verwenden Sie nicht die ältere Ressource azurerm_bot_channels_registration, die die vorherige Generation der Bot-Registrierung beschreibt.

Ein Single-Tenant-Bot bedient Ihren eigenen Tenant, und genau das braucht eine selbst gehostete Bereitstellung. Die Multi-Tenant-Verteilung in die Tenants Ihrer Kunden ist ein eigenes Thema, das über AppSource läuft.

Unabhängig von der gewählten Methode ist der Bot-Name zwischen 4 und 42 Zeichen lang und muss azureweit frei sein, sodass Drovio allein bereits vergeben sein kann. Die Bot-Ressource selbst liegt am Standort global, unabhängig von der Region ihrer Ressourcengruppe.

Das Client Secret läuft ab

Dasselbe Secret authentifiziert den Bot, wenn er in Teams antwortet, und das Plugin, wenn es Graph aufruft. Nach dem Ablauf antwortet die App nicht mehr und die Oberfläche verliert den Blick auf den Katalog, bis ein neues Secret in der Administrationsoberfläche eingetragen wird. Wie lange es gilt, hängt davon ab, wie Sie es erstellt haben:

Methode Gültigkeitsdauer
Portal Nach Ihrer Wahl, höchstens 24 Monate, wobei Microsoft weniger als 12 empfiehlt
Azure CLI Ein Jahr, änderbar über --years bei az ad app credential reset
Terraform Zwei Jahre, der Standardwert von Microsoft Entra ID, wenn end_date_relative weggelassen wird

Notieren Sie sich das Ablaufdatum und planen Sie die Rotation: erst das neue Secret erstellen, dann in die Oberfläche einfügen.

Free oder Standard

Die Stufe Free (F0) erlaubt 10.000 Nachrichten pro Monat auf Premium-Kanälen, was für die meisten selbst gehosteten Bereitstellungen ausreicht. Wechseln Sie zu Standard (S1), wenn Sie höhere Volumen erwarten.

Graph-Berechtigungen

Berechtigung Was sie bringt Ohne sie
User.Read.All Die Namen und Fotos der Teilnehmer Die Integration funktioniert, die Karten zeigen kein Foto
AppCatalog.Read.All Die Oberfläche liest den App-Katalog Ihrer Organisation Die Oberfläche sagt nichts über den Katalog, und ihre Schaltfläche bietet Veröffentlichen oder Aktualisieren an, ohne zu wissen, welches von beiden

Beides sind Anwendungsberechtigungen, und beide erfordern die Administratorzustimmung. Das Plugin fordert bei jedem Lesen des Katalogs ein neues Token an, sodass eine bei laufendem Server erteilte Zustimmung schon beim nächsten Lesen greift, ohne Neustart.

Die Veröffentlichung erfordert eine dritte Berechtigung, die delegierte AppCatalog.ReadWrite.All, und sie funktioniert anders. Sie wird nicht auf der Anwendungsregistrierung deklariert: Die Administrationsoberfläche fordert sie in dem Moment an, in dem Sie zu veröffentlichen versuchen.

Das Plugin installieren

Kopieren Sie drovio-teams.jar in den Paketordner des Servers und deklarieren Sie es dann in settings.conf:

"plugin_management": {
  "plugins": [
    {
      "classpath": "/opt/drovio-server/packages/drovio-teams.jar",
      "path": "com.drovio.server.teams",
      "ext": "java",
      "base_address": "drovio.server.msteams"
    }
  ]
}

Der Schlüssel lautet plugin_management. plugin_manager zu schreiben ergibt ein Plugin, das nie geladen wird, ohne dass eine Fehlermeldung darauf hinweist. Die base_address lautet drovio.server.msteams, eine Adresse, die die Drovio App und der Server beide in ihrem Code verwenden.

Starten Sie den Server neu. In der Administrationsoberfläche erscheint ein Eintrag Microsoft Teams, und er erscheint nur, wenn das Plugin geladen ist.

Warum hier ein Neustart nötig ist

Der größte Teil der Konfiguration von Drovio Server wird im laufenden Betrieb übernommen, Plugins werden jedoch nur beim Start geladen. Jede Änderung an plugin_management, auch die dieses Plugins, wird erst beim nächsten Neustart wirksam.

Die Integration konfigurieren

Öffnen Sie den Eintrag Microsoft Teams der Administrationsoberfläche.

Feld Woher es kommt
Status Enabled oder Disabled
Application ID Die in Azure notierte client_id
Client secret Das Secret, das Sie kopiert haben
Tenant ID Die in Azure notierte tenant_id
Launch URI Vorausgefüllt aus der Server-URL
Join URI Vorausgefüllt aus der Server-URL

Das Speichern schreibt die Werte in die Serverkonfiguration und wirkt ab dem nächsten Aufruf, ohne Neustart. Das Client Secret wird nie wieder angezeigt: Wenn Sie das Feld leer lassen, bleibt das gespeicherte erhalten.

Vor 3.6.6 erforderte eine Änderung der Application ID einen Neustart

Frühere Versionen lasen sie nur einmal beim Start des Servers. Der Bot prüfte eingehende Aufrufe daher weiterhin gegen den alten Wert und beantwortete jede Anfrage mit 401, protokolliert als Bot authentication failed: Invalid JWT audience.

Den Status auf Disabled zu setzen stoppt den Bot und die Aktionen aus der Drovio App, lässt diese Oberfläche aber weiterhin zugänglich, um die Integration zu konfigurieren.

Konfigurationsreferenz

Dies sind die Schlüssel des Elements msteams in settings.conf, falls Sie es lieber direkt bearbeiten.

Das Plugin schreibt dieses Element beim ersten Start, bei dem es keines vorfindet, selbst. So kann ein Server mit dem Plugin bereitgestellt und vollständig über die Oberfläche konfiguriert werden.

Schlüssel Standard Bedeutung
enabled false Aktiviert die Integration. Fehlt der Schlüssel, gilt false
client_id Application (client) ID des Bots
client_secret Client Secret des Bots
tenant_id Directory (tenant) ID. Leer bezeichnet er einen Multi-Tenant-Bot, dessen Erstellung Microsoft seit Juli 2025 nicht mehr vorsieht
launch_uri <Server-URL>/launch Die Adresse, an die eine Teams-Karte einen Benutzer schickt, um einen Anruf zu starten
join_uri <Server-URL>/join/app Die Adresse, an die eine Teams-Karte einen Benutzer schickt, um einem Anruf beizutreten

Die Teams-App erstellen und veröffentlichen

Die App ist ein ZIP-Archiv, das das Manifest und die Symbole enthält. Der Abschnitt App package der Administrationsoberfläche erlaubt es, sie zu erstellen.

Feld Hinweise
Application ID Vorausgefüllt aus der Konfiguration
Application ID URI Vorausgefüllt mit api://<app id>. Ändern Sie den Wert nur, wenn Entra ID eine andere URI bereitstellt
Version Wird mit dem Plugin geliefert und zur Information angezeigt. Erst die Aktualisierung des Plugins veröffentlicht eine neue Version

Download liefert Ihnen das Archiv, das Sie selbst über das Teams Admin Center hochladen.

Die andere Schaltfläche meldet Sie bei Microsoft an und legt die App direkt im Katalog Ihrer Organisation ab. Ihre Beschriftung richtet sich nach dem Inhalt des Katalogs: Publish, wenn die App nicht darin enthalten ist, Update to x.y.z, wenn er eine ältere Version enthält, und Up to date, wenn nichts zu senden ist. Genau dieses Lesen des Zustands bringt AppCatalog.Read.All. Ohne sie zeigt die Schaltfläche Publish or update an und deckt beide Fälle ab, was ebenso gut funktioniert.

Die Veröffentlichung setzt ein Konto mit der Teams-Administratorrolle voraus: Jedes andere Konto kann die App nur zur Prüfung einreichen, die dann auf eine Genehmigung im Teams Admin Center wartet. Von dieser Anmeldung wird nichts aufbewahrt: Wer erneut veröffentlicht, meldet sich erneut an.

Der Katalog spiegelt die App-Verwaltungsrichtlinien des Tenants wider, die Microsoft innerhalb von 24 bis 48 Stunden nach einer Veröffentlichung anwendet. Eine soeben veröffentlichte App ist daher möglicherweise noch nicht gelistet, und die Oberfläche bietet unter Umständen weiterhin an, sie zu veröffentlichen.

Die App zulassen und leicht auffindbar machen

Gehen Sie im Teams Admin Center zu Teams apps und dann Manage apps, suchen Sie nach Drovio und setzen Sie den Status auf Allowed.

Die App zeigt das Profilbild der Teilnehmer an. Klicken Sie auf der Registerkarte Permissions auf Review permissions und erteilen Sie sie.

Um die App Ihren Benutzern sichtbar zu machen, gehen Sie zu Teams apps und dann Setup policies. Bearbeiten Sie die Richtlinie Global (Org-wide default) oder erstellen Sie eine neue und weisen Sie sie einer Gruppe zu. Fügen Sie unter Pinned apps Drovio hinzu und ordnen Sie es im Bereich Messaging extensions ein.

Wissenswertes zu Anheftungsrichtlinien

  • Die App öffnet sich über das + des Verfassenfelds. Der aktuelle Teams-Client zeigt die Symbole von Nachrichtenerweiterungen nicht mehr neben diesem Feld an. Es gibt also kein Symbol, das davor angeheftet werden könnte. Die Richtlinie legt die Reihenfolge innerhalb des +-Menüs fest, und genau das setzt Drovio an die erste Stelle.
  • Eine Richtlinienänderung braucht einige Stunden, bis sie die Clients erreicht, ein Zurücknehmen ebenso.
  • User pinning deaktiviert zu lassen entfernt die Anheftungen, die Ihre Benutzer selbst vorgenommen haben.