Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web Push API - storing subscriptions in backend

I've implemented a Web Push API with the help of this Google tutorial: https://developers.google.com/web/fundamentals/getting-started/codelabs/push-notifications/

The tutorial includes a method, which could be used to send the subscription to a backend server:

function updateSubscriptionOnServer(subscription) {
  // TODO: Send subscription to application server
  ...
}

I want to store the subscription together with a user identifier, so I can choose which users I want to send a notification. Now I'm wondering, which part of the subscription I've to store in the database. My subscription objects look like this:

{"endpoint":"https://fcm.googleapis.com/fcm/send/...","keys":{"p256dh":"...","auth":"..."}}

Should I just create a table "Subscription" with columns (Id|User_Id|Subscription), which includes the whole JSON subscription? What is best practice for that? Is the JSONs validity unlimited? Which field can I use to identify a subscription in case of unsubscription?

like image 927
AndrejDelany Avatar asked Feb 28 '17 09:02

AndrejDelany


People also ask

How does push notification Work backend?

The API call from your back-end / application that triggers a push message to a user's device. The service worker JavaScript file that will receive a "push event" when the push arrives on the device. It's in this JavaScript that you'll be able to show a notification.

What is push subscription?

A push subscription is a message delivery context established between the user agent and the push service on behalf of a web application. Each push subscription is associated with a service worker registration and a service worker registration has at most one push subscription.

What protocol is used for push notifications?

There are two protocols http and xmpp which you can use to send message to GCM server.


2 Answers

To allow anonymous web-push-users to use our service, we've come up with the idea to hash the subscription and use the hash as the backend's primary key (id).

// pseudo-code
const id = hash(subscription);
https.post(`${SERVER}/subscription/${id}`, subscription).then(...);

As I understand correctly, the subscription does not change over time and therefore, the hash is a constant. Collisions are not to be expected since every subscription is unique and you may choose an appropriate hash function (e.g. SHA-512).

You can then re-validate the subscription in your Service Worker or handle pushsubscriptionchange events as long as you can access the original subscription and re-create the hash/id.

This should cover most of the cases. But still, when sending the push-notification through Google's and Firefox's push-servers, you'll still need to respect the response codes (HTTP 401) for invalid subscriptions and remove them from your database.

See Javascript Crypto functionality for available hash-functions. Supported by FF and Chrome.

like image 124
mana Avatar answered Nov 06 '22 07:11

mana


Storing your Subscription in the database

Your database should look like if you are using a document db:

userId: {type:String, required: true},
endpoint: { type: String, unique: true},
keys: {
 p256dh: {type: String},
 auth: {type: String}
},
userAgent: {type: String}, // optional, just an additional tracking field
deviceId: {type: String} // just additional tracking fields

If you are using a relational database you can store the keys part in individual columns or use a JSON type column.

The main thing to know is that webpush.sendNotification(...) takes an object with the following interface:

export interface PushSubscription {
    endpoint: string;
    keys: {
        p256dh: string;
        auth: string;
    };
}

which means basically these are the properties your database will need to keep track of subscriptions. You may choose to add userId, and others for your own specific use case

like image 35
Dan White Avatar answered Nov 06 '22 05:11

Dan White