Why is my Service Worker's push event data/payload null? - javascript

I have made multiple attempts to get desktop notifications working in Chrome, but I have not found a single source of documentation that covers a step by step procedure to get desktop notifications to work correctly. Each resource I have come across is either outdated or inconsistent with others.
The problem I am facing is: once the Service Worker receives the push event,
self.addEventListener('push', function (event) {
console.log(event);
event.waitUntil(
self.registration.showNotification(
event.data.title,
{
body: event.data.body,
icon: event.data.icon,
tag: event.data.tag
}));
});
event.data is null. I expect it to have data that I am sending as JSON in a POST request like this:
POST https://fcm.googleapis.com/fcm/send HTTP/1.1
Content-Type: application/json
Authorization: key=<FCM Server Key here>
{
"data": {
"title": "Foo",
"body": "Bar"
},
"to": "<recipient ID here>"
}
The weird thing is the registration script gets a "subscription endpoint" that looks like https://android.googleapis.com/gcm/<recipient ID here>, but I cannot get the POST to go through unless I follow other examples on the web that say to put the recipient ID as the to field in the JSON I am sending.
Of all the examples I have come across, there are multiple URLs that POST calls are being made to:
https://fcm.googleapis.com/fcm/send
https://android.googleapis.com/gcm/send
https://gcm-http.googleapis.com/gcm/send
I have tried all three, with each attempt having the recipient at the end of the API address (like https://fcm.googleapis.com/fcm/send/<recipient ID here> and alternatively in the JSON body. My goal is to get Foo and Bar from the data I am sending into the self.registration.showNotification( method of the service worker.
Why is event.data null? Can anyone point me to a complete guide from start to finish that favors FCM over GCM? Any help would be appreciated.

You may want to check the following statement from the documentation,
A downside to the current implementation of the Push API in Chrome is that you can't send any data with a push message. Nope, nothing. The reason for this is that in a future implementation, payload data will have to be encrypted on your server before it's sent to a push messaging endpoint. This way the endpoint, whatever push provider it is, will not be able to easily view the content of the push message. This also protects against other vulnerabilities like poor validation of HTTPS certificates and man-in-the-middle attacks between your server and the push provider. However, this encryption isn't supported yet, so in the meantime you'll need to perform a fetch to get information needed to populate a notification.
Reading further, you may want to try using fetch() to get data from an API, convert the response to an object and use it to populate notification. This same method was also used in this related SO post.
In addition to that, you may want to also check the response of #Indici Indici in the thread wherein he stated that push event does not contain data values; instead it contains different events which contains information(s). Here is the sample code that was provided as a possible workaround to receive notification in Firebase service-worker in "push" event:
self.addEventListener('push', function(event) {
if (event.data) {
const dataText = event.data.text();
notificationTitle = 'Custom Notification';
notificationOptions.body = 'Message: ' + `${dataText}`;
var title = event.data.notification.title;
var message = event.data.notification.message;
var icon = event.data.notification.icon;
var notificationTag = event.data.notification.tag;
}
}

For receive data need:
self.addEventListener('push', function(event) {
var jsonData = JSON.parse(event.data.text());
// jsonData -> here is you data
const options = {
body: 'set you body',
icon: 'img/apple-icon-120x120.png',
badge: 'img/apple-icon-120x120.png'
};
event.waitUntil(self.registration.showNotification(jsonData.data.title, options));
});

Related

POST Request to PUT Request

"
An open source course that I am taking has the following prompt for fullstack development:
3.17: Phonebook database, step5
If the user tries to create a new phonebook entry for a person whose name is already in the phonebook, the frontend will try to update the phone number of the existing entry by making an HTTP PUT request to the entry's unique URL.
Modify the backend to support this request.
Verify that the frontend works after making your changes."*
It appears that this would call for an express app.put request called inside on an app.post request. Is there something that I'm missing here? How you handle this kind of logic with mongoDB/mongoose/expresss? My current post code is pasted below.
Thanks
app.post('/api/persons',(req,res) => {
const body = req.body
const containsNameNumber = body.name && body.number
if(!containsNameNumber){
return res.status(400).json({
error:"must specify a name and a number"
})
}
const phone = new Person({
name: body.name,
number:body.number
})
phone.save().then(savedPerson => {
res.json(savedPerson)
})
})
I think you are missunderstanding one thing, check PUT definition from RFC7231
The PUT method requests that the state of the target resource be
created or replaced with the state defined by the representation
enclosed in the request message payload
Is importante the part "be created". So with a PUT if the resource exists it will be updated but if not exists will be created.
If the target resource does not have a current representation and the
PUT successfully creates one, then the origin server MUST inform the
user agent by sending a 201 (Created) response.
So you only have to do a PUT call and check if exists to update (return 200 Ok) or not exists to create (return 201 Created).

Channel_not_found: authed_user cannot post a message to a channel via Slack API

I'm trying to post a message on a channel a user belongs via the Slack Api as an authed_user.
here is the flow:
User gives permissions with scopes 'chat:write,channels:write,channels:history'
I receive a token along with some more information from Slack that looks like xoxp-122474-a bunch of numbers
I create a Slack Client with the token and sends a request with:
const { WebClient } = require('#slack/web-api');
const client = new WebClient(token.access_token);
await client.chat.postMessage({
channel: channelId, // = Something similar to C02E2K5CCUZ
as_user: true,
text: "here is some text",
});
I get an error from the slack API, 'channel_not_found' but I checked the channel does exists + the user is in the channel.
What should I do to make this work? Am I missing anything?
Thank you !
It's possible that error is a red herring. The as_user parameter might be messing you up. That parameter can only be used for legacy apps. You can still use chat.postMessage but make sure you are also requesting the [chat:write.customize][1] scope. You will then be able to customize the posting user by defining the username and icon_urlparameters in your API call.

"redirect_uri_mismatch" when sending authentication code to GoogleAPI

I am having trouble with the authentication process for the GoogleAPI. In the end I want to be able to read the users steps using the GoogleFit API and then store that value in a database. Currently I'm using restdb.io and executing javascript in codehooks.
The documentation from Google that I am following can be found here, clicking on the HTTP/REST option in the code examples. At the moment I am at step 5: I have gotten the users authentication code and stored it in the database. Now I have to POST the code along with some other parameters and get the access and refresh tokens.
If the POST is successful (from what I understand) I should get back a 200-OK message that the request was valid. Google will then POST a JSON body with the access and refresh token to the redirect_uri that I have specified in my GoogleAPI credentials page and the initial request. At redirect_uri I have to handle the request and save the two values.
The problem is that I receive a redirect_uri_mismatch - Bad Request message from Google as a response when executing the request. I get it at the log.debug("ERROR HERE: " + [...]); in the code below:
async function mainFunction(){
const authCode = THIS_IS_MY_AUTHENTICATION_CODE;
try {
var answer = await postRequestToGoogle(authCode);
//do stuff with response from Google
} catch (error) {
//do stuff
}
}
async function postRequestToGoogle(authCode){
//body for the request
const params = "code=" + authCode + "&" +
"client_id=THIS_IS_MY_CLIENT_ID" + "&" +
"client_secret=THIS_IS_MY_CLIENT_SECRET" + "&" +
"redirect_uri=THIS_IS_MY_REDIRECT_URI" + "&" +
"grant_type=authorization_code";
try{
const result = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: params})
.then(res => {
log.debug("ERROR HERE: " + JSON.stringify(res.json()));
return res.json();
})
//return JSON back main function
return result;
}catch(error){
//do stuff
}
}
I looked up the error message and tried some things:
Copy and pasted multiple different Authorized redirect URI from the GoogleAPI credentials page into the code to make sure that there is no problem with
http/https
www/no www
trailing slashes
typos or capitalization
Waited for changes to be processed by Google (read that it can more than 30min)
Changed all the other parameters to see if the redirect_uri is actually the problem
If code is changed the message is invalid_grant - Bad Request
If client_id is changed the message is invalid_client - The OAuth client was not found
If client_secret is changed the message is invalid_client - Unauthorized
If the grant_type is changed the message is unsupported_grant_type - Invalid grant_type
That's why I think the issue is the redirect_uri, but it's unclear to me how since I copy&pasted it. Something that came to mind was that maybe the value of redirect_uri gets changed when it's read by Google? Or maybe when the request is being put together? Do some characters have to be replaced?
I tried to analyze the request with Wireshark but didn't think about the fact that it's HTTPS so I would have I would have to decrypt it.. Is that something I should look into?
Thank you for taking the time to read all of this! If you have any advice please let me know :)
Update 16.11.20:
I have created a new OAuth 2.0 Client ID and used the new id/secret in my request. The resulting message the same as before. I will wait and try again tomorrow to see if maybe Google needs some more time. Then I'll try to delete all current IDs and start with a fresh GoogleAPI project.
Update 19.11.20:
Creating a new OAuth 2.0 Client ID did not resolve my problem, neither did creating a whole new GoogleAPI project and adding those credentials into the request. I am in contact with the developers of restdb.io and have asked them to add the Google Auth Library: Node.js Client to the list of supported Node.js packages. Hopefully that will help, I will give it a try as soon as it can be used :)
Update 02.12.20:
No progress so far, but I'm optimistic that the developers will add the package soon. I will post a final update as soon as I am done with this project.

