From f657d198b6d42eec6467c5c5fe620322b8562891 Mon Sep 17 00:00:00 2001 From: 0xsysr3ll <0xsysr3ll@pm.me> Date: Sun, 7 Dec 2025 15:15:49 +0100 Subject: [PATCH] fix(webpush): add backend subscription check to determine if a valid push subscription exists. Signed-off-by: 0xsysr3ll <0xsysr3ll@pm.me> --- src/utils/pushSubscriptionHelpers.ts | 47 +++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/utils/pushSubscriptionHelpers.ts b/src/utils/pushSubscriptionHelpers.ts index e65c84ee1..cf71fe2db 100644 --- a/src/utils/pushSubscriptionHelpers.ts +++ b/src/utils/pushSubscriptionHelpers.ts @@ -32,16 +32,26 @@ export const verifyPushSubscription = async ( return false; } + let hasBackendSubscriptions = false; + try { + const { data: backendSubscriptions } = await axios.get< + UserPushSubscription[] + >(`/api/v1/user/${userId}/pushSubscriptions`); + hasBackendSubscriptions = backendSubscriptions.length > 0; + } catch { + hasBackendSubscriptions = false; + } + try { const { subscription } = await getPushSubscription(); if (!subscription) { - return false; + return hasBackendSubscriptions; } const appServerKey = subscription.options?.applicationServerKey; if (!(appServerKey instanceof ArrayBuffer)) { - return false; + return hasBackendSubscriptions; } const currentServerKey = new Uint8Array(appServerKey).toString(); @@ -49,15 +59,26 @@ export const verifyPushSubscription = async ( currentSettings.vapidPublic ).toString(); + if (currentServerKey !== expectedServerKey) { + return hasBackendSubscriptions; + } + const endpoint = subscription.endpoint; - const { data } = await axios.get( - `/api/v1/user/${userId}/pushSubscription/${encodeURIComponent(endpoint)}` - ); + try { + const { data } = await axios.get( + `/api/v1/user/${userId}/pushSubscription/${encodeURIComponent( + endpoint + )}` + ); - return expectedServerKey === currentServerKey && data.endpoint === endpoint; + return data.endpoint === endpoint; + } catch { + // iOS endpoint refresh: browser has new endpoint but backend has old one + return hasBackendSubscriptions; + } } catch (error) { - return false; + return hasBackendSubscriptions; } }; @@ -71,6 +92,18 @@ export const verifyAndResubscribePushSubscription = async ( return true; } + try { + const { data: backendSubscriptions } = await axios.get< + UserPushSubscription[] + >(`/api/v1/user/${userId}/pushSubscriptions`); + + if (backendSubscriptions.length > 0) { + return true; + } + } catch { + // Continue with resubscribe logic + } + if (currentSettings.enablePushRegistration) { try { // Unsubscribe from the backend to clear the existing push subscription (keys and endpoint)