"Lost" push subscriptions for iOS PWA

digitalpoint

Well-known member
Affected version
2.2.13
Has anyone noticed push subscriptions going away for the PWA app? Noticed it happening not just for my own, but also here at XenForo. At the operating system level, push was still enabled (you can reenable it by going to account preferences and hitting the Enable push notifications button and it does it [doesn't require the permission dialog]).

Digging a little in my databases, the push subscriptions at https://web.push.apple.com went missing in the xf_user_push_subscription table. If it was just my site, I'd say it was something on my end... but like I said, it also happened for the PWA app I have installed for this site.

Has anyone else lost push notifications for the PWA for xenforo.com?
 
Last edited:
Interesting, I had a user mention they weren't getting alerts but I assumed it was their error. I'll check my database later (on a Netflix binge right now 🤓)
 
Doing a little more digging, maybe XenForo devs noticed something similar because XF 2.2.13 added some logic to not delete the push subscription record when it was an HTTP 4xx response (at least not immediately, will wait until it happens 5x), however the logic is never used because XF\Service\PushNotification::DELETE_ON_ERROR is always true? Can we change that to false so the new logic is actually used?
 
Last edited:
Yup, checked the db now and you're right - the push subscription entries are gone.

In fact, checking my current db and the backup, the Apple ones have a difference of a few hundred :(
 
Yup, checked the db now and you're right - the push subscription entries are gone.

In fact, checking my current db and the backup, the Apple ones have a difference of a few hundred :(
Ya, there's something going on where the Apple push subscriptions are being dropped by XenForo. From the looking at the XenForo source, it appears the subscriptions are dropped if the response code from attempting to send the push is 401, 403, 404 or 410.

The various reasons Apple's APN would return those codes are here:


I've actually made an addition to my PWA add-on that I'm using on my sites now that makes it so it will not delete the subscription immediately, and also log to the XenForo server error log the underlying reason that it would have deleted the subscription. Just waiting now for an error to pop up...
 
Doing a little more digging, maybe XenForo devs noticed something similar because XF 2.2.13 added some logic to not delete the push subscription record when it was an HTTP 4xx response
Yes I was aware of it and had some debug code running here prior to 2.2.12.

The default behaviour was returned because it wasn’t actually 4xx errors causing the deletion.

Subscriptions were going missing despite logging no errors.

So to avoid any potentially undesirable behaviour changes, and to aid in further debugging in the future, I maintained the original behaviour.

Wasn’t ever designed to be extended hence the use of self.

But ultimately whatever deletes them, doesn’t seem to be here.

I haven’t had a chance to look into it this release cycle as I’ve been working on some 2.3 stuff.
 
So this is not limited to iOS (or PWA). I was just working on some push stuff and I noticed my user account only had a single push subscription in the table (this time it was Chrome, not the PWA that lost it's subscription). So I enabled push and the table showed 2 push subscriptions as expected.

I received the "Thank you for enabling push notifications" message successfully. No other push notifications were attempted to be sent (I'm also logging any errors when attempting to send a push and there were no errors when sending that "thank you" push).

Less than 2 minutes later, the Chrome user push subscription record was lost again.

I went and looked at my server logs and there was an push unsubscribe request made from admin.php:

Code:
1.2.3.4 - - [13/Aug/2023:13:28:22 -0700] "POST /index.php?misc/update-push-subscription HTTP/2.0" 200 190 "https://iolabs.io/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
1.2.3.4 - - [13/Aug/2023:13:28:42 -0700] "POST /index.php?misc/update-push-subscription HTTP/2.0" 200 189 "https://iolabs.io/account/preferences" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
1.2.3.4 - - [13/Aug/2023:13:28:44 -0700] "POST /index.php?misc/update-push-subscription HTTP/2.0" 200 190 "https://iolabs.io/account/preferences" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
1.2.3.4 - - [13/Aug/2023:13:29:00 -0700] "POST /index.php?misc/update-push-subscription HTTP/2.0" 200 189 "https://iolabs.io/admin.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
1.2.3.4 - - [13/Aug/2023:13:30:56 -0700] "POST /index.php?misc/update-push-subscription HTTP/2.0" 200 190 "https://iolabs.io/account/preferences" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"

The first two requests to account/preferences was because I noticed the user push subscription record was missing in Chrome and I hit the disable push button and then enable push button. Less than 90 seconds later a request originated from admin.php unsubscribed. Then the last request to account/preferences was me subscribing again.

I haven't gone digging into the core.js JavaScript, but I'm pretty certain it's something in that which is causing the lost subscription records (I had logging within the Service/PushNotitication.php class and I haven't seen it ever get triggered... it would get triggered if the push server kicked back an error that would cause it to unsubscribe).
 
I can (sort of) replicate it. I don't think this is 100% the issue because I've seen normal user's push subscriptions go missing, but if you try to go into the admin area (where you are prompted for a login/password), you lose your push subscription because we are subscribed to push (XF.Push.isSubscribed) but we don't have a user_id (XF.config.userId) because we are in a different app. So the logic kicks in to automatically unsubscribe the user if they logged out.

Probably makes sense to only fire that unsubscribe request if the user is in data-app="public". I know that it will attempt to automatically resubscribe when the user logs back in/returns to a public page. But makes me think that mechanism might be causing the lost subscriptions. Maybe an issue with the logic of XF.Push.isExpectedServerKey()? 🤷🏻‍♂️
 
Also just ran into a situation where iOS PWA stopped receiving push notifications, but the user push subscription record was still there. Going into preferences to enable push added a second user push subscription for that device/app and it started working again. No error when sending to the first endpoint, but nothing comes through and the device/app doesn't think it's subscribed.

PWA subscription management is WHACK.
 
Probably makes sense for XenForo's service worker to handle the pushsubscriptionchange event. It's not supported in most browsers yet, but it's part of the Push API spec:


If the user agent has to change the keys for any reason, it MUST fire the "pushsubscriptionchange" event with the service worker registration associated with the push subscription as registration, a PushSubscription instance representing the push subscription having the old keys as oldSubscription and a PushSubscription instance representing the push subscription having the new keys as newSubscription.

Chromium is (slowly) working on implementing it (Chrome's push subscriptions endpoints never expire, so that's probably why they aren't quick to implement it):

...but maybe other providers (like Apple) are expiring them? Not sure if Safari is firing the event, but it's part of the spec, so it wouldn't hurt to handle it.

XenForo will attempt to resubscribe/update subscription if the push_subscription_updated cookie isn't set. The problem is the cookie is a session cookie, so it could in theory never be unset if you don't quit the app/browser. Probably makes more sense to have the push_subscription_updated cookie be set with a specific expiration (maybe 24 hours or something?). Unless a user proactively quits the app and reloads it, a missing push subscription may never get re-subscribed since the session cookie persists until it's quit.

If you are going to use a session cookie for it, wouldn't it make more sense for push_subscription_updated to be sessionStorage instead of a cookie? It's not used on the server-side (in PHP), so no point in sending it with every request.
 
Last edited:
I need to re-enable push notifications almost every day or two on Safari for desktop and mobile PWA app (iPhone).

It is annoying as hell. There is no notification that your push notifications are disabled. I go to Preferences and there I can re-enable them again. I really can't rely on this.

Changing your forum account email address to Pushover email is almost better and you get notifications there. I don't use it like that, but one of my moderators does and he never complained.
 
I'm noticing same thing on Android PWA for what it's worth.
Ya, finding all sorts of places where they can be "lost" that isn't necessarily exclusive to iOS.

Enter the admin area and the subscription is deleted:

A cookie is used to "restore" lost subscriptions, but that cookie is a session cookie meaning it might not be restored until you fully quit the browser:
 
I’ve never had to reinstall. That seems to be a common thing people say needs to be done to get it working.

You should just be able to enable push notifications again in your preferences.
 
Top Bottom