Google Calendar API - Push notifications not working

I'm using the Google Calendar API and am trying to receive push notifications when a calendar event is triggered https://developers.google.com/calendar/v3/push
I think everything is setup correctly...
gapi.client.calendar.events.watch({
calendarId: 'primary',
resource: {
id: uuid,
type: 'web_hook',
address: window.location.href,
},
}, (err, response) => {
if (err) {
console.log('err:', err);
} else {
console.log('response:', response);
}
}).then((res) => {
console.log('res:', res);
});
But I guess not. I get a 200 response when I call the above code
{
"kind": "api#channel",
"id": "...",
"resourceId": "...",
"resourceUri": "https://content.googleapis.com/calendar/v3/calendars/primary/events?alt=json&maxResults=250&alt=json",
"expiration": "1554203159000"
}
I believe I should also be receiving a sync message, but I am not (https://developers.google.com/calendar/v3/push#sync)
To test things I am modifying an event within the calendar itself (changing the title, date, deleting, etc), and I expect something to happen in my browser, but nothing.
I'm not familiar with Push notifications in general, so not exactly sure what to expect.
I'm already authenticated and displaying events as per https://developers.google.com/calendar/quickstart/js
What am I missing? Any help is really appreciated!
Thanks in advance!
I suspect you are miss understanding exactly what push notifications is.
There are two primary ways to track when a resource has changed. You can poll that resource often and check for any changes in the resource.
For example Your application could run every five minutes and make a request to Google asking to have the event returned to you. When that event is returned you will then check if there are any changes in the event created by the user. This method of checking for changes is very time consuming and requires resources to constantly poll the server looking for changes. A better way of doing it is using Push notifications
Push notifications notify your application when a change has been made.
This document describes how to use push notifications that inform your application when a resource changes.
Its set up by enabling a watch
POST https://www.googleapis.com/calendar/v3/calendars/my_calendar#gmail.com/events/watch
Authorization: Bearer auth_token_for_current_user
Content-Type: application/json
{
"id": "01234567-89ab-cdef-0123456789ab", // Your channel ID.
"type": "web_hook",
"address": "https:/examle.com/notifications", // Your receiving URL.
...
"token": "target=myApp-myCalendarChannelDest", // (Optional) Your channel token.
"expiration": 1426325213000 // (Optional) Your requested channel expiration time.
}
This tells Googles servers that you would like to be notified when ever someone makes a change to the event. This sets up a web hook to https:/examle.com/notifications which will be notified as soon as there is a change to the event.
Name of the event, date time are normally changes i dont think you will get a push notification if someone else is added to the event.
What this is not
The server is NOT going to send you a message 10 minutes before the event is due. Thats user notification and something completely different and not part of the Google Calendar api.

Firebase FCM error: 'InvalidRegistration'

I am currently trying to send a PushNotification to a Device Group using FCM with the help of Firebase Cloud Functions but once the notification is sent, it returns with code 200 but with failure :
SUCCESS response= {
multicast_id: 8834986220110966000,
success: 0,
failure: 1,
canonical_ids: 0,
results: [ { error: 'InvalidRegistration' } ]
}
Here is the code I am using to send this notification... what am I missing?
const options = {
method: 'POST',
uri: 'https://fcm.googleapis.com/fcm/send',
headers: {
'Authorization': 'key=' + serverKey,
},
body: {
to: groupId,
data: {
subject: message
},
notification: {
title: title,
body: body,
badge: 1,
},
content_available: true
},
json: true
};
return rqstProm(options)
.then((parsedBody) => {
console.log('SUCCESS response=', parsedBody);
})
.catch((err) => {
console.log('FAILED err=', err);
});
Where JSON values title, body, subject, message are String
In my case, I was sending notifications to topic ("topics/my-topic"). I was missing prepending / in the starting of topic so I was getting the same issue. SO topic should be /topics/my-topic.
May be this helps!!
There is an easier way to send a message to a device group from a Cloud Function. Use admin.messaging().sendToDeviceGroup(). Sample code and instructions are in this guide.
I think your current method is failing because there is something wrong with the group notification key provided in groupId. It should be the string key value that was returned when you created the device group. The error codes are listed in this table. For 200/InvalidRegistration it says:
Check the format of the registration token you pass to the server.
Make sure it matches the registration token the client app receives
from registering with Firebase Notifications. Do not truncate or add
additional characters.
I was losing my mind with this InvalidRegistration error.
Eventually the problem was that I was subscribing my device to "example" but sending the notification json to: "example".
But we actually need to send to "/topics/example"
2 hours of my life wasted..
A registration token is tied to a certain group of senders. When a client app registers for FCM, it must specify which senders are allowed to send messages. You should use one of those sender IDs when sending messages to the client app.
Al you need to do is add a http header 'project_id' with your sender id.
I was getting InvalidRegistration:
Basic meaning: you are using the wrong token. Why? This may happen when you a new registrationToken is given to you in onNewToken (docs), but for some reason you are using the old token. That could happen when:
You're using a different push notification library which remembers token (stores it somewhere locally) and you didn't update that library with the new token.
Your application (or other library dependencies) implements another FirebaseMessagingService, and they conflict. Only one service can accept (react to) to the action sent by the FirebaseMessaging Android library's when a new token is given to it. You can double check this by opening the AndroidManifest.xml in Android Studio and selecting the Merged Manifest tab at the bottom of the tab. You can also place debuggers in each Service from each library you use. You'll see that only one service's onNewToken gets called.
When they conflict, one doesn't get the correct token, and the FCM registration token that gets registered would be wrong. Sending a message to a wrong registration, gets you InvalidRegistration.
for me, it was a mistake that I was passing an Id from my models instead of the tokens of the users
InvalidRegistration simply means that the token is either invalid or expired. You can uninstall the app and then reinstall and get a new token and then try with that token. This will definitely solve your problem.
You can read more here.

Categories

Resources