ValidationTokens Missing in Notification received from Microsoft Graph Webhook - microsoft-graph-api

We are using Microsoft Graph (beta) Webhooks to get notified about presence changes in Microsoft Teams and have currently an issue at our customer.
When we receive the presence change notification from the Graph API it does not contain the validationTokens property, thus the validation and subsequent processing fails.
Our code is similar to the sample provided by Microsoft.
The (simplified/shortened) content of the received request at the customer looks like the following:
{
"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": "..."
}
}
]
}
Compared to our lab the request body is missing the validationTokens property:
{
"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": [
"..."
]
}
According to the doc, validationTokens are only provided for change notifications with resource data - which is the case here, so we guess the validationTokens should be present?
Any hints are welcome.
Edit
Here is a shortened code snipped used to deserialize the request body/handle the notification request:
<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
The code to create the subscription is
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

I think this is what you are looking for subscribing to the presence API using the Change Notification API, We have developed samples in csharp and node js which have the capability to notify user when presence is updated, You can take a look at following github sample code repo graph-change-notification for your scenario.

Its kind of a late reply but the validationToken will only send to the webhook at the time of Subscription creation, after that Microsoft start sending the chang notifications and there won't be any validationToken send with the change notification. This is done just to ensure that the Notification endpoint is valid/active.
Notification endpoint validation
SS taken from: https://learn.microsoft.com/en-us/graph/webhooks

Related

Azure JSON subprotocol `json.webpubsub.azure.v1`to join a group fetch responses programmatically

I'm trying obtain programmatically if joining the group was successfully when using json.webpubsub.azure.v1 subprotocol to join a group with a sample.
My sample JSON below, which doesn't fetch outcome success response or error response:
Basically, I'm trying to identify if joining the group was successful with the json.webpubsub.azure.v1 subprotocol.
Sample request:
{
"type": "joinGroup",
"group": "group1",
}
Yes, you can, by add “ackId” when joining the group. When the request payload contains “ackId”, the service will return an ack response to the client containing the result for this action. Make sure you use incremental “ackId”s when sending different messages.
Sample request:
{
"type": "joinGroup",
"group": "group1",
"ackId" : 1
}
Sample success response:
{
"type": "ack",
"success": true,
"ackId" : 1
}
Sample error response:
{
"type": "ack",
"success": false,
"ackId" : 1,
"error":
{
"name": "Forbidden",
"description": "The client does not have permission to join group ‘group1’"
}
}

I can't get an image sent by the user on WhatsApp using Twilio

I've done plenty and this is one of the last things to get the chatbot working. I'm trying to receive an image (a selfie) from the user on my WhatsApp chatbot with no success. I'm using Python with Django.
#twilio_view
def visita_selfie(request):
print('VISITA SELFIE')
message_sid = request.POST.get('MessageSid', '')
from_number = request.POST.get('From', '')
num_media = int(request.POST.get('NumMedia', 0))
media_files = [(request.POST.get("MediaUrl{}".format(i), ''),
request.POST.get("MediaContentType{}".format(i), ''))
for i in range(0, num_media)]
print('media files')
print(media_files)
memory = json.loads(request.POST.get('Memory'))
print('Memory= ',memory)
return HttpResponse(status=200)
At first I tried something like:
{
"actions": [
{
"say": "Please send me the selfie."
},
{
"listen": true
},
{
"redirect" : "my webhook"
}
]
}
but that didn't work.
I got nothing on my logs and the Twilio Debugger showed me:
Request Inspector
- Collapse All
POST
https://channels.autopilot.twilio.com/v1/AC0de44f5c63d50ab672ae85bef67ff3bc/UA313a4235eb1ee7cc39ce2ec1781d911a/twilio-messaging/whatsapp
2019-11-12 17:54:05 UTC
400
Request
URL
https://channels.autopilot.twilio.com/v1/AC0de44f5c63d50ab672ae85bef67ff3bc/UA313a4235eb1ee7cc39ce2ec1781d911a/twilio-messaging/whatsapp
Parameters
Show Raw
ApiVersion
"2010-04-01"
MediaUrl0
"https://api.twilio.com/2010-04-01/Accounts/AC0de44f5c63d50ab672ae85bef67ff3bc/Messages/MMd9aa12480e0bebd90ace8a8d5e46cca9/Media/MEaf6ae55ca8c5b27defdef15698a182f8"
SmsSid
"MMd9aa12480e0bebd90ace8a8d5e46cca9"
SmsStatus
"received"
SmsMessageSid
"MMd9aa12480e0bebd90ace8a8d5e46cca9"
NumSegments
"1"
From
"whatsapp:+553584311599"
To
"whatsapp:+14155238886"
MessageSid
"MMd9aa12480e0bebd90ace8a8d5e46cca9"
Body
""
AccountSid
"AC0de44f5c63d50ab672ae85bef67ff3bc"
NumMedia
"1"
MediaContentType0
"image/jpeg"
Message Text
Show Raw
Msg
"Bad Request"
sourceComponent
"14100"
ErrorCode
"11200"
EmailNotification
"false"
httpResponse
"400"
LogLevel
"ERROR"
url
"https://channels.autopilot.twilio.com/v1/AC0de44f5c63d50ab672ae85bef67ff3bc/UA313a4235eb1ee7cc39ce2ec1781d911a/twilio-messaging/whatsapp"
Response
Headers
X-Cache MISS from Twilio-Cache
X-Cache-Lookup MISS from Twilio-Cache:3128
X-Twilio-WebhookAttempt 1
X-Twilio-WebhookRetriable false
Content-Length 66
Date Tue, 12 Nov 2019 17:54:06 GMT
Content-Type application/json
Body
Show Raw
{
"code": 20001,
"status": 400,
"message": "Missing/Invalid Parameters"
}
Then I tried with Collect:
{
"actions": [
{
"collect": {
"name": "collect-selfie",
"questions": [
{
"question": "Para que possamos identificá-lo, poderia nos enviar uma foto do rosto? (selfie)\n",
"name": "selfie"
}
],
"on_complete": {
"redirect": {
"method": "POST",
"uri": "https://dimep.herokuapp.com/selfie/"
}
}
}
}
]
}
I didn't work either, my log only showed me the 'VISITA SELFIE' (meaning it got to the function) when I typed in text with the collect, but the media_files was empty [].
What am I doing wrong?
Twilio developer evangelist here.
I'm afraid Twilio Autopilot doesn't support media right now, so you won't be able to pick up the image from the webhook like this.

