2020-06-18 06:44:07 +00:00
---
2021-11-16 14:48:05 +00:00
permalink: /raw/16
2020-06-18 06:44:07 +00:00
title: 16/PUSH-NOTIFICATION-SERVER
2021-11-16 14:48:05 +00:00
parent: Raw specs
layout: default
2020-06-18 06:44:07 +00:00
---
# 16/PUSH-NOTIFICATION-SERVER
> Version: 0.1
>
> Status: Raw
>
> Authors: Andrea Maria Piana <andreap@status.im>
- [Push Notification Server ](#16push-notification-server )
- [Reason ](#reason )
- [Requirements ](#requirements )
- [Components ](#components )
- [Registering with the push notification service ](#registering-with-the-push-notification-service )
- [Re-registering with the push notification service ](#re-registering-with-the-push-notification-server )
- [Changing options ](#changing-options )
- [Unregistering from push notifications ](#unregistering-from-push-notifications )
- [Advertising a push notification server ](#advertising-a-push-notification-server )
- [Discovering a push notification server ](#discovering-a-push-notification-server )
- [Querying the push notification service ](#querying-the-push-notification-server )
- [Sending a push notification ](#sending-a-push-notification )
- [Flow ](#flow )
- [Registration process ](#registration-process )
- [Sending a notification ](#sending-a-notification )
- [Receiving a push notification ](#receiving-a-push-notification )
- [Protobuf description ](#protobuf-description )
2020-07-23 11:27:50 +00:00
- [PushNotificationRegistration ](#pushnotificationregistration )
2020-06-25 11:57:49 +00:00
- [PushNotificationRegistrationResponse ](#pushnotificationregistrationresponse )
2020-06-18 06:44:07 +00:00
- [ContactCodeAdvertisement ](#contactcodeadvertisement )
- [PushNotificationQuery ](#pushnotificationquery )
- [PushNotificationQueryInfo ](#pushnotificationqueryinfo )
- [PushNotificationQueryResponse ](#pushnotificationqueryresponse )
- [PushNotification ](#pushnotification )
- [PushNotificationRequest ](#pushnotificationrequest )
2020-07-23 11:27:50 +00:00
- [PushNotificationResponse ](#pushnotificationacknowledgement )
- [PushNotificationReport ](#pushnotificationreport )
2020-06-18 06:44:07 +00:00
- [Anonymous mode of operations ](#anonymous-mode-of-operations )
- [Security considerations ](#security-considerations )
- [FAQ ](#faq )
- [Changelog ](#changelog )
- [Version 0.1 ](#version-01 )
- [Copyright ](#copyright )
## Reason
Push notifications for iOS devices and some Android devices can only be
implemented by relying on [APN service ](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1 ) for iOS or [Firebase ](https://firebase.google.com/ ).
2020-06-25 11:57:49 +00:00
This is useful for Android devices that do not support foreground services or that often kill the
foreground service.
2020-06-18 06:44:07 +00:00
iOS only allows certain kind of applications to keep a connection open when in the
background, VoIP for example, which current status client does not qualify for.
Applications on iOS can also request execution time when they are in the [background ](https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background/updating_your_app_with_background_app_refresh )
but it has a limited set of use cases, for example it won't schedule any time
if the application was force quit, and generally is not responsive enough to implement
a push notification system.
Therefore Status provides a set of Push notification services that can be used
to achieve this functionality.
Because this can't be safely implemented in a privacy preserving manner, clients
2020-06-25 11:57:49 +00:00
MUST be given an option to opt-in to receiving and sending push notifications. They are disabled by default.
2020-06-18 06:44:07 +00:00
## Requirements
2020-06-25 11:57:49 +00:00
The party releasing the app MUST possess a certificate for the Apple Push Notification service and its has to run a [gorush ](https://github.com/appleboy/gorush ) publicly accessible server for sending the actual notification.
The party releasing the app, Status in this case, needs to run its own [gorush ](https://github.com/appleboy/gorush )
2020-06-18 06:44:07 +00:00
## Components
### Gorush instance
2020-06-25 11:57:49 +00:00
A [gorush ](https://github.com/appleboy/gorush ) instance MUST be publicly
2020-06-18 06:44:07 +00:00
available, this will be used only by push notification servers.
### Push notification server
2020-06-25 11:57:49 +00:00
A push notification server used by clients to register for receiving and sending push notifications.
2020-06-18 06:44:07 +00:00
### Registering client
2020-06-25 11:57:49 +00:00
A Status client that wants to receive push notifications
2020-06-18 06:44:07 +00:00
### Sending client
2020-06-25 11:57:49 +00:00
A Status client that wants to send push notifications
2020-06-18 06:44:07 +00:00
## Registering with the push notification service
A client MAY register with one or more Push Notification services of their choice.
2020-07-23 11:27:50 +00:00
A `PNR message` (Push Notification Registration) MUST be sent to the [partitioned topic ](../stable/10-waku-usage.md#partitioned-topic ) for the
2020-06-18 06:44:07 +00:00
public key of the node, encrypted with this key.
2020-07-23 11:27:50 +00:00
The message MUST be wrapped in a [`ApplicationMetadataMessage` ](../stable/6-payloads.6#payload-wrapper ) with type set to `PUSH_NOTIFICATION_REGISTRATION` .
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
The marshaled protobuf payload MUST also be encrypted with AES-GCM using the Diffie– Hellman key
generated from the client and server identity.
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
This is done in order to ensure that the extracted key from the signature will be
considered invalid if it can't decrypt the payload.
The content of the message MUST contain the following [protobuf record ](https://developers.google.com/protocol-buffers/ ):
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
```protobuf
message PushNotificationRegistration {
2020-06-18 06:44:07 +00:00
enum TokenType {
UNKNOWN_TOKEN_TYPE = 0;
APN_TOKEN = 1;
FIREBASE_TOKEN = 2;
}
TokenType token_type = 1;
2020-07-23 11:27:50 +00:00
string device_token = 2;
2020-06-18 06:44:07 +00:00
string installation_id = 3;
2020-06-25 11:57:49 +00:00
string access_token = 4;
2020-07-23 11:27:50 +00:00
bool enabled = 5;
uint64 version = 6;
repeated bytes allowed_key_list = 7;
repeated bytes blocked_chat_list = 8;
bool unregister = 9;
bytes grant = 10;
bool allow_from_contacts_only = 11;
2020-09-03 07:59:09 +00:00
string apn_topic = 12;
bool block_mentions = 13;
repeated bytes allowed_mentions_chat_list = 14;
2020-06-18 06:44:07 +00:00
}
```
A push notification server will handle the message according to the following rules:
2020-07-23 11:27:50 +00:00
- it MUST extract the public key of the sender from the signature and verify that
the payload can be decrypted successfully.
2020-06-18 06:44:07 +00:00
- it MUST verify that `token_type` is supported
2020-07-23 11:27:50 +00:00
- it MUST verify that `device_token` is non empty
2020-06-18 06:44:07 +00:00
- it MUST verify that `installation_id` is non empty
2020-07-23 11:27:50 +00:00
- it MUST verify that `version` is non-zero and greater than the currently stored version for the public key and installation id of the sender, if any
- it MUST verify that `grant` is non empty and according to the [specs ](#server-grant )
2020-06-25 11:57:49 +00:00
- it MUST verify that `access_token` is a valid [`uuid` ](https://tools.ietf.org/html/rfc4122 )
2020-09-03 07:59:09 +00:00
- it MUST verify that `apn_topic` is set if `token_type` is `APN_TOKEN`
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
If the message can't be decrypted, the message MUST be discarded.
2020-06-18 06:44:07 +00:00
2020-06-25 11:57:49 +00:00
If `token_type` is not supported, a response MUST be sent with `error` set to
2020-06-18 06:44:07 +00:00
`UNSUPPORTED_TOKEN_TYPE` .
If `token` ,`installation_id`,`device_tokens`,`version` are empty, a response MUST
be sent with `error` set to `MALFORMED_MESSAGE` .
If the `version` is equal or less than the currently stored version, a response MUST
be sent with `error` set to `VERSION_MISMATCH` .
If any other error occurs the `error` should be set to `INTERNAL_ERROR` .
2020-07-23 11:27:50 +00:00
If the response is successful `success` MUST be set to `true` otherwise a response MUST be sent with `success` set to `false` .
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
`request_id` should be set to the `SHAKE-256` of the encrypted payload.
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
The response MUST be sent on the [partitioned topic][./10-waku-usage.md#partitioned-topic] of the sender
and MUST not be encrypted using the [secure transport ](../docs/stable/5-secure-transport.md ) to facilitate
the usage of ephemeral keys.
2020-06-18 06:44:07 +00:00
The payload of the response is:
```protobuf
2020-06-25 11:57:49 +00:00
message PushNotificationRegistrationResponse {
2020-07-23 11:27:50 +00:00
bool success = 1;
2020-06-18 06:44:07 +00:00
ErrorType error = 2;
bytes request_id = 3;
enum ErrorType {
UNKNOWN_ERROR_TYPE = 0;
MALFORMED_MESSAGE = 1;
VERSION_MISMATCH = 2;
UNSUPPORTED_TOKEN_TYPE = 3;
INTERNAL_ERROR = 4;
}
}
```
2020-07-23 11:27:50 +00:00
The message MUST be wrapped in a [`ApplicationMetadataMessage` ](../stable/6-payloads.6#payload-wrapper ) with type set to `PUSH_NOTIFICATION_REGISTRATION_RESPONSE` .
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
A client SHOULD listen for a response sent on the [partitioned topic][./10-waku-usage.md#partitioned-topic]
that the key used to register.
2020-06-18 06:44:07 +00:00
If `success` is `true` the client has registered successfully.
If `success` is `false` :
2020-06-25 11:57:49 +00:00
- If `MALFORMED_MESSAGE` is returned, the request SHOULD NOT be retried without ensuring
that it is correctly formed.
- If `INTERNAL_ERROR` is returned, the request MAY be retried, but the client MUST
2020-06-18 06:44:07 +00:00
backoff exponentially
A client MAY register with multiple Push Notification Servers in order to increase availability.
2020-07-23 11:27:50 +00:00
A client SHOULD make sure that all the notification services they registered with have the same information about their tokens.
2020-06-18 06:44:07 +00:00
If no response is returned the request SHOULD be considered failed and MAY be retried with the same server or a different one, but clients MUST exponentially backoff after each trial.
2020-07-23 11:27:50 +00:00
If the request is successful the token SHOULD be [advertised ](#advertising-a-push-notification-server ) as described below
### Query topic
On successful registration the server MUST be listening to the topic derived from:
```
0XHexEncode(Shake256(CompressedClientPublicKey))
```
Using the topic derivation algorithm described [here ](../stable/10-waku-usage.md#public-chats )
and listen for client queries.
### Server grant
A push notification server needs to demonstrate to a client that it was authorized
by the client to send them push notifications. This is done by building
a grant which is specific to a given client-server pair.
The grant is built as follow:
```
Signature(Keccak256(CompressedPublicKeyOfClient . CompressedPublicKeyOfServer . AccessToken), PrivateKeyOfClient)
```
When receiving a grant the server MUST be validate that the signature matches the registering client.
2020-06-18 06:44:07 +00:00
## Re-registering with the push notification server
A client SHOULD re-register with the node if the APN or FIREBASE token changes.
When re-registering a client SHOULD ensure that it has the most up-to-date
2020-07-23 11:27:50 +00:00
`PushNotificationRegistration` and increment `version` if necessary.
2020-06-18 06:44:07 +00:00
Once re-registered, a client SHOULD advertise the changes.
## Changing options
This is handled in exactly the same way as re-registering above.
## Unregistering from push notifications
2020-07-23 11:27:50 +00:00
To unregister a client MUST send a `PushNotificationRegistration` request as described
above with `unregister` set to `true` , or removing
2020-06-18 06:44:07 +00:00
their device information.
The server MUST remove all data about this user if `unregistering` is `true` ,
apart from the `hash` of the public key and the `version` of the last options,
in order to make sure that old messages are not processed.
2020-06-25 11:57:49 +00:00
A client MAY unregister from a server on explicit logout if multiple chat keys
2020-06-18 06:44:07 +00:00
are used on a single device.
## Advertising a push notification server
Each user registered with one or more push notification servers SHOULD
advertise periodically the push notification services that they have registered with for each device they own.
```protobuf
2020-07-23 11:27:50 +00:00
message PushNotificationQueryInfo {
string access_token = 1;
string installation_id = 2;
bytes public_key = 3;
repeated bytes allowed_user_list = 4;
bytes grant = 5;
uint64 version = 6;
bytes server_public_key = 7;
2020-06-18 06:44:07 +00:00
}
message ContactCodeAdvertisement {
2020-07-23 11:27:50 +00:00
repeated PushNotificationQueryInfo push_notification_info = 1;
2020-06-18 06:44:07 +00:00
}
```
2020-07-23 11:27:50 +00:00
The message MUST be wrapped in a [`ApplicationMetadataMessage` ](../stable/6-payloads.6#payload-wrapper ) with type set to `PUSH_NOTIFICATION_QUERY_INFO` .
2020-06-18 06:44:07 +00:00
If no filtering is done based on public keys,
the access token SHOULD be included in the advertisement.
Otherwise it SHOULD be left empty.
This SHOULD be advertised on the [contact code topic ](./10-waku-usage.md#contact-code-topic )
and SHOULD be coupled with normal contact-code advertisement.
Every time a user register or re-register with a push notification service, their
contact-code SHOULD be re-advertised.
Multiple servers MAY be advertised for the same `installation_id` for redundancy reasons.
## Discovering a push notification server
To discover a push notification service for a given user, their [contact code topic ](./10-waku-usage.md#contact-code-topic )
SHOULD be listened to.
A mailserver can be queried for the specific topic to retrieve the most up-to-date
contact code.
## Querying the push notification server
2020-06-25 11:57:49 +00:00
If a token is not present in the latest advertisement for a user, the server
2020-06-18 06:44:07 +00:00
SHOULD be queried directly.
To query a server a message:
```protobuf
message PushNotificationQuery {
repeated bytes public_keys = 1;
}
```
2020-07-23 11:27:50 +00:00
The message MUST be wrapped in a [`ApplicationMetadataMessage` ](../stable/6-payloads.6#payload-wrapper ) with type set to `PUSH_NOTIFICATION_QUERY` .
MUST be sent to the server on the topic derived from the hashed public key of the
key we are querying, as [described above ](#query-topic ).
An ephemeral key SHOULD be used and SHOULD NOT be encrypted using the [secure transport ](../docs/stable/5-secure-transport.md ).
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
If the server has information about the client a response MUST be sent:
2020-06-18 06:44:07 +00:00
```protobuf
message PushNotificationQueryInfo {
string access_token = 1;
string installation_id = 2;
2020-06-25 11:57:49 +00:00
bytes public_key = 3;
2020-07-23 11:27:50 +00:00
repeated bytes allowed_user_list = 4;
bytes grant = 5;
uint64 version = 6;
bytes server_public_key = 7;
2020-06-18 06:44:07 +00:00
}
message PushNotificationQueryResponse {
repeated PushNotificationQueryInfo info = 1;
2020-07-23 11:27:50 +00:00
bytes message_id = 2;
bool success = 3;
2020-06-18 06:44:07 +00:00
}
```
2020-07-23 11:27:50 +00:00
A `PushNotificationQueryResponse` message MUST be wrapped in a [`ApplicationMetadataMessage` ](../stable/6-payloads.6#payload-wrapper ) with type set to `PUSH_NOTIFICATION_QUERY_RESPONSE` .
2020-06-18 06:44:07 +00:00
Otherwise a response MUST NOT be sent.
2020-07-23 11:27:50 +00:00
If `allowed_key_list` is not set `access_token` MUST be set and `allowed_key_list` MUST NOT
2020-06-25 11:57:49 +00:00
be set.
2020-07-23 11:27:50 +00:00
If `allowed_key_list` is set `allowed_key_list` MUST be set and `access_token` MUST NOT be set.
2020-06-25 11:57:49 +00:00
If `access_token` is returned, the `access_token` SHOULD be used to send push notifications.
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
If `allowed_key_list` are returned, the client SHOULD decrypt each
token by generating an `AES-GCM` symmetric key from the Diffie– Hellman between the
2020-06-25 11:57:49 +00:00
target client and itself
If AES decryption succeeds it will return a valid [`uuid` ](https://tools.ietf.org/html/rfc4122 ) which is what is used for access_token.
The token SHOULD be used to send push notifications.
2020-07-23 11:27:50 +00:00
The response MUST be sent on the [partitioned topic][./10-waku-usage.md#partitioned-topic] of the sender
and MUST not be encrypted using the [secure transport ](../docs/stable/5-secure-transport.md ) to facilitate
the usage of ephemeral keys.
On receiving a response a client MUST verify `grant` to ensure that the server
has been authorized to send push notification to a given client.
2020-06-18 06:44:07 +00:00
## Sending a push notification
2020-06-25 11:57:49 +00:00
When sending a push notification, only the `installation_id` for the devices targeted
2020-06-18 06:44:07 +00:00
by the message SHOULD be used.
2020-06-25 11:57:49 +00:00
If a message is for all the user devices, all the `installation_id` known to the client MAY be used.
2020-06-18 06:44:07 +00:00
The number of devices MAY be capped in order to reduce resource consumption.
At least 3 devices SHOULD be targeted, ordered by last activity.
For any device that a token is available, or that a token is successfully queried,
a push notification message SHOULD be sent to the corresponding push notification server.
```protobuf
message PushNotification {
string access_token = 1;
string chat_id = 2;
2020-07-23 11:27:50 +00:00
bytes public_key = 3;
string installation_id = 4;
bytes message = 5;
2020-09-09 06:15:39 +00:00
PushNotificationType type = 6;
enum PushNotificationType {
UNKNOWN_PUSH_NOTIFICATION_TYPE = 0;
MESSAGE = 1;
MENTION = 2;
}
bytes author = 7;
2020-06-18 06:44:07 +00:00
}
message PushNotificationRequest {
repeated PushNotification requests = 1;
2020-07-23 11:27:50 +00:00
bytes message_id = 2;
2020-06-18 06:44:07 +00:00
}
```
2020-07-23 11:27:50 +00:00
A `PushNotificationRequest` message MUST be wrapped in a [`ApplicationMetadataMessage` ](../stable/6-payloads.6#payload-wrapper ) with type set to `PUSH_NOTIFICATION_REQUEST` .
2020-06-18 06:44:07 +00:00
Where `message` is the encrypted payload of the message and `chat_id` is the
2020-07-23 11:27:50 +00:00
`SHAKE-256` of the `chat_id` .
`message_id` is the id of the message
2020-09-09 06:15:39 +00:00
`author` is the `SHAKE-256` of the public key of the sender.
2020-06-18 06:44:07 +00:00
If multiple server are available for a given push notification, only one notification
MUST be sent.
2020-06-25 11:57:49 +00:00
If no response is received
a client SHOULD wait at least 3 seconds, after which the request MAY be retried against a different server
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
This message SHOULD be sent using an ephemeral key.
2020-06-18 06:44:07 +00:00
On receiving the message, the push notification server MUST validate the access token.
2020-06-25 11:57:49 +00:00
If the access token is valid, a notification MUST be sent to the gorush instance with the
2020-06-18 06:44:07 +00:00
following data:
```
{
"notifications": [
{
"tokens": ["token_a", "token_b"],
"platform": 1,
"message": "You have a new message",
"data": {
"chat_id": chat_id,
"message": message,
"installation_ids": [installation_id_1, installation_id_2]
}
}
]
}
```
Where platform is `1` for IOS and `2` for Firebase, according to the [gorush
documentation](https://github.com/appleboy/gorush)
2020-06-25 11:57:49 +00:00
A server MUST return a response message:
2020-06-18 06:44:07 +00:00
```protobuf
2020-07-23 11:27:50 +00:00
message PushNotificationReport {
bool success = 1;
ErrorType error = 2;
2020-06-25 11:57:49 +00:00
enum ErrorType {
UNKNOWN_ERROR_TYPE = 0;
2020-07-23 11:27:50 +00:00
WRONG_TOKEN = 1;
2020-06-25 11:57:49 +00:00
INTERNAL_ERROR = 2;
2020-07-23 11:27:50 +00:00
NOT_REGISTERED = 3;
2020-06-25 11:57:49 +00:00
}
2020-07-23 11:27:50 +00:00
bytes public_key = 3;
string installation_id = 4;
}
message PushNotificationResponse {
bytes message_id = 1;
repeated PushNotificationReport reports = 2;
2020-06-18 06:44:07 +00:00
}
```
2020-07-23 11:27:50 +00:00
A `PushNotificationResponse` message MUST be wrapped in a [`ApplicationMetadataMessage` ](../stable/6-payloads.6#payload-wrapper ) with type set to `PUSH_NOTIFICATION_RESPONSE` .
Where `message_id` is the `message_id` sent by the client.
The response MUST be sent on the [partitioned topic][./10-waku-usage.md#partitioned-topic] of the sender
and MUST not be encrypted using the [secure transport ](../docs/stable/5-secure-transport.md ) to facilitate
the usage of ephemeral keys.
2020-06-18 06:44:07 +00:00
2020-06-25 11:57:49 +00:00
If the request is accepted `success` MUST be set to `true` .
Otherwise `success` MUST be set to `false` .
If `error` is `BAD_TOKEN` the client MAY query again the server for the token and
retry the request.
If `error` is `INTERNAL_ERROR` the client MAY retry the request.
2020-06-18 06:44:07 +00:00
## Flow
### Registration process
- A client will generate a notification token through `APN` or `Firebase` .
- The client will [register ](#registering-with-the-push-notification-service ) with one or more push notification server of their choosing.
- The server should process the response and respond according to the success of the operation
- If the request is not successful it might be retried, and adjusted according to the response. A different server can be also used.
- Once the request is successful the client should [advertise ](#advertising-a-push-notification-server ) the new coordinates
### Sending a notification
- A client should prepare a message and extract the targeted installation-ids
- It should retrieve the most up to date information for a given user, either by
2020-07-23 11:27:50 +00:00
querying a push notification server, a mailserver if not listening already to the given topic, or checking
2020-06-18 06:44:07 +00:00
the database locally
- It should then [send ](#sending-a-push-notification ) a push notification according
to the rules described
- The server should then send a request to the gorush server including all the required
information
### Receiving a push notification
2020-06-25 11:57:49 +00:00
- On receiving the notification, a client can open the right account by checking the
2020-06-18 06:44:07 +00:00
`installation_id` included. The `chat_id` MAY be used to open the chat if present.
- `message` can be decrypted and presented to the user. Otherwise messages can be pulled from the mailserver if the `message_id` is no already present.
## Protobuf description
2020-07-23 11:27:50 +00:00
### PushNotificationRegistration
2020-06-18 06:44:07 +00:00
2020-06-25 11:57:49 +00:00
`token_type` : the type of token. Currently supported is `APN_TOKEN` for Apple Push
2020-07-23 11:27:50 +00:00
`device_token` : the actual push notification token sent by `Firebase` or `APN`
and `FIREBASE_TOKEN` for firebase.
2020-06-18 06:44:07 +00:00
`installation_id` : the [`installation_id` ](./2-account.md ) of the device
2020-07-23 11:27:50 +00:00
`access_token` : the access token that will be given to clients to send push notifications
2020-06-18 06:44:07 +00:00
`enabled` : whether the device wants to be sent push notifications
2020-07-23 11:27:50 +00:00
`version` : a monotonically increasing number identifying the current `PushNotificationRegistration` . Any time anything is changed in the record it MUST be increased by the client, otherwise the request will not be accepted.
2020-06-25 11:57:49 +00:00
`allowed_key_list` : a list of `access_token` encrypted with the AES key generated
by Diffie– Hellman between the publisher and the allowed
contact.
`blocked_chat_list` : a list of `SHA2-256` hashes of chat ids.
Any chat id in this list will not trigger a notification.
2020-07-23 11:27:50 +00:00
`unregister` : whether the account should be unregistered
`grant` : the grant for this specific server
`allow_from_contacts_only` : whether the client only wants push notifications from contacts
2020-09-03 07:59:09 +00:00
`apn_topic` : the APN topic for the push notification
`block_mentions` : whether the client does not want to be notified on mentions
`allowed_mentions_chat_list` : a list of `SHA2-256` hashes of chat ids where we want to receive mentions
2020-06-18 06:44:07 +00:00
#### Data disclosed
2020-07-23 11:27:50 +00:00
- Type of device owned by a given user
- The `FIREBASE` or `APN` push notification token
2020-06-18 06:44:07 +00:00
- Hash of the chat_id a user is not interested in for notifications
2020-07-23 11:27:50 +00:00
- The times a push notification record has been modified by the user
- The number of contacts a client has, in case `allowed_key_list` is set
2020-06-18 06:44:07 +00:00
2020-06-25 11:57:49 +00:00
### PushNotificationRegistrationResponse
2020-06-18 06:44:07 +00:00
`success` : whether the registration was successful
`error` : the error type, if any
2020-07-23 11:27:50 +00:00
`request_id` : the `SHAKE-256` hash of the `signature` of the request
2020-06-18 06:44:07 +00:00
`preferences` : the server stored preferences in case of an error
### ContactCodeAdvertisement
`push_notification_info` : the information for each device advertised
#### Data disclosed
2020-06-25 11:57:49 +00:00
- The chat key of the sender
2020-06-18 06:44:07 +00:00
### PushNotificationQuery
2020-07-23 11:27:50 +00:00
`public_keys` : the `SHAKE-256` of the public keys the client is interested in
2020-06-18 06:44:07 +00:00
#### Data disclosed
2020-07-23 11:27:50 +00:00
- The hash of the public keys the client is interested in
2020-06-18 06:44:07 +00:00
### PushNotificationQueryInfo
2020-06-25 11:57:49 +00:00
`access_token` : the access token used to send a push notification
2020-06-18 06:44:07 +00:00
`installation_id` : the `installation_id` of the device associated with the `access_token`
2020-07-23 11:27:50 +00:00
`public_key` : the `SHAKE-256` of the public key associated with this `access_token` and `installation_id`
`allowed_key_list` : a list of encrypted access tokens to be returned
2020-06-25 11:57:49 +00:00
to the client in case there's any filtering on public keys in place.
2020-07-23 11:27:50 +00:00
`grant` : the grant used to register with this server.
`version` : the version of the registration on the server.
`server_public_key` : the compressed public key of the server.
2020-06-18 06:44:07 +00:00
### PushNotificationQueryResponse
2020-07-23 11:27:50 +00:00
`info` : a list of `PushNotificationQueryInfo` .
`message_id` : the message id of the `PushNotificationQueryInfo` the server is replying to.
`success` : whether the query was successful.
2020-06-18 06:44:07 +00:00
### PushNotification
2020-07-23 11:27:50 +00:00
`access_token` : the access token used to send a push notification.
`chat_id` : the `SHAKE-256` of the `chat_id` .
`public_key` : the `SHAKE-256` of the compressed public key of the receiving client.
`installation_id` : the installation id of the receiving client.
`message` : the encrypted message that is being notified on.
2020-09-09 06:15:39 +00:00
`type` : the type of the push notification, either `MESSAGE` or `MENTION`
`author` : the `SHAKE-256` of the public key of the sender
2020-06-18 06:44:07 +00:00
### Data disclosed
2020-07-23 11:27:50 +00:00
- The `SHAKE-256` of the `chat_id` the notification is to be sent for
2020-09-09 06:15:39 +00:00
- The cypher text of the message
- The `SHAKE-256` of the public key of the sender
- The type of notification
2020-06-18 06:44:07 +00:00
### PushNotificationRequest
`requests` : a list of `PushNotification`
`message_id` : the [status message id ](./6-payloads.md )
### Data disclosed
- The status message id for which the notification is for
2020-07-23 11:27:50 +00:00
### PushNotificationResponse
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
`message_id` : the `message_id` being notified on.
`reports` : a list of `PushNotificationReport`
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
### PushNotificationReport
2020-06-18 06:44:07 +00:00
2020-07-23 11:27:50 +00:00
`success` : whether the push notification was successful.
`error` : the type of the error in case of failure.
`public_key` : the public key of the user being notified.
`installation_id` : the installation id of the user being notified.
2020-06-18 06:44:07 +00:00
## Anonymous mode of operations
2020-06-25 11:57:49 +00:00
An anonymous mode of operations MAY be provided by the client, where the
2020-06-18 06:44:07 +00:00
responsibility of propagating information about the user is left to the client,
in order to preserve privacy.
2020-06-25 11:57:49 +00:00
A client in anonymous mode can register with the server using a key different
from their chat key.
This will hide their real chat key.
2020-06-18 06:44:07 +00:00
2020-06-25 11:57:49 +00:00
This public key is effectively a secret and SHOULD only be disclosed to clients that you the user wants to be notified by.
2020-06-18 06:44:07 +00:00
A client MAY advertise the access token on the contact-code topic of the key generated.
2020-06-25 11:57:49 +00:00
A client MAY share their public key through [contact updates ](./6-payloads.md#contact-update )
2020-06-18 06:44:07 +00:00
2020-06-25 11:57:49 +00:00
A client receiving a push notification public key SHOULD listen to the contact code
topic of the push notification public key for updates.
2020-06-18 06:44:07 +00:00
The method described above effectively does not share the identity of the sender
nor the receiver to the server, but MAY result in missing push notifications as
the propagation of the secret is left to the client.
This can be mitigated by [device syncing ](./6-payloads.md ), but not completely
addressed.
## Security considerations
If no anonymous mode is used, when registering with a push notification service a client discloses:
2020-06-25 11:57:49 +00:00
- The chat key
2020-06-18 06:44:07 +00:00
- The devices that will receive notifications
A client MAY disclose:
- The hash of the chat_ids they want to filter out
2020-06-25 11:57:49 +00:00
When running in anonymous mode, the client's chat key is not disclosed.
2020-06-18 06:44:07 +00:00
2020-06-25 11:57:49 +00:00
When querying a push notification server a client will disclose:
2020-06-18 06:44:07 +00:00
2020-06-25 11:57:49 +00:00
- That it is interested in sending push notification to another client,
but the querying client's chat key is not disclosed
2020-06-18 06:44:07 +00:00
2020-06-25 11:57:49 +00:00
When sending a push notification a client discloses:
2020-07-23 11:27:50 +00:00
- The `SHAKE-256` of the chat id
2020-06-18 06:44:07 +00:00
2020-06-25 11:57:49 +00:00
[//]: This section can be removed, for now leaving it here in order to help with the
review process. Point can be integrated, suggestion welcome.
2020-06-18 06:44:07 +00:00
## FAQ
### Why having ACL done at the server side and not the client?
2020-06-25 11:57:49 +00:00
We looked into silent notification for
2020-06-18 06:44:07 +00:00
[IOS ](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app ) (android has no equivalent)
but can't be used as it's expected to receive maximum 2/3 per hour, so not our use case. There
are also issue when the user force quit the app.
### Why using an access token?
The access token is used to decouple the requesting information from the user from
actually sending the push notification.
2020-06-25 11:57:49 +00:00
Some ACL is necessary otherwise it would be too easy to spam users (it's still fairly
2020-06-18 06:44:07 +00:00
trivial, but with this method you could allow only contacts to send you push notifications).
Therefore your identity must be revealed to the server either when sending or querying.
2020-06-25 11:57:49 +00:00
By using an access token we increase deniability, as the server would know
who requested the token but not necessarily who sent a push notification.
2020-06-18 06:44:07 +00:00
Correlation between the two can be trivial in some cases.
This also allows a mode of use as we had before, where the server does not propagate
info at all, and it's left to the user to propagate the token, through contact requests
for example.
### Why advertise with the bundle?
Advertising with the bundle allows us to piggy-back on an already implemented behavior
2020-06-25 11:57:49 +00:00
and save some bandwidth in cases where is not filtering by public keys
2020-06-18 06:44:07 +00:00
### What's the bandwidth impact for this?
Generally speaking, for each 1-to-1 message and group chat message you will sending
2020-06-25 11:57:49 +00:00
1 and `number of participants` push notifications. This can be optimized if
multiple users are using the same push notification server. Queries have also
2020-06-18 06:44:07 +00:00
a bandwidth impact but they are made only when actually needed
### What's the information disclosed?
The data disclosed with each message sent by the client is above, but for a summary:
When you register with a push notification service you may disclose:
2020-06-25 11:57:49 +00:00
1) Your chat key
2020-06-18 06:44:07 +00:00
2) Which devices you have
3) The hash of the chat_ids you want to filter out
2020-06-25 11:57:49 +00:00
4) The hash of the public keys you are interested/not interested in
2020-06-18 06:44:07 +00:00
When you query a notification service you may disclose:
2020-06-25 11:57:49 +00:00
1) Your chat key
2020-06-18 06:44:07 +00:00
2) The fact that you are interested in sending push notification to a given user
Effectively this is fairly revealing if the user has a whitelist implemented.
Therefore sending notification should be optional.
### What prevents a user from generating a random key and getting an access token and spamming?
Nothing really, that's the same as the status app as a whole. the only mechanism that prevents
this is using a white-list as described above, but that implies disclosing your true identity to the push notification server.
### Why not 0-knowledge proofs/quantum computing
We start simple, we can iterate
### How to handle backward/forward compatibility
Most of the request have a target, so protocol negotiation can happen. We cannot negotiated
the advertisement as that's effectively a broadcast, but those info should not change and we can
always accrete the message.
2020-06-25 11:57:49 +00:00
### Why ack_key?
2020-06-18 06:44:07 +00:00
2020-06-25 11:57:49 +00:00
That's necessary to avoid duplicated push notifications and allow for the retry
in case the notification is not successful.
2020-06-18 06:44:07 +00:00
2020-06-25 11:57:49 +00:00
Deduplication of the push notification is done on the client side, to reduce a bit
of centralization and also in order not to have to modify gorush.
2020-06-18 06:44:07 +00:00
### Can I run my own node?
Sure, the methods allow that
### Can I register with multiple nodes for redundancy
Yep
### What does my node disclose?
2020-06-25 11:57:49 +00:00
Your node will disclose the IP address is running from, as it makes an HTTP post to
2020-06-18 06:44:07 +00:00
gorush. A waku adapter could be used, but please not now.
### Does this have high-reliability requirements?
The gorush server yes, no way around it.
The rest, kind of, at least one node having your token needs to be up for you to receive notifications.
But you can register with multiple servers (desktop, status, etc) if that's a concern.
### Can someone else (i.e not status) run this?
Push notification servers can be run by anyone. Gorush can be run by anyone I take,
but we are in charge of the certificate, so they would not be able to notify status-clients.
## Changelog
### Version 0.1
Released [](https://github.com/status-im/specs/commit/)
- Initial version
## Copyright
Copyright and related rights waived via [CC0 ](https://creativecommons.org/publicdomain/zero/1.0/ ).