Freigeben über


Einrichten von Microsoft Graph-Änderungsbenachrichtigungen mit Ressourcendaten

Microsoft Graph ermöglicht Apps das Abonnieren und Empfangen von Benachrichtigungen über Änderungen an Ressourcen. In diesem Artikel wird erläutert, wie Sie umfangreiche Benachrichtigungen einrichten, die Ressourcendaten direkt in der Benachrichtigungsnutzlast enthalten.

Umfangreiche Benachrichtigungen erfordern keine zusätzlichen API-Aufrufe, um aktualisierte Ressourcen zu erhalten, sodass geschäftslogik schneller und einfacher ausgeführt werden kann.

Unterstützte Ressourcen

Umfangreiche Benachrichtigungen sind für die folgenden Ressourcen verfügbar.

Hinweis

Umfangreiche Benachrichtigungen für Abonnements für Endpunkte, die mit einem Sternchen (*) gekennzeichnet sind, sind nur auf dem /beta Endpunkt verfügbar.

Ressource Unterstützte Ressourcenpfade Begrenzungen
Copilot aiInteraction Copilot KI-Interaktionen, an denen ein bestimmter Benutzer Teil ist: copilot/users/{userId}/interactionHistory/getAllEnterpriseInteractions

Copilot KI-Interaktionen in einem organization:copilot/interactionHistory/getAllEnterpriseInteractions
Maximale Abonnementkontingente:
  • Kombination aus App und Mandant (für Abonnements, die KI-Interaktionen über einen Mandanten hinweg nachverfolgen): 1
  • Kombination aus App und Benutzer (für Abonnements, in der KI-Interaktionen nachverfolgt werden, an der ein bestimmter Benutzer beteiligt ist): 1
  • Pro Benutzer (für Abonnements, die KI-Interaktionen nachverfolgen, zu der ein bestimmter Benutzer gehört): 10 Abonnements.
  • Pro organization: insgesamt 10.000 Abonnements.
  • Outlook-Ereignis Änderungen an allen Ereignissen im Postfach eines Benutzers: /users/{id}/events Erfordert $select , dass nur eine Teilmenge der Eigenschaften in der rich-Benachrichtigung zurückgegeben wird. Weitere Informationen finden Sie unter Ändern von Benachrichtigungen für Outlook-Ressourcen.
    Outlook-Nachricht Änderungen an allen Nachrichten im Postfach eines Benutzers: /users/{id}/messages

    Änderungen an Nachrichten im Posteingang eines Benutzers: /users/{id}/mailFolders/{id}/messages
    Erfordert $select , dass nur eine Teilmenge der Eigenschaften in der rich-Benachrichtigung zurückgegeben wird. Weitere Informationen finden Sie unter Ändern von Benachrichtigungen für Outlook-Ressourcen.
    Persönlicher Outlook-Kontakt Änderungen an allen persönlichen Kontakten im Postfach eines Benutzers: /users/{id}/contacts

    Änderungen an allen persönlichen Kontakten im contactFolder eines Benutzers: /users/{id}/contactFolders/{id}/contacts
    Erfordert $select , dass nur eine Teilmenge der Eigenschaften in der rich-Benachrichtigung zurückgegeben wird. Weitere Informationen finden Sie unter Ändern von Benachrichtigungen für Outlook-Ressourcen.
    Teams-AnrufAufzeichnung Alle Aufzeichnungen in einem organization:communications/onlineMeetings/getAllRecordings

    Alle Aufzeichnungen für eine bestimmte Besprechung: communications/onlineMeetings/{onlineMeetingId}/recordings

    Eine Anrufaufzeichnung, die in einer Besprechung verfügbar wird, die von einem bestimmten Benutzer organisiert wird: users/{id}/onlineMeetings/getAllRecordings

    Eine Anrufaufzeichnung, die in einer Besprechung verfügbar wird, in der eine bestimmte Teams-App installiert ist: appCatalogs/teamsApps/{id}/installedToOnlineMeetings/getAllRecordings *
    Maximale Abonnementkontingente:
  • Kombination pro App und Onlinebesprechung: 1
  • Kombination pro App und Benutzer: 1
  • Pro Benutzer (für Abonnements, die Aufzeichnungen in allen onlineMeetings nachverfolgen, die vom Benutzer organisiert werden): 10 Abonnements.
  • Pro organization: insgesamt 10.000 Abonnements.
  • Teams callTranscript Alle Transkripte in einem organization:communications/onlineMeetings/getAllTranscripts

    Alle Transkripte für eine bestimmte Besprechung: communications/onlineMeetings/{onlineMeetingId}/transcripts

    Ein Anruftranskript, das in einer Besprechung verfügbar wird, die von einem bestimmten Benutzer organisiert wird: users/{id}/onlineMeetings/getAllTranscripts

    Ein Anruftranskript, das in einer Besprechung verfügbar wird, in der eine bestimmte Teams-App installiert ist: appCatalogs/teamsApps/{id}/installedToOnlineMeetings/getAllTrancripts *
    Maximale Abonnementkontingente:
  • Kombination pro App und Onlinebesprechung: 1
  • Kombination pro App und Benutzer: 1
  • Pro Benutzer (für Abonnements, die Transkripte in allen vom Benutzer organisierten onlineMeetings nachverfolgen): 10 Abonnements.
  • Pro organization: insgesamt 10.000 Abonnements.
  • Teams channel Änderungen an Kanälen in allen Teams: /teams/getAllChannels

    Änderungen am Kanal in einem bestimmten Team: /teams/{id}/channels
    -
    Teams Chat Änderungen an chatten im Mandanten: /chats

    Änderungen an einem bestimmten Chat: /chats/{id}
    -
    Teams chatMessage Änderungen an Chatnachrichten in allen Kanälen in allen Teams: /teams/getAllMessages

    Änderungen an Chatnachrichten in einem bestimmten Kanal: /teams/{id}/channels/{id}/messages

    Änderungen an Chatnachrichten in allen Chats: /chats/getAllMessages

    Änderungen an Chatnachrichten in einem bestimmten Chat: /chats/{id}/messages

    Änderungen an Chatnachrichten in allen Chats, zu der ein bestimmter Benutzer gehört: /users/{id}/chats/getAllMessages
    Unterstützt nicht die Verwendung von $select , um nur ausgewählte Eigenschaften zurückzugeben. Die rich-Benachrichtigung besteht aus allen Eigenschaften des geänderten instance.
    Teams conversationMember Änderungen an der Mitgliedschaft in einem bestimmten Team: /teams/{id}/members

    Änderungen an der Mitgliedschaft in allen Teams im gesamten Mandanten: /teams/getAllMembers

    Änderungen an der Mitgliedschaft in allen Kanälen unter einem bestimmten Team: /teams/{id}/channels/getAllMembers

    Änderungen an der Mitgliedschaft für alle Kanäle im gesamten Mandanten: /teams/getAllChannels/getAllMembers

    Änderungen an der Mitgliedschaft in einem bestimmten Chat: /chats/{id}/members

    Änderungen an der Mitgliedschaft für alle Teams-Chats: /chats/getAllMembers
    Unterstützt nicht die Verwendung von $select , um nur ausgewählte Eigenschaften zurückzugeben. Die rich-Benachrichtigung besteht aus allen Eigenschaften des geänderten instance.
    Teams onlineMeeting * Änderungen an einer Onlinebesprechung: /communications/onlineMeetings(joinWebUrl='{encodedJoinWebUrl}')/meetingCallEvents * Unterstützt nicht die Verwendung von $select , um nur ausgewählte Eigenschaften zurückzugeben. Die rich-Benachrichtigung besteht aus allen Eigenschaften des geänderten instance. Pro Anwendung und Onlinebesprechung ist ein Abonnement zulässig. Weitere Informationen finden Sie unter Abrufen von Änderungsbenachrichtigungen für Aktualisierungen von Microsoft Teams-Besprechungsanrufereignissen.
    Teams-Anwesenheit Änderungen an der Anwesenheit eines einzelnen Benutzers: /communications/presences/{id}

    Änderungen an der Anwesenheit mehrerer Benutzer: /communications/presences?$filter=id in ({id},{id}...)
    Das Abonnement für die Anwesenheit mehrerer Benutzer ist auf 650 verschiedene Benutzer beschränkt. Unterstützt nicht die Verwendung von $select , um nur ausgewählte Eigenschaften zurückzugeben. Die rich-Benachrichtigung besteht aus allen Eigenschaften des geänderten instance. Pro Anwendung und delegiertem Benutzer ist ein Abonnement zulässig. Weitere Informationen finden Sie unter Abrufen von Änderungsbenachrichtigungen für Anwesenheitsupdates in Microsoft Teams.
    Teams team Änderungen an einem Team im Mandanten: /teams

    Änderungen an einem bestimmten Team: /teams/{id}
    -

    Ressourcendaten in Benachrichtigungs-Nutzlast

    Umfangreiche Benachrichtigungen enthalten Ressourcendaten mit den folgenden Details:

    • Die ID und der Typ der geänderten Ressource instance in der resourceData-Eigenschaft.
    • Alle Eigenschaftswerte der Ressource instance verschlüsselt, wie im Abonnement angegeben, in der encryptedContent-Eigenschaft enthalten.
    • Bestimmte Eigenschaften der Ressource, abhängig von der Ressource, oder wenn dies mithilfe eines $select Parameters in der Ressourcen-URL des Abonnements angefordert wird.

    Erstellen eines Abonnements

    Führen Sie zum Einrichten umfangreicher Benachrichtigungen dieselben Schritte wie grundlegende Änderungsbenachrichtigungen aus, fügen Sie jedoch die folgenden erforderlichen Eigenschaften ein:

    • includeResourceData: Legen Sie dies auf fest true , um Ressourcendaten anzufordern.
    • encryptionCertificate: Geben Sie den öffentlichen Schlüssel an, den Microsoft Graph zum Verschlüsseln der Ressourcendaten verwendet. Weitere Informationen finden Sie unter Entschlüsseln von Ressourcendaten aus Änderungsbenachrichtigungen.
    • encryptionCertificateId: Geben Sie einen Bezeichner für das Zertifikat an, um Benachrichtigungen mit dem richtigen Entschlüsselungsschlüssel abzugleichen.

    Überprüfen Sie beide Endpunkte wie in Überprüfung des Benachrichtigungsendpunkts beschrieben. Wenn Sie dieselbe URL für beide Endpunkte verwenden, erhalten Sie und sollten auf zwei Validierungsanforderungen antworten.

    Beispiel: Abonnementanforderung

    In diesem Beispiel wird ein Abonnement für Kanalnachrichten in Microsoft Teams erstellt.

    POST https://graph.microsoft.com/v1.0/subscriptions
    Content-Type: application/json
    
    {
      "changeType": "created,updated",
      "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
      "resource": "/teams/{id}/channels/{id}/messages",
      "includeResourceData": true,
      "encryptionCertificate": "{base64encodedCertificate}",
      "encryptionCertificateId": "{customId}",
      "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
      "clientState": "{secretClientState}"
    }
    

    Abonnementantwort

    HTTP/1.1 201 Created
    Content-Type: application/json
    
    {
      "changeType": "created,updated",
      "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
      "resource": "/teams/{id}/channels/{id}/messages",
      "includeResourceData": true,
      "encryptionCertificateId": "{customId}",
      "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
      "clientState": "{secretClientState}"
    }
    

    Benachrichtigungen zum Abonnementlebenszyklus

    Ereignisse können den Fluss von Änderungsbenachrichtigungen in einem Abonnement unterbrechen. Lebenszyklusbenachrichtigungen informieren Sie darüber, welche Aktionen sie ergreifen müssen, um den Fluss unterbrechungsfrei zu halten. Im Gegensatz zu Benachrichtigungen zu Ressourcenänderungen konzentrieren sich Lebenszyklusbenachrichtigungen auf den Status des Abonnements.

    Weitere Informationen finden Sie unter Reduzieren fehlender Abonnements und Änderungsbenachrichtigungen.

    Überprüfen der Echtheit von Benachrichtigungen

    Überprüfen Sie immer die Authentizität von Änderungsbenachrichtigungen, bevor Sie sie verarbeiten. Dadurch wird verhindert, dass Ihre App falsche Geschäftslogik auslöst, indem gefälschte Benachrichtigungen von Drittanbietern verwendet werden.

    Überprüfen Sie für grundlegende Benachrichtigungen diese mithilfe des Werts clientState , wie unter Verarbeiten der Änderungsbenachrichtigung erläutert. Führen Sie für umfangreiche Benachrichtigungen zusätzliche Überprüfungsschritte aus.

    Überprüfungstoken in der Änderungsbenachrichtigung

    Umfangreiche Benachrichtigungen umfassen eine validationTokens-Eigenschaft , die ein Array von JSON-Webtoken (JWT) enthält. Jedes Token ist für das App- und Mandantenpaar eindeutig. Eine Änderungsbenachrichtigung kann eine Mischung aus Elementen für verschiedene Apps und Mandanten enthalten, die mit derselben notificationUrl abonniert haben.

    Hinweis

    Microsoft Graph sendet keine Validierungstoken für Änderungsbenachrichtigungen, die über Azure Event Hubs übermittelt werden, da der Abonnementdienst die notificationUrl für Event Hubs nicht überprüfen muss.

    Im folgenden Beispiel enthält die Änderungsbenachrichtigung zwei Elemente für dieselbe App und für zwei verschiedene Mandanten. Daher enthält das validationTokens-Array zwei Token, die validiert werden müssen.

    {
        "value": [
            {
                "subscriptionId": "76619225-ff6b-4489-96ca-4ef547e78b22",
                "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
                "changeType": "created",
                ...
            },
            {
                "subscriptionId": "5cfe2387-163c-4006-81bb-1b5e1e060afe",
                "tenantId": "bbbbcccc-1111-dddd-2222-eeee3333ffff",
                "changeType": "created",
                ...
            }
        ],
        "validationTokens": [
            "eyJ0eXAiOiJKV1QiLCJhb...",
            "cGlkYWNyIjoiMiIsImlkc..."
        ]
    }
    

    Das Änderungsbenachrichtigungsobjekt befindet sich in der Struktur des Ressourcentyps changeNotificationCollection.

    So führen Sie die Validierung durch

    Verwenden Sie die Microsoft Authentication Library (MSAL) oder eine Drittanbieterbibliothek, um Token zu überprüfen. Gehen Sie folgendermaßen vor:

    Beachten Sie die folgenden Prinzipien:

    • Reagieren Sie sofort mit einem HTTP 202 Accepted status Code auf die Benachrichtigung.
    • Reagieren Sie, bevor Sie die Änderungsbenachrichtigung überprüfen, auch wenn die Überprüfung später fehlschlägt. Reagieren Sie sofort nach Erhalt der Änderungsbenachrichtigung, unabhängig davon, ob Sie Benachrichtigungen zur späteren Verarbeitung in Warteschlangen speichern oder direkt verarbeiten.
    • Das Akzeptieren und Reagieren auf eine Änderungsbenachrichtigung verhindert unnötige Übermittlungsversuche und blendet validierungsergebnisse vor potenziellen Angreifern aus. Sie können eine ungültige Änderungsbenachrichtigung jederzeit ignorieren, nachdem Sie sie erhalten haben.

    Führen Sie insbesondere die Überprüfung für jedes JWT-Token in der validationTokens-Sammlung aus. Wenn Token fehlschlagen, betrachten Sie die Änderungsbenachrichtigung als verdächtig und untersuchen Sie sie weiter.

    Führen Sie die folgenden Schritte aus, um Token und die Apps zu überprüfen, die sie generieren:

    1. Überprüfen Sie, ob das Token nicht abgelaufen ist.

    2. Überprüfen Sie, ob das Token vom Microsoft Identity Platform ausgestellt wurde und nicht manipuliert wurde.

      • Beziehen Sie die Signaturschlüssel vom gemeinsamen Konfigurationsendpunkt:https://login.microsoftonline.com/common/.well-known/openid-configuration Ihre App kann diese Konfiguration für einige Zeit zwischenspeichern. Die Konfiguration wird häufig aktualisiert, da Signaturschlüssel täglich rotiert werden.
      • Überprüfen Sie die Signatur des JWT-Tokens mit diesen Schlüsseln.

      Akzeptieren Sie keine Token, die von einer anderen Autorität ausgestellt wurden.

    3. Vergewissern Sie sich, dass das Token für Ihre App ausgestellt wurde.

      Die folgenden Schritte sind Teil der Standardüberprüfungslogik in JWT-Token-Bibliotheken und können normalerweise als einzelner Funktionsaufruf ausgeführt werden.

      • Überprüfen Sie, ob die "Zielgruppe" im Token mit Ihrer App-ID übereinstimmt.
      • Wenn mehr als eine App Änderungsbenachrichtigungen erhält, überprüfen Sie, ob mehrere IDs vorhanden sind.
    4. Überprüfen Sie, ob die -Eigenschaft des azp Tokens mit dem erwarteten Wert von 0bf30f3b-4a52-48df-9a82-234910c4a086übereinstimmt, der den Microsoft Graph-Herausgeber für Änderungsbenachrichtigungen darstellt.

    Beispiel für ein JWT-Token

    Das folgende Beispiel zeigt die Eigenschaften im JWT-Token, die für die Überprüfung erforderlich sind.

    {
      // aud is your app's id
      "aud": "925bff9f-f6e2-4a69-b858-f71ea2b9b6d0",
      "iss": "https://login.microsoftonline.com/9f4ebab6-520d-49c0-85cc-7b25c78d4a93/v2.0",
      "iat": 1624649764,
      "nbf": 1624649764,
      "exp": 1624736464,
      "aio": "E2ZgYGjnuFglnX7mtjJzwR5lYaWvAA==",
      // azp represents the notification publisher and must always be the same value of 0bf30f3b-4a52-48df-9a82-234910c4a086
      "azp": "0bf30f3b-4a52-48df-9a82-234910c4a086",
      "azpacr": "2",
      "oid": "1e7d79fa-7893-4d50-bdde-164260d9c5ba",
      "rh": "0.AX0AtrpOnw1SwEmFzHslx41KkzsP8wtSSt9ImoIjSRDEoIZ9AAA.",
      "sub": "1e7d79fa-7893-4d50-bdde-164260d9c5ba",
      "tid": "9f4ebab6-520d-49c0-85cc-7b25c78d4a93",
      "uti": "mIB4QKCeZE6hK71XUHJ3AA",
      "ver": "2.0"
    }
    

    Beispiel: Überprüfen von Überprüfungstoken

    // add Microsoft.IdentityModel.Protocols.OpenIdConnect and System.IdentityModel.Tokens.Jwt nuget packages to your project
    public async Task<bool> ValidateToken(string token, string tenantId, IEnumerable<string> appIds)
    {
        var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
            "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration",
            new OpenIdConnectConfigurationRetriever());
        var openIdConfig = await configurationManager.GetConfigurationAsync();
        var handler = new JwtSecurityTokenHandler();
        try
        {
        handler.ValidateToken(token, new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateIssuerSigningKey = true,
            ValidateLifetime = true,
            ValidIssuer = $"https://sts.windows.net/{tenantId}/",
            ValidAudiences = appIds,
            IssuerSigningKeys = openIdConfig.SigningKeys
        }, out _);
        return true;
        }
        catch (Exception ex)
        {
        Trace.TraceError($"{ex.Message}:{ex.StackTrace}");
        return false;
        }
    }
    

    Entschlüsseln von Ressourcendaten aus Änderungsbenachrichtigungen

    Die resourceData-Eigenschaft in einer Änderungsbenachrichtigung enthält grundlegende ID- und Typinformationen einer Ressource instance. Die encryptedData-Eigenschaft enthält die vollständigen Ressourcendaten, die von Microsoft Graph mit dem im Abonnement bereitgestellten öffentlichen Schlüssel verschlüsselt wurden. Die Eigenschaft enthält auch Werte, die für die Überprüfung und Entschlüsselung erforderlich sind. Diese Verschlüsselung wird durchgeführt, um die Sicherheit von Kundendaten zu erhöhen, auf die über Änderungsbenachrichtigungen zugegriffen wird. Schützen Sie den privaten Schlüssel, um sicherzustellen, dass ein Drittanbieter Kundendaten nicht entschlüsseln kann, auch wenn er die ursprünglichen Änderungsbenachrichtigungen abfängt.

    In diesem Abschnitt lernen Sie die folgenden Konzepte kennen:

    Verwalten von Verschlüsselungsschlüsseln

    1. Rufen Sie ein Zertifikat mit einem Paar asymmetrischer Schlüssel ab.

      • Sie können ein selbstsigniertes Zertifikat verwenden, da Microsoft Graph den Zertifikataussteller nicht überprüft und den öffentlichen Schlüssel nur für die Verschlüsselung verwendet.

      • Verwenden Sie Azure Key Vault, um Zertifikate zu erstellen, zu rotieren und sicher zu verwalten. Stellen Sie sicher, dass die Schlüssel die folgenden Kriterien erfüllen:

        • Der Schlüssel muss vom Typ RSAsein.
        • Die Schlüsselgröße muss zwischen 2.048 Bit und 4.096 Bits sein.
    2. Exportieren Sie das Zertifikat im Base64-codierten X.509-Format, und fügen Sie nur den öffentlichen Schlüssel ein.

    3. Beim Erstellen eines Abonnements:

      • Geben Sie das Zertifikat in der encryptionCertificate-Eigenschaft an, indem Sie den Base64-codierten Inhalt verwenden, in den das Zertifikat exportiert wurde.

      • Geben Sie Ihre eigene Kennung in der Eigenschaft encryptionCertificateId an.

        Mit dieser Kennung können Sie Ihre Zertifikate mit den empfangenen Änderungsbenachrichtigungen abgleichen und Zertifikate aus Ihrem Zertifikatspeicher abrufen. Die Kennung darf bis zu 128 Zeichen umfassen.

    4. Verwalten Sie den privaten Schlüssel sicher, sodass Ihr Verarbeitungscode für Änderungsbenachrichtigungen auf den privaten Schlüssel zugreifen kann, um Ressourcendaten zu entschlüsseln.

    Rotierende Schlüssel

    Ändern Sie asymmetrische Schlüssel regelmäßig, um das Risiko einer Kompromittierung eines privaten Schlüssels zu minimieren. Befolgen Sie diese Schritte, um ein neues Schlüsselpaar einzuführen:

    1. Beziehen Sie ein neues Zertifikat mit einem neuen Paar asymmetrischer Schlüssel. Verwenden Sie es für alle neuen Abonnements, die erstellt werden.

    2. Aktualisieren Sie vorhandene Abonnements mit dem neuen Zertifikatschlüssel.

      • Machen Sie dieses Update als Teil der regulären Abonnementverlängerung.
      • Oder listen Sie alle Abonnements auf und geben Sie den Schlüssel an. Verwenden Sie den Patch-Vorgang für das Abonnement, und aktualisieren Sie die encryptionCertificate- und encryptionCertificateId-Eigenschaften.
    3. Beachten Sie die folgenden Prinzipien:

      • Das alte Zertifikat wird möglicherweise noch einige Zeit für die Verschlüsselung verwendet. Ihre App muss sowohl auf alte als auch auf neue Zertifikate zugreifen können, um Inhalte entschlüsseln zu können.
      • Verwenden Sie die encryptionCertificateId-Eigenschaft in jeder Änderungsbenachrichtigung, um den zu verwendenden richtigen Schlüssel zu identifizieren.
      • Verwerfen des alten Zertifikats nur, wenn keine aktuellen Änderungsbenachrichtigungen angezeigt werden, die darauf verweisen.

    Entschlüsseln von Ressourcendaten

    Um die Leistung zu optimieren, verwendet Microsoft Graph einen zweistufigen Verschlüsselungsprozess:

    • Es generiert einen symmetrischen Single-Use-Schlüssel und verwendet ihn zum Verschlüsseln von Ressourcendaten.
    • Es verwendet den öffentlichen asymmetrischen Schlüssel (den Sie beim Abonnieren angegeben haben), um den symmetrischen Schlüssel zu verschlüsseln, und bezieht ihn in jede Änderungsbenachrichtigung über dieses Abonnement ein.

    Angenommen, der symmetrische Schlüssel unterscheidet sich für jedes Element in der Änderungsbenachrichtigung.

    Um Ressourcendaten zu entschlüsseln, sollte Ihre App die umgekehrten Schritte ausführen und die Eigenschaften unter encryptedContent in jeder Änderungsbenachrichtigung verwenden:

    1. Identifizieren Sie das richtige Zertifikat mithilfe der EncryptionCertificateId-Eigenschaft .

    2. Initialisieren Sie eine RSA-Kryptografiekomponente mit dem privaten Schlüssel. Eine einfache Möglichkeit zum Initialisieren einer RSA-Komponente besteht darin, die RSACertificateExtensions.GetRSAPrivateKey(X509Certificate2)-Methode mit einem X509Certificate2-instance zu verwenden, der den unter Verwalten von Verschlüsselungsschlüsseln beschriebenen privaten Schlüssel enthält.

    3. Entschlüsseln Sie den symmetrischen Schlüssel in der dataKey-Eigenschaft jedes Elements in der Änderungsbenachrichtigung mit Ihrem privaten Schlüssel. Verwenden Sie Optimal Asymmetric Encryption Padding (OAEP) als Entschlüsselungsalgorithmus.

    4. Verwenden Sie den symmetrischen Schlüssel, um die HMAC-SHA256-Signatur für den Wert in Daten zu berechnen. Vergleichen Sie es mit dem Wert in dataSignature. Wenn sie nicht übereinstimmen, gehen Sie davon aus, dass die Nutzlast manipuliert ist, und entschlüsseln Sie sie nicht.

    5. Entschlüsseln Sie die Dateneigenschaft mithilfe des symmetrischen Schlüssels mit Advanced Encryption Standard (AES), z. B. .NET Aes.

      • Verwenden Sie die folgenden Entschlüsselungsparameter für den AES-Algorithmus:

        • Auffüllung: PKCS7.
        • Verschlüsselungsmodus: CBC.
      • Stellen Sie den "Initialisierungsvektor" ein, indem Sie die ersten 16 Bytes des zur Entschlüsselung verwendeten symmetrischen Schlüssels kopieren.

    Die entschlüsselten Daten sind eine JSON-Zeichenfolge, die die Ressource darstellt.

    Beispiel: Entschlüsseln von Ressourcendaten

    Das folgende JSON-Beispiel zeigt eine Änderungsbenachrichtigung, die verschlüsselte Eigenschaftswerte einer chatMessage-instance in einer Kanalnachricht enthält. Der @odata.id Wert gibt die instance an.

    {
      "value": [
        {
          "subscriptionId": "76222963-cc7b-42d2-882d-8aaa69cb2ba3",
          "changeType": "created",
          // Other properties typical in a resource change notification
          "resource": "teams('d29828b8-c04d-4e2a-b2f6-07da6982f0f0')/channels('19:f127a8c55ad949d1a238464d22f0f99e@thread.skype')/messages('1565045424600')/replies('1565047490246')",
          "resourceData": {
            "id": "1565293727947",
            "@odata.type": "#Microsoft.Graph.ChatMessage",
            "@odata.id": "teams('88cbc8fc-164b-44f0-b6a6-b59b4a1559d3')/channels('19:8d9da062ec7647d4bb1976126e788b47@thread.tacv2')/messages('1565293727947')/replies('1565293727947')"
          },
          "encryptedContent": {
            "data": "{encrypted data that produces a full resource}",
            "dataSignature": "<HMAC-SHA256 hash>",
            "dataKey": "{encrypted symmetric key from Microsoft Graph}",
            "encryptionCertificateId": "MySelfSignedCert/DDC9651A-D7BC-4D74-86BC-A8923584B0AB",
            "encryptionCertificateThumbprint": "07293748CC064953A3052FB978C735FB89E61C3D"
          }
        }
      ],
      "validationTokens": [
        "eyJ0eXAiOiJKV1QiLCJhbGciOiJSU..."
      ]
    }
    

    Eine vollständige Beschreibung der Daten, die beim Senden von Änderungsbenachrichtigungen gesendet werden, finden Sie unter changeNotificationCollection-Ressourcentyp.

    Entschlüsseln des symmetrischen Schlüssels

    Dieser Abschnitt enthält einige nützliche Codefragmente, die C# und .NET für jede Entschlüsselungsstufe verwenden.

    // Initialize with the private key that matches the encryptionCertificateId.
    X509Certificate2 certificate = <instance of X509Certificate2 matching the encryptionCertificateId property>;
    RSA rsa = certificate.GetRSAPrivateKey();
    byte[] encryptedSymmetricKey = Convert.FromBase64String(<value from dataKey property>);
    
    // Decrypt using OAEP padding.
    byte[] decryptedSymmetricKey = rsa.Decrypt(encryptedSymmetricKey, RSAEncryptionPadding.OaepSHA1);
    
    // Can now use decryptedSymmetricKey with the AES algorithm.
    

    Vergleichen von Datensignaturen mit HMAC-SHA256

    byte[] decryptedSymmetricKey = <the aes key decrypted in the previous step>;
    byte[] encryptedPayload = <the value from the data property, still encrypted>;
    byte[] expectedSignature = <the value from the dataSignature property>;
    byte[] actualSignature;
    
    using (HMACSHA256 hmac = new HMACSHA256(decryptedSymmetricKey))
    {
        actualSignature = hmac.ComputeHash(encryptedPayload);
    }
    if (actualSignature.SequenceEqual(expectedSignature))
    {
        // Continue with decryption of the encryptedPayload.
    }
    else
    {
        // Do not attempt to decrypt encryptedPayload. Assume notification payload has been tampered with and investigate.
    }
    

    Entschlüsseln des Inhalts der Ressourcendaten

    Aes aesProvider = Aes.Create();
    aesProvider.Key = decryptedSymmetricKey;
    aesProvider.Padding = PaddingMode.PKCS7;
    aesProvider.Mode = CipherMode.CBC;
    
    // Obtain the initialization vector from the symmetric key itself.
    int vectorSize = 16;
    byte[] iv = new byte[vectorSize];
    Array.Copy(decryptedSymmetricKey, iv, vectorSize);
    aesProvider.IV = iv;
    
    byte[] encryptedPayload = Convert.FromBase64String(<value from data property>);
    
    string decryptedResourceData;
    // Decrypt the resource data content.
    using (var decryptor = aesProvider.CreateDecryptor())
    {
      using (MemoryStream msDecrypt = new MemoryStream(encryptedPayload))
      {
          using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
          {
              using (StreamReader srDecrypt = new StreamReader(csDecrypt))
              {
                  decryptedResourceData = srDecrypt.ReadToEnd();
              }
          }
      }
    }
    
    // decryptedResourceData now contains a JSON string that represents the resource.