HTTP Web Push: Advanced Progressive Web Apps – Push Notifications Under Control – Part 3

The third part of the PWA push notification series will take a closer look at the HTTP Web Push protocol. If you want to learn more about the Notifications API or the Push API, check out the first two parts.

In diesem Artikel:

cl-neu
Christian Liebel ist Consultant bei Thinktecture. Sein Fokus liegt auf Webstandards und Progressive Web Apps. Er vertritt Thinktecture beim W3C.

Article Series

  1. Notifications API
  2. Push API
  3. HTTP Web Push ⬅
  4. Additional Approaches

Delivering Push Messages via HTTP Web Push

The third specification we want to discuss is HTTP Web Push, an infrastructure protocol standardized by the Internet Engineering Task Force (IETF) in RFC 8030. Web Push is a single abstract protocol that can be used in combination with any push service supporting Push API. Among others, it specifies the HTTP endpoints called by application servers to deliver push messages or request delivery receipts. When sending a push message, developers can determine the urgency of the notification. For instance, incoming phone calls are urgent compared to an advertising message sent by a free-to-play game. Also, they can specify a Time to live (TTL) for messages with a limited life span, such as daily offers. Furthermore, push messages can also be updated or deleted, for example, when users edit an instant message or remove it.

Keeping Your Push Messages Secure

Guaranteeing security and privacy was one of the main goals when web-based push notifications where specified: Nobody should be able to intercept or tamper with the push messages sent from your backend to the client. Hence, push messages should be signed and encrypted. Web Push message encryption is based on a public/private key procedure and allows for end-to-end encryption of push messages (RFC 8291). At least Google Chrome requires developers to encrypt the contents of their push messages. As a result, not even the platform’s push service (which may or may not be trustworthy) can read the contents of your push messages; they can merely see the traffic data like the amount and size of your messages.

Voluntarily Identify Your Application Server

As mentioned in the first part of this series, each platform uses its own push service: On desktop systems, Firefox uses the Mozilla Push Service, Edge relies on the Windows Notification Services, and Chrome uses Firebase Cloud Messaging. Other browser vendors may implement their push services. As the Web Push protocol is entirely abstract, developers cannot know in advance which push services their application server will need to connect to. Consequently, developers can’t authenticate their application server at the push service using API keys or logins, and using the push infrastructure is completely free. Developers can send in as many push messages as they like. However, push services could stop accepting messages from the application server in case of abuse or misconfiguration. To prevent disruptions, developers can voluntarily identify themselves so that the push service operator could contact them.

This is where the Voluntary Application Server Identification (VAPID, RFC 8292) comes in. VAPID allows developers to specify contact information, such as their email address or website, and provides a corresponding authentication scheme for communication between the application server and the push service. Fortunately, developers do not have to implement the VAPID authentication scheme or communicate with push services themselves. There are ready-to-use libraries for a wide range of server platforms such as Node.js, .NET, Java, or Python. The complete list of web push libraries can be found at GitHub.

Generating VAPID Key Pairs

To send messages to subscribed clients, the developer first needs a pair of VAPID keys. The following code snippet shows how to create a key pair in Node.js.

				
					const webpush = require('web-push');
const vapidKeys = webpush.generateVAPIDKeys(); // do this only once!
				
			

The resulting object in vapidKeys contains the publicKey and the privateKey. Please note that the application server should only generate VAPID keys once and then keep using the same pair, as it shares its public key with the client application. The web-push package for Node.js can also be used as a command-line tool to generate keys:

				
					npm i -g web-push
web-push generate-vapid-keys
				
			

If you want to play around with HTTP Web Push, you can also make use of https://pwapraxis-push.glitch.me/, which generates valid VAPID keys. Internally, this website uses the same web-push package.

The application server must then make its public key available to the client application, for instance, by providing an HTTPS endpoint to request it.

Using The Public VAPID Key

In the second part of the series, we demonstrated the web push flow between the client application on the user’s device and the platform’s push service. Let’s take another look at the registerForPush() method implemented in the client application:

				
					async function registerForPush(pushManager) {
  try {
    const subscription = await pushManager.subscribe({
      userVisibleOnly: true,
      applicationServerKey: new Uint8Array([/* Public VAPID key */])
    });
    await fetch('https://example.com/push/subscribe', { method: 'POST', body: JSON.stringify(subscription.toJSON()) })
  } catch (error) {
    console.error(error);
  }
}
				
			

When subscribing for push messages, the client application needs to specify an applicationServerKey. This is the generated public VAPID key from above. The key can either be hard-coded or, more elegantly, retrieved from the application server via an HTTPS endpoint. If subscribing was successful, the browser returns the push subscription for this very client application. The push subscription then has to be sent to the application server.

In the listing from above, the application server implements an endpoint, where the subscription will be sent to. The subscription can then be stored in a database. Typically, the user authenticates with the application server so that it can assign the push subscription to the respective user. Please bear in mind that a user can have more than one device and thus more than one active push subscription.

Sending Push Messages to Your Users

Back on the application server, we now want to send push messages to our subscribed users. Therefore, the web-push library from above needs to be configured first.

				
					webpush.setVapidDetails('mailto:example@yourdomain.org', vapidKeys.publicKey, vapidKeys.privateKey);

				
			

As shown in the listing, this is also the point where developers can voluntarily identify themselves. Furthermore, the public and private VAPID keys have to be specified.

