Agent Wranglers

Recommended

Send the current subscription to the server on every start

Read the push subscription or device token each time the app starts, and send it to the server when it changed. Never trust a copy cached on the device.

How to do it

The Push API fires pushsubscriptionchange when a subscription changes outside the app's control. Not every browser fires it, so also call getSubscription() on each start and compare the endpoint. Apple says to register for a device token at every launch and never cache it, because restores and reinstalls issue a new one. Firebase asks you to store a timestamp with each registration and update it on every upload. Save with an upsert keyed by endpoint or token, as Make writes safe to repeat says.

Examples

Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

JavaScript example

// Service worker
self.addEventListener('pushsubscriptionchange', event => {
  event.waitUntil((async () => {
    const fresh = event.newSubscription ?? await self.registration.pushManager.subscribe(
      { userVisibleOnly: true, applicationServerKey: VAPID_PUBLIC_KEY });
    await fetch('/push/subscriptions', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ subscription: fresh, replaces: event.oldSubscription?.endpoint }),
    });
  })());
});

Plain text example

func application(_ application: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.map { String(format: "%02x", $0) }.joined()
    Task { try await api.post("/push/tokens", body: ["token": token]) } // called on every launch, no local cache
}

How to check

Unsubscribe the test browser's subscription by hand and reload the app. Within one start, the server holds the new endpoint and no row for the old one. Restore a test phone from a backup, and the server gets its new token at first launch.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/notifications/push-notifications/refresh-push-subscriptions">Agent Wranglers notifications playbook</a>. In code you write, add a comment next to it with the same link.