“Decentralized” Push Notifications for ios

References:

Status:

Push notifications proposal by Oskar https://docs.google.com/document/d/1OgjnY8ps8lVA4dIohwkfGK9HVt0nZxEWbuNdb7BX5-o/edit#heading=h.kjam5hcc2nif

Push Notifications v2 by Pedro https://ideas.status.im/ideas/086-push-notif-v2/README

Message IDs in Push Notifications by Pedro Message IDs in Push Notifications

Push Notifications v2 design notebook https://docs.google.com/document/d/1TCeTY77fCGHqAseWkH74P0mk7PF8DGXN7xvbYqodnTI/edit#

Fixing notifications by Eric Fixing notifications

Community:

Feature Request: Mobile Push Notifications https://github.com/status-im/status-react/issues/10363
Riot’s magical push notifications in iOS https://thomask.sdf.org/blog/2016/12/11/riots-magical-push-notifications-in-ios.html

Proper Key Exchange with Push Notification Providers? Proper Key Exchange with Push Notification Providers?

Adventures in “Decentralized” Push Notifications by Pelle Braendgaard [uPort] https://medium.com/uport/adventures-in-decentralized-push-notifications-3c64e700ec18

A push notification server written in Go (Golang). https://github.com/appleboy/gorush

Implementation

There are two ways for PN implementation

  1. local notifications

    application or service is running and it triggers push notifications
  2. remote notifications

    application isn’t running and push notifications are added by OS triggered by remote services

Currently, we have local notifications implemented on Android

BUT for ios there is no obvious solution for that
Some research from Andre https://notes.status.im/vDbGDuz3QUuzaLF4UHHhwA

Among the references above, we know that signal, riot and uport use remote notifications with their own centralized server and apple push server

Status first MVP version for PN used Firebase Cloud Messaging directly from the application and users exchanged their device tokens

Lets consider next options:

  1. Direct usage of Firebase Cloud Messaging in the application

pros:
Status doesn’t need to run and maintain servers
FCM react native library can be used
cons:
users need to exchange tokens
both users sender and receiver must give access to this service and share their tokens
metadata leakage
relience on third party service
not possible to publish such app on f-droid

  1. Status service avaliable over http with 3rd party service like Firebase Cloud Messaging, Amazon SNS, Pushy or other 3rd party providers

pros:
FCM react native library can be used only on ios
cons:
Status needs to run and maintain servers
relience on third party service
metadata leakage to status servers
difficult or not possible to run such service by users because of privacy and 3rd party service registrations

  1. Status service avaliable over waku with 3rd party service like Firebase Cloud Messaging, Amazon SNS, Pushy or other 3rd party providers

pros:
FCM react native library can be used only on ios
less or no metadata leakage to status servers
cons:
Status needs to run and maintain servers
difficult or not possible to run such service by users because of privacy and 3rd party service registrations
relience on third party service

  1. Status service avaliable over http with custom opensource push notification server like gorush

pros:
no relience on third party service
less metadata leakage to status servers
cons:
Status needs to run and maintain servers
Status needs to implement support for ios push notification in the app

  1. Status service avaliable over waku with custom opensource push notification server like gorush

pros:
no relience on third party service
no metadata leakage
can be run by users as a service
cons:
Status or users need to run and maintain servers
Status needs to implement support for ios push notification in the app

So in any case with remote notifications, user who sends message, should also send notification and it can be sent only if recipient apple device token is known

Alice and Bob have additional public keys for push notifications

PN waku node is a regular status node which has a public key

Alice sends her device token using push notification public key, so waku node doesn’t know Alice’s chat public key

PN node stores Alice’s device token and Alice’s pn public key

When Bob wants to send PN to Alice he sends Alice’s pn public key to waku pn node, Bob doesn’t know Alice’s device token

In this approach ios users must share their push notification public key if they want to receive PN from user or group chat, IMO that’s fine so notifications for every chat will be disabled by default and users can enable them for example by clicking on the bell icon, and in that case, they share their pn pubkey

PN implementation tutorial for ios https://www.raywenderlich.com/8277640-push-notifications-tutorial-for-ios-rich-push-notifications

So there are options how PN on ios can be implemented, and we need to discuss and find the best fit for us and implement it, please share your thoughts and ideas, thanks.