With the library configured, and the push subscription transferred to the application server, developers can send push messages to clients. The application server typically delivers push messages after a change of data (e.g., a new instant message or a price update) to the affected users. With the help of the web-push package, this is as simple as follows:

				
					webpush.sendNotification(pushSubscription, { title: 'Hello' });
				
			

Developers simply call the sendNotification() method with the push subscription they want to send the push message to. Remember that even a single user can have more than one push subscription, so make sure to call this method for all affected subscriptions. Furthermore, the method takes the payload that should be sent to the subscription. The library then takes care of encrypting the content and sending it to the push service specified by the subscription. As described in the previous part, the service worker of the client application should now wake up and present the push notification to the user.

The application server will be notified if the push message could be delivered, or an error has occurred. In case the push subscription is not valid (anymore), the server should remove it from its store of push subscriptions.

Web Push Limitations

Currently, there are some limitations when dealing with web-based push notifications: For instance, no silent pushes are allowed. Each push message must lead to a push notification banner visible to the user. The Chrome team experiments with a Budget API that allows a few silent pushes per day. An inline reply functionality is not (yet) a part of the Notification API. Finally, Apple Safari does not support Push API—neither on desktop nor mobile. While there is an alternative for the desktop platform, Safari Push Notifications, it is cumbersome to implement and operate. Unfortunately, there is no information available if Apple will ever support Push API on Safari.

The WebKit Team is collecting use cases for push notification via their bug tracker for Progressive Web Apps, to consider supporting them. So feel free to add your use case and help to prove the relevance of push notifications.

Conclusion

HTTP Web Push is the missing piece to complete the puzzle of web-based push notifications: Secure, privacy-preserving, free to use, and, with the help of web push libraries, simple to implement. In the next and final part of this series, we’ll have a look at some more aspects, such as alternative approaches for Safari, and what Project Fugu has in store for notifications on the web.

Kostenloser
Newsletter

Aktuelle Artikel, Screencasts, Webinare und Interviews unserer Experten für Sie

Verpassen Sie keine Inhalte zu Angular, .NET Core, Blazor, Azure und Kubernetes und melden Sie sich zu unserem kostenlosen monatlichen Dev-Newsletter an.

Newsletter Anmeldung
Diese Artikel könnten Sie interessieren
Angular
sl_300x300

View Transition API Integration in Angular—a brave new world (Part 1)

If you previously wanted to integrate view transitions into your Angular application, this was only possible in a very cumbersome way that needed a lot of detailed knowledge about Angular internals. Now, Angular 17 introduced a feature to integrate the View Transition API with the router. In this two-part series, we will look at how to leverage the feature for route transitions and how we could use it for single-page animations.
15.04.2024
Low-angle photography of metal structure
AI
cl-neu

AI-Funktionen zu Angular-Apps hinzufügen: lokal und offlinefähig

Künstliche Intelligenz (KI) ist spätestens seit der Veröffentlichung von ChatGPT in aller Munde. Wit WebLLM können Sie einen KI-Chatbot in Ihre eigenen Angular-Anwendungen integrieren. Wie das funktioniert und welche Vor- und Nachteile WebLLM hat, lesen Sie hier.
26.02.2024
Angular
sl_300x300

Konfiguration von Lazy Loaded Angular Modulen

Die Konfigurierbarkeit unserer Angular-Module ist für den Aufbau einer wiederverwendbaren Architektur unerlässlich. Aber in der jüngsten Vergangenheit hat uns Angular seine neue modullose Zukunft präsentiert. Wie sieht das Ganze jetzt aus? Wie konfigurieren wir jetzt unsere Lazy-Komponenten? Lasst uns gemeinsam einen Blick darauf werfen.
03.08.2023
Blazor
favicon

Blazor WebAssembly in .NET 7: UI-Performance-Optimierung auf Komponentenebene

Stockende UI, keine Reaktion nach dem Klick auf einen Button oder einer Eingabe in einem Feld - dies sind nur wenige Beispiele alltäglicher Probleme, die der Nutzung von Client-Anwendungen im Allgemeinen, und bei Webanwendungen im Speziellen, immer wieder auftreten können. In diesem Artikel schauen wir uns an, wie wir komponentenbasierte UIs in Blazor WebAssembly optimieren können, um dadurch eine für die Benutzer zufriedenstellende Geschwindigkeit und ein flüssiges UI zu bekommen.
29.03.2023
Blazor
sg

Understanding and Controlling the Blazor WebAssembly Startup Process

There are a lot of things going on in the background, when a Blazor WebAssembly application is being started. In some cases you might want to take a bit more control over that process. One example might be the wish to display a loading screen for applications that take some time for initial preparation, or when users are on a slow internet connection. However, in order to control something, we need to understand what is happening first. This article takes you down the rabbit hole of how a Blazor WASM application starts up.
07.03.2023
.NET
cl-neu

Adding Superpowers to your Blazor WebAssembly App with Project Fugu APIs

Blazor WebAssembly is a powerful framework for building web applications that run on the client-side. With Project Fugu APIs, you can extend the capabilities of these apps to access new device features and provide an enhanced user experience. In this article, learn about the benefits of using Project Fugu APIs, the wrapper packages that are available for Blazor WebAssembly, and how to use them in your application.

Whether you're a seasoned Blazor developer or just getting started, this article will help you add superpowers to your Blazor WebAssembly app.
28.02.2023