bitwarden/server
Notifications
Active contributors: platform team.
Purpose
src/Notifications/ is the real-time push service. Clients open an authenticated SignalR connection (/hub) to it and receive vault-update / login-request / notification-center messages. Other Bitwarden services (notably Api) call into Notifications via an internal HTTP/SignalR contract to fan a message out to a user's connected devices.
Directory layout
src/Notifications/
├── Program.cs / Startup.cs
├── NotificationsHub.cs # The authenticated SignalR hub
├── AnonymousNotificationsHub.cs # The unauthenticated hub (used during pre-login flows)
├── HubHelpers.cs # 13KB of routing helpers — converts incoming PushNotificationData → SignalR group sends
├── AzureQueueHostedService.cs # Drains a "notifications" queue if the API publishes via queue
├── HeartbeatHostedService.cs # Periodic health/keep-alive
├── ConnectionCounter.cs # In-memory counter of connected clients per user
├── INotificationHub.cs
├── SubjectUserIdProvider.cs # Extracts the userId from the JWT claims
├── Controllers/ # Internal HTTP endpoints (e.g. POST /send) for service-to-service push
├── Jobs/ # Quartz jobs for periodic cleanup
└── appsettings.*.json + Dockerfile + entrypoint.shKey abstractions
| Type | Path | Description |
|---|---|---|
NotificationsHub |
src/Notifications/NotificationsHub.cs |
SignalR hub clients connect to. Authorisation via Bearer JWT; on connect, joins the user-scoped group. |
HubHelpers |
src/Notifications/HubHelpers.cs |
Switch over PushType (cipher created, cipher updated, folder created, login request, notification status, …). Sends to the right SignalR group(s). |
AnonymousNotificationsHub |
src/Notifications/AnonymousNotificationsHub.cs |
Listens for login-request approvals during the auth-request flow when the requester is not yet authenticated. |
AzureQueueHostedService |
src/Notifications/AzureQueueHostedService.cs |
Optional: when push is delivered via queue, this drains it into hub sends. |
HeartbeatHostedService |
src/Notifications/HeartbeatHostedService.cs |
Periodic SignalR keep-alive / connection counting. |
IPushNotificationService impls |
src/Core/Platform/Push/ |
The API uses these to talk to Notifications and to Azure Notification Hub for mobile push. |
How it works
sequenceDiagram
participant C as Client
participant Api
participant N as Notifications
participant ANH as Azure Notification Hub
C->>N: WS /hub (Bearer JWT)
N->>N: SignalR JoinGroup(userId)
Api->>N: NotificationHubProxy.SendAsync(userId, payload)
N->>N: HubHelpers routes to user group
N-->>C: Push (web / desktop / browser ext)
Api->>ANH: ANH push (mobile devices)Mobile push is not sent through Notifications — it goes through Azure Notification Hub via NotificationHubPushNotificationService (src/Core/Platform/Push/). Notifications is responsible for everything that is currently connected over WebSocket: web, browser extension, desktop, CLI sync.
Integration points
- Identity — Bearer JWT validation. The user id from the JWT determines the SignalR group.
- API — calls Notifications via HTTP/SignalR proxy in
IPushNotificationServiceto push events. - Azure Storage Queue — when configured, the API enqueues push messages and Notifications drains them via
AzureQueueHostedService(so push is durable and survives a restart of the SignalR host). - Azure Notification Hub — for mobile, the API talks directly to Azure Notification Hub through
NotificationHubPushNotificationService. Self-host proxies through Bitwarden's cloud relay (IRelayPushNotificationService).
Self-host
A self-hosted instance runs Notifications as a container. The bundled nginx config maps /notifications/* to it. Mobile push uses the relay-mode service which forwards to Bitwarden's cloud Notification Hub on behalf of the customer.
Entry points for modification
- Adding a new push event → add a value to
PushType(src/Core/Platform/Push/PushType.cs— explicitly excluded from CODEOWNERS so any team can add to it), add a method toIPushNotificationService, and route it inHubHelpers.SendNotificationAsync. - Changing connection authorization → extend
NotificationsHub.OnConnectedAsyncand the JWT policies inStartup. - Tuning hub limits → see
globalSettings.Notificationsand theMapHub<NotificationsHub>options inStartup.Configure.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.