Page MenuHomePhabricator

Possible solution for broken iOS notifications
ClosedPublic

Authored by marcin on Jul 26 2023, 7:27 AM.
Tags
None
Referenced Files
Unknown Object (File)
Sat, Nov 23, 4:25 PM
Unknown Object (File)
Sat, Nov 23, 9:52 AM
Unknown Object (File)
Sat, Nov 23, 9:52 AM
Unknown Object (File)
Sat, Nov 23, 9:52 AM
Unknown Object (File)
Sat, Nov 23, 9:52 AM
Unknown Object (File)
Fri, Nov 22, 6:59 PM
Unknown Object (File)
Thu, Nov 14, 9:26 PM
Unknown Object (File)
Thu, Nov 14, 8:40 PM
Subscribers
None

Details

Summary
IMPORTANT: This differential is for test release purposes.

The context for this change is described here: https://linear.app/comm/issue/ENG-4453#comment-4d1770b3. We introduce dummy body to the encrypted notification to make sure we comply to apple docs. Additionally we make necessary changes to
NotificationService extension to prevent from displaying notification that contains ENCRYPTED text.

Test Plan

Build release iOS app. Ensure that notifications, rescinds and bade-only notifications work correctly

Diff Detail

Repository
rCOMM Comm
Branch
marcin/eng-4453
Lint
No Lint Coverage
Unit
No Test Coverage

Event Timeline

Create mutable content directly

native/ios/NotificationService/NotificationService.mm
167 ↗(On Diff #29058)

In current setup badge-only notifications and only badge-only notifications carry threadID property so this check is semantically correct. IF the solution proposed in this diff appears to solve the issue we will introduce badgeOnly field to iOS notifications along with other refactors.

native/ios/NotificationService/NotificationService.mm
63 ↗(On Diff #29064)

Signal also seems to create notification content from scratch so it is probably safe: https://github.com/signalapp/Signal-iOS/blob/main/SignalNSE/NSEEnvironment.swift#L164

keyserver/src/push/crypto.js
69 ↗(On Diff #29064)

In general, I think we should opt for >= here. That way, the releaser can simply replace NEXT_CODE_VERSION with the version they are releasing

keyserver/flow-typed/npm/@parse/node-apn_vx.x.x.js
41 ↗(On Diff #29064)
  1. Nit: spacing
  2. I think this type is strange. Is it important that we overload aps.alert for this, or is it possible to have a different key for this?
keyserver/src/push/crypto.js
72 ↗(On Diff #29064)
  1. Do we ever set encryptedNotification.aps before this line?
  2. Is your theory here that it's important to set the aps key, otherwise the notif might not go through? If so, how come some of the other notifs go through?

(Resigning since encrypted notifications are a blindspot for me, feel free to re-add if there's something specific I can be useful for)

ashoat requested changes to this revision.Jul 26 2023, 12:30 PM

Passing back to @marcin with some requests

This revision now requires changes to proceed.Jul 26 2023, 12:30 PM
keyserver/flow-typed/npm/@parse/node-apn_vx.x.x.js
41 ↗(On Diff #29064)

My theory, as described and discussed in https://linear.app/comm/issue/ENG-4453/notifs-are-broken-in-production#comment-eaa12167, is that encrypted notifs don't trigger NSE since they have pushType: alert and mutable-content: 1 but don't have the alert field. According to apple docs alert field can be either string or a dict, that can contain may different keys. So logically to test my theory we don't have to modify this type and just put some string under alert field. However I came across this doc: https://developer.apple.com/documentation/usernotifications/modifying_content_in_newly_delivered_notifications?language=objc, where Apple considers the case of encrypted notification handled in NSE. In their example they configure notification payload to have a dict in alert field with body set to string. Therefore I intuitively decided to match apple tutorial as close as possible. To do this I had to modify this type.

it possible to have a different key for this

When alert is a dict it can have a lot of different keys. I didn't add them all since this diff is just to make a test release. If it proves to work I will refactor this type to cover all keys that alert field can accept.

However if you think we should do this now, then please re-request changes and I will add those keys to this type.

keyserver/src/push/crypto.js
72 ↗(On Diff #29064)

aps is always set for apn.Notification. Most of setter methods of this class put data in aps under the hood.
https://github.com/node-apn/node-apn/blob/master/lib/notification/apsProperties.js

Please address these comments before landing. They are repeats from my previous review

keyserver/flow-typed/npm/@parse/node-apn_vx.x.x.js
41
keyserver/src/push/crypto.js
69

>=

This revision is now accepted and ready to land.Jul 27 2023, 7:58 AM

Address comments and rebase before patching to release

ashoat requested changes to this revision.Aug 15 2023, 8:47 AM
ashoat added inline comments.
keyserver/src/push/crypto.js
69 ↗(On Diff #29542)

This can't be landed on master, since we only want these changes to apply to staff releases. You'll likely need a % 2 check here

This revision now requires changes to proceed.Aug 15 2023, 8:47 AM

Introduce staff release check

ashoat added inline comments.
native/ios/NotificationService/NotificationService.mm
62–68 ↗(On Diff #29943)

Just confirming – this change is safe to land for public-facing production builds, right?

This revision is now accepted and ready to land.Aug 16 2023, 12:31 PM
native/ios/NotificationService/NotificationService.mm
62–68 ↗(On Diff #29943)

Yes - this change is safe for public releases however hiding it behind isStaffRelease check would result in the same behaviour.

After landing this stack staff users will receive encrypted badgeonly notifications with ENCRYPTED alert body. Therefore we must create new notification content without body but with badge count. Public users will be still receiving badgeonly notifications without any body so it would be sage not to enter this code and call contentHandler directly on what has arrived with didReceive.. callback.