9 Likes

The first question I’d want to know is about the feature requirements, that will help us I think filter out some of the solutions, as they might not fully adhere to the requirements.

If I receive a one-to-one message from someone that I had no contact with before, should I receive a push notification? Or notifications should only be received by contacts? What is the situation with the current android implementation (I believe is from anyone)?

That will help us better shape a solution.

cc @maciej @hester

2 Likes

The expectation is, yes.

Or notifications should only be received by contacts?

Not really no, contacts are a fancy bookmark, they don’t carry that kind of weight anymore and are a personal preference. You should be able to enjoy the basic feature set of a chat without having to add someone as a contact if you don’t wish to.

5 Likes

Agree with @maciej. Shhould be able to receive a notification on anyone sending a messages. Especialy when this is someone not in your contact list and you have no reason to expect or check for new messages

Any thoughts on how this would work? Is the PN public key shared along with the public chat key? Is it shared along with public chat key, when writing in a public channel?

1 Like

It depends, so if we want to receive all notifications in that case we lose part of privacy, users need to share their chat’s public key and device token with notifications service, in that case user should trust this service, if this service will be run by status we can add it as default in settings, and when user runs the app we show push notifications dialog, and if user enables notifications we send his public key and device token to push notification service
later user can run and use his own “pn node” or use desktop

4 Likes

so I would suggest the fifth case with some changes in flow
Alice do not share her pn public key with Bob, and she shares her device token via her chat public key

If we go this way we need to implement next:

  1. run a server with waku node which will be listening for device token registration and send pn commands
  2. run database in which token and public key will be stored
  3. run push notification gorush server
  4. implement push notifications on ios
  5. implement the logic for pn in status react and for pn waku node
3 Likes

Only commenting on user experience for now:

I’d disagree on the ‘receive notification from anyone’. To me that’s basically a form of attention spam, and it is everywhere today. Twitter notifications, Email newsletters you didn’t subscribe to, etc etc. This means I personally turn off notifications for almost anything. I think there’s a good opportunity here for Status to be a counter point to this engagement obesity trend. This also plays into offers like Tribute to Talk, etc.

Even if we decide to go the vanilla IM experience route, as long as I can turn customize it / turn it off I’d be happy, as an end user.

3 Likes

i would agree with Oskar, but we could implement this as an options, so when you enable notifications you can select an option to mute all notifications by default
as for implementation i think as a first version we could use FMS for ios, in that case implementation will be simpler for us

1 Like

Yes that was always the idea and design blueprint, any chat or contact can be muted or you can toggle off notifications entirely first and only choose to opt in for given contacts.

4 Likes

run a server with waku node which will be listening for device token registration and send pn commands

One concern with this is that it further solidifies the special role cluster node have, which is something we want to move away him.

What would be the path towards making this more “flexible”? I.e. changing fluidly to a new node, relaxing high availabiliy requirements etc.

Here’s my thoughts on a couple of solutions

https://notes.status.im/push-notifications-ios

If people could let me know which one is preferred, opinions etc, it would help moving this forward.

4 Likes

Thanks for the write up!

I notice we say user in the user stories. Would it be more accurate to say device? Specifically I think it’d be useful to also have some details on how we deal with these cases:

  • One user many devices
  • One device many users (login/out, do you stay registered and get a PN for a different user?)

User B when sending a message to user A, will POST to an endpoint passing the PK of user A

How does B know to perform this action? I.e. what if A runs on Android? Would this not reveal to the server that B is sending a message to A public key, including time and frequency? If B opts out, what would that do to UX of A?

I can imagine this is an option B can choose, and then this can be communicated in UI like “B doesn’t want to send notifications, so you won’t get them on iOS”.

For solution 2:

The other problem to solve here is discovery, namely, as user B , how do I know which server to hit in order to send a push notification to A ?

