1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-12 22:44:11 +00:00
Files
browser/libs/common/src/platform/server-notifications/README.md
Justin Baur f4e497e005 Formatting
2025-09-04 13:24:40 -04:00

4.8 KiB

Server Notifications

About

This is the clients equivalent of server push notifications. The ServerNotificationsService takes care of receiving the notifications from our server no matter the technology needed to make it happen behind the scenes.

Usage

At the current moment the best way to consume a notification pushed to our client is by adding code to the switch statement in the processNotification method of DefaultServerNotificationsService. It's best to put as much of your logic in your own service and inject and call a method on that service in response to your notification type being processed.

In the future, notifications will be able to be handled in response to the notifications$ observable. This stream will contain all notifications that come from our server and it will be your responsibility to filter out for only the notifications you care about and to parse the payload into your expected type. Through this stream you will also be required to filter out if the notification should not be handled as the current device was the originator of the notification or if you only want to handle the notifications of the currently active user.

Implementation

There are three server notification service implementations available for our clients, with specific use cases detailed below.

Default

The default implementation is the main implementation that actually does the actions people expect it to do. This service manages the logic for when we should connect, ensuring we always have a connection during those times, and trying to limit reconnection events to only when necessary. The service establishes a connection for the active user if they have an available access token and a notification URL other than http://-, which is used as a special value to say that notifications should not be used. Then the service will reach out to the injected WebPushConnectionService for its support status on if it supports web push. If it does support web push it will give us an object to use to connect to web push notifications. If that service tells us web push is not supported or any exceptions happen in the web push stream we fall back to connecting to SignalR notifications. We are sure to use the rxjs operator distinctUntilChanged on a lot of these events to help avoid doing unnecessary reconnects.

This structure allows us to inject a different implementation of WebPushConnectionService based on the client, depending on the best way to use web push in that client's ecosystem. For now it is only using the Service Worker of our Chrome MV3 extension. Possible future implementation of this service could be a Worker in our web app. This would require that we request the Notification permission and that browsers start allowing userVisibleOnly: false. Another possible implementation that could apply to web and desktop would be using our autopush-manager package. That package uses web sockets under the hood but implements the cryptography layer of web push on top of it so that we can offload the socket connection to another party.

The injected SignalRConnectionService is another service that we can utilize to make the below foreground service not needed anymore. Instead of having a whole different ServerNotificationService implementation we can have a new implementation of this and it can defer to the service worker for the more persistent connection but send SignalR messages through MessageSender. Since web push shouldn't have any problem of creating multiple connection per browser context this brings the solution closer to the actual problem.

Noop

This is a special implementation that can be opted into being used through the dev flag noopNotifications. When that flag is true then the noop version of server notifications will be used. This is usually done to keep the console cleaner from any logs that might happen from the default implementation. We could, in the future decide to depracate this implementation in favor of instructing users to use http://- as their notifications url in the local.json configuration. That should largely have the same behavior and would allow us to maintain one fewer implementation.

Foreground

The foreground implementation is specially for browser foreground instances. At the moment this service acts as a stub to avoid accidentally doubling up SignalR connections. If we had the default implementation in both the background service worker and in each foreground instance anyone then would be a web socket connection made in each. With this special instance we avoid that by doing nothing at the moment. Once we begin to fully support the notifications$ observable we can make a choice whether or not keep not supporting it in the browser foreground or we can decide to support it through messaging the background.