Introduction
UnifiedPush is a protocol that allows applications to receive push messages, while letting the user choose which push provider they wish to use.
In this ecosystem, we can identify 2 different sides:
- The push provider
The service that provides the UnifiedPush functionality.
It again consists of two parts.
- An application called distributor, that keeps a constant connection with its push server, and forwards notifications to other apps.
- A push server that receives push notifications from an application server and relays them to the distributor.
- The end user applications A typical application that uses the push service. Their server sends messages to the mobile application through the push server and the distributor.
Any application can be used with any distributor. Users can install multiple distributors. Users can set a default distributor or make applications ask the user which distributor should be used. So users have a choice on which distributor should be used for which app. For more details, see the User Experience guide.
ImportantWhen adding UnifiedPush support to your app, you should test the feature with at least 2 different distributors!
Push notification is a misleading name, it gives the impression that every push notification leads to an actual notification shown on the user interface. Push message would be more accurate, as this implies that not every message received actually leads to a notification. One must imagine the push system more like a tool for an application server to wake up its client, for example, when the server wants the client to synchronize with it. This can happen entirely in the background without the user noticing.
UnifiedPush uses two main standards/specifications:
- Web Push is used for the connection between the application server and the push server.
- The UnifiedPush specification is used for the communication between the distributor app and the end user application. There are separate specifications for Android and Linux.
Note that the following parts of the UnifiedPush system are deliberately not standardized:
- The connection between the push server and the distributor app.
- The connection between the application server and the end user application.
It’s the choice of the push provider to decide how the push server and distributor app communicate with each other.
Push notifications are encrypted following RFC8291. An application generates a public key and an authentication secret, which it shares with its application server along with the push server endpoint. The application server can then use this information to encrypt the content of the notifications.
ImportantSome libraries are outdated and support a draft of the RFC8291 (the 4th draft) and won’t work. To check if the library supports the RFC correctly, check thecontent-encodingheader: it must beaes128gcm.
Push notifications may be authenticated with VAPID (RFC8292). VAPID is a mechanism to authenticate requests to a push server, using asymmetric keys. These keys are generated by the application server. The mobile application fetches the public key and uses it to register to the distributor, which will be able to add restrictions for your subscription. VAPID adds an additional security layer on push notifications; endpoints are already Capability URLs that should not be guessable.
ImportantSome push providers require a VAPID key to get registrations, if they don’t have it, they will respond to registration with a failure.
Some other push providers may ignore VAPID authorizations.
This blog post gives more insight about the security of push notifications.
The content of the cleartext inside the notification is totally dependent on the application itself. It may be a JSON containing the information that can be used to create a UI notification directly, a simple ping to tell the app to synchronize, a message the app needs to parse, and so on.
When adding Web Push support to an application server, you should take the following points into account.
After receiving a new push registration, it is recommended for the application server to validate the new push channel before sending actual notifications using VAPID. This prevents the Web Push server from being used for Denial Of Service (DOS) amplification. This is especially relevant in a federated context where a single event could trigger push messages to many different servers.
During the registration, the server should send a unique token to the application through a push message, and the app should send the token back to the app server. If this succeeds, the application server can safely use the newly registered channel.
Additionally, the application server should reject push endpoints that resolve to non-global IP addresses, in order to limit server-side request forgery (SSRF).
The server should check this for every push message it sends. After the domain resolution, and before sending the request.
At a minimum, private IP addresses such as RFC 1918 and RFC 4193 must be denied. Excluding other non-global IP ranges is recommended, but not as critical (e.g., link-local or broadcast addresses). Many programming languages have library functions for this, for example, Rust.
If the application server is self-hostable, it should provide an option to allow-list domains and IP ranges (to allow for self-hosted private push servers).
The specifications can be overwhelming. Luckily, libraries are available, so that you don’t have to implement these protocols yourself.
On the end user application side, the UnifiedPush connector libraries handle things for you: they generate encryption keys during a new registration, and automatically decrypt incoming messages. Libraries are available for both Android and Linux.
On the application server side, you should use a Web Push library. Most programming languages and frameworks should have such a library available. Make sure that the library complies with the latest version of the Web Push RFCs (see above).
The high-level flow of adding UnifiedPush support to your app looks as follows:
- Include one of the UnifiedPush connector libraries in your end user application. Build the user flows for handling the different situations, for example, selecting from multiple installed distributors.
- Include a Web Push library in your application server.
- Build your own API for communicating between your end user application and your application server.
It needs to have the following features:
- The end user application may query the application server for the VAPID public key (optional, but recommended).
- The end user application sends the push registration to the application server. This registration includes a push URL, a public key and an auth secret (RFC8291).
- Note: These values are generally provided by and consumed by the UnifiedPush connector library and the Web Push library. You don’t need to generate them, you only need to send them between your app and server.
If you wish to write a new distributor, to provide push notifications to other applications, you need to look at UnifiedPush specifications, starting with the Definitions.