【问题标题】:ValidationTokens Missing in Notification received from Microsoft Graph Webhook从 Microsoft Graph Webhook 收到的通知中缺少 ValidationTokens
【发布时间】:2021-09-10 22:55:13
【问题描述】:

我们正在使用 Microsoft Graph(测试版)Webhook 来获取有关 Microsoft Teams 中的状态更改的通知,并且目前我们的客户遇到了问题。 当我们从 Graph API 接收到存在更改通知时,它不包含 validationTokens 属性,因此验证和后续处理失败。 我们的代码类似于微软提供的sample

客户收到的请求的(简化/缩短的)内容如下所示:

{
   "value": [
      {
         "subscriptionId": "...",
         "clientState": "...",
         "changeType": "updated",
         "resource": "communications/presences?$filter=id+in+(...)",
         "subscriptionExpirationDateTime": "2021-04-22T02:06:56.2872368-07:00",
         "resourceData": {
            "@odata.id": "communications/presences?$filter=id+in+(...)",
            "@odata.type": "#Microsoft.Graph.presence",
            "id": "..."
         },
         "tenantId": "...",
         "encryptedContent": {
            "data": "...",
            "dataSignature": "...",
            "dataKey": "...",
            "encryptionCertificateId": "3",
            "encryptionCertificateThumbprint": "..."
         }
      }
   ]
}

与我们的实验室相比,请求正文缺少validationTokens 属性:

{
   "value": [
      {
         "subscriptionId": "...",
         "clientState": "...",
         "changeType": "updated",
         "resource": "communications/presences?$filter=id+in+(...)",
         "subscriptionExpirationDateTime": "2021-04-26T00:07:08.9251516-07:00",
         "resourceData": {
            "@odata.id": "communications/presences?$filter=id+in+(...)",
            "@odata.type": "#Microsoft.Graph.presence",
            "id": "..."
         },
         "tenantId": "...",
         "encryptedContent": {
            "data": "...",
            "dataSignature": "...",
            "dataKey": "...",
            "encryptionCertificateId": "3",
            "encryptionCertificateThumbprint": "..."
         }
      }
   ],
   "validationTokens": [
      "..."
   ]
}

根据docvalidationTokens 仅提供给带有资源数据的更改通知——这里就是这种情况,所以我们猜测应该存在validationTokens

欢迎任何提示。

编辑 这是一个用于反序列化请求正文/处理通知请求的简短代码:

      <HttpPost("/Notification/{connectorId}/{apiLinkId}")>
      Public Async Function Listen(connectorId As Guid, apiLinkId As Guid, <FromQuery> Optional validationToken As String = Nothing) As Task(Of IActionResult)
         If Not String.IsNullOrEmpty(validationToken) Then
            ' Validate the new subscription by sending the token back to Microsoft Graph.
            ' This response is required for each subscription.
            Return Content(WebUtility.HtmlEncode(validationToken))
         End If

         Try
            ' Parse the received notifications.
            Dim options As New JsonSerializerOptions With {.PropertyNameCaseInsensitive = True}
            options.Converters.Add(New JsonStringEnumConverter(JsonNamingPolicy.CamelCase))

            Dim plainNotifications As New Dictionary(Of String, ChangeNotification)()
            Dim notificationCollection = Await JsonSerializer.DeserializeAsync(Of ChangeNotificationCollection)(Request.Body, options)
            notificationCollection.Value _
               .Where(Function(x) x.EncryptedContent Is Nothing) _
               .ForEach(Sub(notification)
                           Dim subscription = Stores.TeamsPresenceSubscriptionStore.Instance.GetValueOrDefault(notification.SubscriptionId.Value)

                           ' Verify the current client state matches the one that was sent.
                           If subscription Is Nothing OrElse notification.ClientState <> subscription.SecretClientState Then
                              Log.msg(Category.TEAMS, "Error: Failed to verify notification")
                              Return
                           End If

                           ' Just keep the latest notification for each resource. No point pulling data more than once.
                           plainNotifications(notification.Resource) = notification
                        End Sub)

            If plainNotifications.Count > 0 Then
               ' Query for the changed messages
               GetChangedMessages(plainNotifications.Values)
            End If

            If notificationCollection.ValidationTokens IsNot Nothing AndAlso notificationCollection.ValidationTokens.Any() Then
               ' -> notificationCollection.ValidationTokens is not set at the customer
            End If

         Catch ex As Exception
            ' Still return a 202 so the service doesn't resend the notification.
         End Try
         Return Accepted()
      End Function

创建订阅的代码是

         Subscription = graphApi.Client.Subscriptions.Request().AddAsync(New Subscription() With
            {
               .Resource = $"/communications/presences?$filter=id in ({String.Join(",", userIds.Select(Function(id) $"'{id}'"))})",
               .ChangeType = "updated",
               .NotificationUrl = $"{publicNotificationEndpoint}/Notification/{connectorid}/{Me.GraphApi.Link.Id}",
               .LifecycleNotificationUrl = $"{publicNotificationEndpoint}/LifecycleNotification/{connectorid}/{Me.GraphApi.Link.Id}",
               .ClientState = SecretClientState,
               .ExpirationDateTime = DateTime.UtcNow.Add(MAX_SUBSCRIPTION_LIFETIME),
               .EncryptionCertificate = Convert.ToBase64String(encryptionCertificate.Export(X509ContentType.Cert)),
               .EncryptionCertificateId = encryptionCertificate.Version.ToString(),
               .IncludeResourceData = True
            }).Result

【问题讨论】:

  • 只是为了隔离问题,您可以尝试使用 Graph Explorer 或 POSTMAN 重现问题,看看您是否看到不同的结果。
  • 嗨@hypetsch,你能分享一下你用来获取validationTokens的代码吗?
  • @Jagadeesh-MSFT - 根据要求,我添加了上面的(简化)代码,但如前所述,validationTokens 不是我们在通知中收到的 JSON 内容的一部分。我在问题中添加的 JSON 实际上是通过 Wireshark 捕获的格式化/缩短的内容。无论如何,我标记了未设置 .validationTokens 属性的位置。
  • 嗨@hypetsch,你还面临这个问题吗
  • 我们同时实施了一种解决方法(并忽略验证令牌)。我会要求我们的服务部门联系客户,询问他们是否可以尝试。

标签: microsoft-graph-api microsoft-teams microsoft-graph-teams


【解决方案1】:

我认为这就是您正在寻找使用更改通知 API 订阅存在 API 的内容,我们在 csharp 和节点 js 中开发了示例,它们能够在存在更新时通知用户,您可以看看按照您的方案的 github 示例代码仓库 graph-change-notification

【讨论】:

  • 感谢您的回复,但在我们的案例中,问题只是缺少收到的通知中的“validationTokens”(仅在特定客户处,而对其他人工作正常) - 并且我们理解文档的方式,如果存在资源docs.microsoft.com/en-us/graph/api/resources/…,它们应该在那里
  • ...收到的状态数据很好(也在这个客户处) - 所以我们的解决方法是在不先验证收到的请求的情况下处理数据。
【解决方案2】:

这是一种迟到的回复,但validationToken 只会在订阅创建时发送到webhook,之后微软开始发送更改通知,并且不会有任何validationToken 与更改通知一起发送。这样做只是为了确保通知端点有效/活跃。

Notification endpoint validation

SS 取自:https://docs.microsoft.com/en-us/graph/webhooks

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-15
    相关资源
    最近更新 更多