fix(webpush): resolve push subscription bugs for multi-device and shared browsers#3142
fix(webpush): resolve push subscription bugs for multi-device and shared browsers#3142fallenbagel wants to merge 2 commits into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughThis PR isolates push subscriptions per endpoint, tightens stale-subscription cleanup to auth-scoped deletions, verifies ownership during enable/disable and resubscribe flows, and adds best-effort push cleanup during logout. ChangesPush Subscription Multi-Device Isolation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
02c1975 to
8aac087
Compare
8aac087 to
5f4b19e
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@server/routes/user/index.ts`:
- Around line 286-294: The cleanup currently requires both req.body.userAgent
and req.body.auth and filters by userAgent in transactionalRepo.find, which
skips stale rows when userAgent changed and can cause unique auth conflicts;
change the conditional to run when req.body.auth is present (remove the
dependence on req.body.userAgent) and update the find() where clause used in
transactionalRepo.find to match by auth and user id with endpoint:
Not(req.body.endpoint) (remove the userAgent equality requirement) so stale
subscriptions are removed based on auth regardless of userAgent.
In `@src/utils/pushSubscriptionHelpers.ts`:
- Around line 87-95: The verification step currently treats any false from
verifyPushSubscription() as an explicit "invalid" and unconditionally calls
unsubscribeToPushNotifications() then resubscribes; change
verifyPushSubscription() to return a typed outcome (e.g., enum/union: "valid" |
"invalid" | "verification_error") or make it throw on transient/non-404 errors,
then update the try block to only call unsubscribeToPushNotifications(userId)
and subsequent subscribeToPushNotifications(userId, currentSettings) when the
outcome is explicit "invalid"; for "verification_error" propagate or throw so
the caller can retry instead of tearing down the browser subscription, and keep
downstream ownership/disable checks gated by the explicit "invalid" result.
Ensure references: verifyPushSubscription, unsubscribeToPushNotifications,
subscribeToPushNotifications are updated accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: eaa5c7ec-bf15-4d0e-bb1f-4aba741b8cda
📒 Files selected for processing (4)
server/routes/user/index.tssrc/components/Layout/UserDropdown/index.tsxsrc/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush/index.tsxsrc/utils/pushSubscriptionHelpers.ts
…ations Stale cleanup matched only on userAgent, deleting subscriptions from subling devices that share a UA string (e.g. two iphones of the same model). Now requires matchin auth so only tru iOS endpoint rotations are cleaned up. fix #2660
…browsers Logout now unsubscribes and clears push state; verifyWebPush no longer treats any browser subscription as proof the current user is enabled; verifyAndResubscribePushSubscription re-registers orphaned subscriptions instead of bailing; disable path verifies ownership before unsubscribing to avoid killing a sibling user's working subscription.
5f4b19e to
15f0d14
Compare
Description
This PR fixes a cluster of web push notification bugs affecting non-admin users, multi-device setups, and shared browsers.
Note
The changes are split into separate commits so they remain individually bisectable after the rebase merge. We should rebase merge rather than squash so commit boundaries are preserved on
develop.Previously, cleanup matched only on
userAgent, which meant two devices of the same model and OS/browser version sharing an identical user agent string were treated as the same device. Registering on the second device could delete the first device's subscription, breaking its notifications.The cleanup now also requires a matching
authkey, so only a true push-service endpoint rotation, same subscription identity with a new endpoint, is cleaned up. Duplicate detection remains endpoint-based so same-authendpoint rotations can still replace the stale endpoint. Sibling devices that share a user agent but have distinct subscriptions are left intact. Any subscription that becomes genuinely invalid is still pruned by the delivery path, which removes subscriptions on a410or404response per RFC 8030.The second commit addresses cross-user contamination on shared browsers, where browser-level push subscriptions are per-origin and can otherwise persist across logout/login transitions.
Logout now unsubscribes the browser-level push subscription, deletes that endpoint from the current user's backend records, and clears the local enablement flag. This prevents a later user on the same browser from inheriting the previous user's push state.
The verification routine no longer treats the mere presence of any browser subscription as proof that the current user is subscribed. It verifies ownership against the current user's records. The resubscribe routine no longer bails out when a browser subscription exists but does not belong to the current user; it tears down the orphaned browser subscription and registers a fresh one. The disable action also verifies ownership before unsubscribing or deleting, so a user disabling push on a shared browser can no longer silently kill another user's working subscription.
How Has This Been Tested?
0xsysr3lland receive notifications independently.userAgentbut different push subscription keys can coexist in the database.0xsysr3ll's push state.0xsysr3lldoes not show a stale browser subscription while the iPhone subscriptions remain intact.Screenshots / Logs (if applicable)
Checklist:
pnpm buildpnpm i18n:extractSummary by CodeRabbit
New Features
Bug Fixes