Open-Source Wikis

/

Bitwarden Server

/

Apps

/

Notifications

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.sh

Key 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 IPushNotificationService to 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 to IPushNotificationService, and route it in HubHelpers.SendNotificationAsync.
  • Changing connection authorization → extend NotificationsHub.OnConnectedAsync and the JWT policies in Startup.
  • Tuning hub limits → see globalSettings.Notifications and the MapHub<NotificationsHub> options in Startup.Configure.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Notifications – Bitwarden Server wiki | Factory