Seems similar to the problem of node discovery (DNS, Discv5) and capabilities discussion (https://github.com/vacp2p/specs/issues/87).

Probably I would go for 2 with either interactive or non-interactive. I don’t have a strong preference.

I’d agree with 2. No strong preference for interactive or non-interactive right now. Main reason is that it’d mean a user can run their own node / use a semi-trusted one, and not collect the whole social graph in one central service.

I notice we say user in the user stories. Would it be more accurate to say device? Specifically I think it’d be useful to also have some details on how we deal with these cases:

Yes, device is more accurate, currently there’s only some small complications by supporting multiple devices, so overall is probably best to discuss as we move a bit deeper into the implementation.

How does B know to perform this action? I.e. what if A runs on Android? Would this not reveal to the server that B is sending a message to A public key, including time and frequency? If B opts out, what would that do to UX of A?

So, here we have a few options, again there are probably a lot of different ways, but here’s a couple:

Anonymous push notifications

B does not need to reveal their identity to push a notification server. That’s the simplest, it’s obviously though susceptible to abuse, but in general abuse is always trivial in status as anyone can just generate a bunch of keys and hit the server.
This is the most privacy preserving, but I don’t think that’s a viable solution, I think some ACL is necessary as push notification can be very annoying.

Token-based push notifications + ACL

The push notification server, will issue tokens to user requesting information on whether the user A has registered with them.

This token will be the same for multiple users.
When asking for the token they will have to disclose their identity to the PN server, but not when using the token (actually sending a notification).
The user registering with the PN can communicate an allow list/block list (depending on the user preferences), any time it changes the tokens will be invalidated, and user requesting to send notifications will be notified and will have to try again.
This is similar to what signals does with sealed envelopes.
A user could ask for multiple tokens using ephemeral keys to protect their identity somehow.

Effectively from a UX point of view it would work something like:

On the user receiving push notifications:

A) A user will have an option to enable push notifications

If notifications are enabled:
B) They will have an option to use status server or add their own
C) They will have some ACL options, for example: Receive only from contacts, allow list, ban list, possibly mute chats. This information will have to be shared with the PN server. If privacy is a concern they don’t have. (We explored client side filtering using silent notifications, but that’s not possible). Anytime this settings change the token will be refreshed on the PN server.

On the sender side, there will be an option to disable sending notifications, that can be global or per chat.

Seems similar to the problem of node discovery (DNS, Discv5) and capabilities discussion (https://github.com/vacp2p/specs/issues/87 ).

It’s related, but slightly different, here we want to know “Who has Oskar devicetoken?”, but we already have a channel where to ask this (waku), so it’s easier. The request can be “anonymous” (using an ephemeral key), at which point communication can continue on a separate topic 1-to-1 encrypted, where identity will be disclosed in order to access the token as described above.

The only feasible is interactive actually, without getting in too complex solutions. I had a discussion with Andrea F to check some assumptions and turns out I got some technical details wrong.

I am writing now the specs, I think there’s enough certainty now to move to the next level.

3 Likes

Push notification server specs https://github.com/status-im/specs/pull/139/files

4 Likes

Currently Status don’t have spam protection, so having from “contacts only” is very important.
As you know, the problem of accepting notifications from non contacts in Status is cheap spam vector.

Personally I would consider “receiving notifications from non contacts” as optional, and maybe even out of scope of an MVP.

I think that this is an ok solution, but I just don’t like the revealing identity thing, because then mailserver becomes a privacy single point of failure for knowing “who talks with who”, and “what device is who”.
Would be better if the tokens are sent directly from user-to-user using Status Network, and the notification server only knows that some tokens are being used.

Currently Status don’t have spam protection, so having from “contacts only” is very important.
As you know, the problem of accepting notifications from non contacts in Status is cheap spam vector.

The proposal supports both cases, and you don’t have to disclose your real identity to the server, nor the fact that you want to be notified only by contacts (this is roughly the same as we had before in terms of push notifications) https://github.com/status-im/specs/pull/139/files#diff-3d6351c57005d2e2cbb351b53bb61994R575 .

I can add a section to the main document to make it clearer how it would work.

1 Like

This is explained here https://github.com/status-im/specs/pull/139/files#diff-3d6351c57005d2e2cbb351b53bb61994R589

This allow receiving pn only from “contacts” (or whoever you want to share your identity with)

1 Like

For the anonymous case where we want prevent leakage of the public key/address I’d like to bring this construction based on el-gamal to your attention:


It was used by Apple to implement privacy preserving find-my-device, so it seems practical. I think “anonymous billboards” how they describe it is a fairly general construction that we could potentially reuse in several components to increase user privacy.
3 Likes