diff --git a/keyserver/src/push/crypto.js b/keyserver/src/push/crypto.js --- a/keyserver/src/push/crypto.js +++ b/keyserver/src/push/crypto.js @@ -11,13 +11,18 @@ NotificationTargetDevice, } from './types.js'; import { encryptAndUpdateOlmSession } from '../updaters/olm-session-updater.js'; +import { getOlmUtility } from '../utils/olm-utils.js'; async function encryptIOSNotification( cookieID: string, notification: apn.Notification, codeVersion?: ?number, notificationSizeValidator?: apn.Notification => boolean, -): Promise<{ +notification: apn.Notification, +payloadSizeExceeded: boolean }> { +): Promise<{ + +notification: apn.Notification, + +payloadSizeExceeded: boolean, + +encryptedPayloadHash?: string, +}> { invariant( !notification.collapseId, 'Collapsible notifications encryption currently not implemented', @@ -71,9 +76,11 @@ }; } + const encryptedPayloadHash = getOlmUtility().sha256(serializedPayload.body); return { notification: encryptedNotification, payloadSizeExceeded: !!dbPersistConditionViolated, + encryptedPayloadHash, }; } catch (e) { console.log('Notification encryption failed: ' + e); @@ -217,6 +224,7 @@ +deviceToken: string, +notification: apn.Notification, +payloadSizeExceeded: boolean, + +encryptedPayloadHash?: string, }>, > { const notificationPromises = devices.map( diff --git a/keyserver/src/push/send.js b/keyserver/src/push/send.js --- a/keyserver/src/push/send.js +++ b/keyserver/src/push/send.js @@ -846,9 +846,10 @@ if (devicesWithExcessiveSize.length === 0) { return notifsWithMessageInfos.map( - ({ notification: notif, deviceToken }) => ({ + ({ notification: notif, deviceToken, encryptedPayloadHash }) => ({ notification: notif, deviceToken, + encryptedPayloadHash, }), ); } @@ -861,15 +862,17 @@ const targetedNotifsWithMessageInfos = notifsWithMessageInfos .filter(({ payloadSizeExceeded }) => !payloadSizeExceeded) - .map(({ notification: notif, deviceToken }) => ({ + .map(({ notification: notif, deviceToken, encryptedPayloadHash }) => ({ notification: notif, deviceToken, + encryptedPayloadHash, })); const targetedNotifsWithoutMessageInfos = notifsWithoutMessageInfos.map( - ({ notification: notif, deviceToken }) => ({ + ({ notification: notif, deviceToken, encryptedPayloadHash }) => ({ notification: notif, deviceToken, + encryptedPayloadHash, }), ); @@ -1098,13 +1101,17 @@ }; type APNsDelivery = { - source: $PropertyType, - deviceType: 'ios' | 'macos', - iosID: string, - deviceTokens: $ReadOnlyArray, - codeVersion: number, - stateVersion: number, - errors?: $ReadOnlyArray, + +source: $PropertyType, + +deviceType: 'ios' | 'macos', + +iosID: string, + +deviceTokens: $ReadOnlyArray, + +codeVersion: number, + +stateVersion: number, + +errors?: $ReadOnlyArray, + +encryptedPayloadHashes?: $ReadOnlyArray, + +deviceTokensToPayloadHash?: { + +[deviceToken: string]: string, + }, }; type APNsResult = { info: NotificationInfo, @@ -1131,7 +1138,7 @@ const deviceTokens = targetedNotifications.map( ({ deviceToken }) => deviceToken, ); - const delivery: APNsDelivery = { + let delivery: APNsDelivery = { source, deviceType: platform, iosID, @@ -1140,8 +1147,26 @@ stateVersion, }; if (response.errors) { - delivery.errors = response.errors; + delivery = { + ...delivery, + errors: response.errors, + }; } + + const deviceTokensToPayloadHash = {}; + for (const targetedNotification of targetedNotifications) { + if (targetedNotification.encryptedPayloadHash) { + deviceTokensToPayloadHash[targetedNotification.deviceToken] = + targetedNotification.encryptedPayloadHash; + } + } + if (Object.keys(deviceTokensToPayloadHash).length !== 0) { + delivery = { + ...delivery, + deviceTokensToPayloadHash, + }; + } + const result: APNsResult = { info: notificationInfo, delivery, diff --git a/keyserver/src/push/types.js b/keyserver/src/push/types.js --- a/keyserver/src/push/types.js +++ b/keyserver/src/push/types.js @@ -5,6 +5,7 @@ export type TargetedAPNsNotification = { +notification: apn.Notification, +deviceToken: string, + +encryptedPayloadHash?: string, }; type AndroidNotificationPayloadBase = {