From 033db56565e93ea820b92a2caaa1860678be8276 Mon Sep 17 00:00:00 2001 From: Gustavo Reis Bauer Date: Wed, 29 Jan 2025 19:37:12 -0300 Subject: [PATCH] chore: prune the token whenever we receieve a 403 (#33885) --- .changeset/rude-adults-shout.md | 5 +++++ apps/meteor/app/push/server/fcm.ts | 13 +++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 .changeset/rude-adults-shout.md diff --git a/.changeset/rude-adults-shout.md b/.changeset/rude-adults-shout.md new file mode 100644 index 00000000000..b23410ed805 --- /dev/null +++ b/.changeset/rude-adults-shout.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": minor +--- + +Fixes an issue where tokens generated while using the legacy notification provider would never be removed from the database. diff --git a/apps/meteor/app/push/server/fcm.ts b/apps/meteor/app/push/server/fcm.ts index 6015780f118..ff9e8644db5 100644 --- a/apps/meteor/app/push/server/fcm.ts +++ b/apps/meteor/app/push/server/fcm.ts @@ -54,16 +54,22 @@ type FCMError = { }; }; +// The 403 error code is used when the server is refusing to process a request to a specific token due to +// a SENDER_ID_MISMATCH error. This error is returned when the sender ID provided in the request does not match the sender ID +// associated with the registration token. +const SENDER_ID_MISMATCH_ERROR_CODE = 403; +const NOT_FOUND_ERROR_CODE = 404; + /** * Send a push notification using Firebase Cloud Messaging (FCM). * implements the Firebase Cloud Messaging HTTP v1 API, and all of its retry logic, * see: https://firebase.google.com/docs/reference/fcm/rest/v1/ErrorCode * * Errors: - * - For 400, 401, 403 errors: abort, and do not retry. + * - For 400, 401 errors: abort, and do not retry. * - For 404 errors: remove the token from the database. * - For 429 errors: retry after waiting for the duration set in the retry-after header. If no retry-after header is set, default to 60 seconds. - * - For 500 errors: retry with exponential backoff. + * - For 5xx errors: retry with exponential backoff. */ async function fetchWithRetry(url: string, _removeToken: () => void, options: ExtendedFetchOptions, retries = 0): Promise { const MAX_RETRIES = 5; @@ -80,8 +86,7 @@ async function fetchWithRetry(url: string, _removeToken: () => void, options: Ex const retryAfter = response.headers.get('retry-after'); const retryAfterSeconds = retryAfter ? parseInt(retryAfter, 10) : 60; - - if (response.status === 404) { + if ([SENDER_ID_MISMATCH_ERROR_CODE, NOT_FOUND_ERROR_CODE].includes(response.status)) { _removeToken(); return response; }