How to send push notification from Rest API

I have created my App in Firebase and configured for cloud messaging.
When I am sending the notification from Firebase Console, device gets the notification but if I try to send via Rest API (Using PostMan).
Then notification not coming to device but the response is showing as Success.
Here is my PostMan request
URI - https://fcm.googleapis.com/fcm/send
Header: Content-Type:application/json Authorization:key=MY_SERVER_KEY
Body: { "data": { "title": "Firebase", "detail": "I am firebase" },
"to" : "MY FCM TOKEN HERE" }
Response : {
"multicast_id": 7834540847388366233,
"success": 1,
"failure": 0,
"canonical_ids": 0,
"results": [
{
"message_id": "0:1532422122326299%ebf5f25ef9fd7ecd"
}
] }
I have searched and it seems the way mentioned in documentation is same as I am following
Can anyone let me know why it is not working?
Thanks
I am posting here so as to guide others. As per the guidance of #rv7284, We need to send the data in notification key rather any other key.
So While requesting the body should look like this, Other request parameter like header and all will be same as mentioned in the question.
{ "notification": {
"title": "Firebase",
"detail": "I am firebase"
},
"to" : "YOUR FCM TOKEN"
}

Send email at a later time

I am wondering if the /v1.0/me/sendMail has the ability to delay sending an email. In the Outlook client, you can specify that you want your email sent at a later date and time. I've snooped around to see if there is a property that can be set on the message object to indicate this.
Did anyone find a way to get this working? Of course, I could implement something in my software to handle the delayed sending, but why re-create something if it is already there.
You can achieve delayed sending of emails using extended properties. These can be set on the Graph API request payload using the "singleValueExtendedProperties" attribute.
The property to use is PidTagDeferredSendTime which has the ID 0x3FEF and type SystemTime.
The id attribute of "singleValueExtendedProperties" takes different formats depending on the property you are setting.
For the deferred send time you would use SystemTime 0x3FEF.
Example using a HTTP JSON POST Payload:
{
"message": {
"subject": "Meet for lunch?",
"body": {
"contentType": "Text",
"content": "The new cafeteria is open."
},
"toRecipients": [
{
"emailAddress": {
"address": "bob#contoso.com"
}
}
],
"singleValueExtendedProperties":
[
{
"id":"SystemTime 0x3FEF",
"value":"2019-01-29T20:00:00"
}
]
}
}
Example using the Microsoft Graph API client library:
var client = /* Create and configure GraphServiceClient */;
var msg = new Message();
msg.ToRecipients = List<Recipient>();
msg.ToRecipients.Add(new Recipient() {
EmailAddress = new EmailAddress() { Address ="bob#contoso.com" }
};
msg.Subject = "Meet for lunch?";
msg.Body = new ItemBody()
{
Content = "The new cafeteria is open.",
ContentType = BodyType.Text,
};
msg.SingleValueExtendedProperties = new MessageSingleValueExtendedPropertiesCollectionPage();
msg.SingleValueExtendedProperties.Add(new SingleValueLegacyExtendedProperty()
{
Id = "SystemTime 0x3FEF",
Value = DateTime.UtcNow.AddMinutes(5).ToString("o")
});
await client.Me.SendMail(msg, true).Request().PostAsync();
https://gallery.technet.microsoft.com/office/Send-Emails-until-a-9cee20cf
You set the deferred send time extended prop when creating the item.

Date-time format in the JIRA REST API giving error response Operation value must be a string

I am passing the below JOSN with the POST request to create the Jira issue. One of the parameters is the starting date and time (customfield_10603
).On the JIRA app we have date and time picker for this field.
In what format this value should be sent out. I tried with 2018-06-17T00:00:00.0+0000.
JSON sent:
{
"fields": {
"project":
{
"key": "HOA"
},
"summary": "Test ticket for JIRA_Jenkins integration.",
"customfield_10616":{"value":"Other"},
"description": "Creating of an issue using project keys and issue type names using the REST API",
"customfield_10603": {"value":"2018-06-17T00:00:00.0+0000"},
"issuetype": {"name": "Change Request" },
"customfield_10624": {"value":"Low"},
"customfield_12100": {"value" :"Low"},
"customfield_10625": {"value":"SRE"},
"customfield_10615": {"value":"Routine"}
}
}
received response:
{
"errorMessages": [],
"errors": {
"customfield_10603": "Operation value must be a string"
}
}
Found the solution.
"customfield_10603": "2018-06-17T00:00:00.0+0000".

Resources