From c6a38e2fc61a05af85cc966fd35fcbcd12883295 Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Fri, 12 Jun 2026 09:39:26 +0400 Subject: [PATCH] fix: Keep Instagram scopes out of new Messenger OAuth flows (#14695) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes Instagram permissions from the Facebook Messenger inbox setup flow to avoid blocking Meta App Review for Messenger-only apps. Meta rejects or stalls Messenger-only app reviews when the OAuth flow requests unrelated Instagram permissions such as `instagram_basic` and `instagram_manage_messages`. This blocks approval for Messenger permissions like `human_agent`, even when the user only wants to configure a Facebook Messenger inbox. New Facebook Messenger inbox setup now requests only the Page and Messenger permissions required for Messenger. Existing Facebook Messenger inboxes that already have Instagram details continue to request Instagram permissions during reauthorization, preserving support for the legacy combined Facebook/Instagram inbox flow. Going forward, new Instagram setups should use the dedicated Instagram channel inbox instead of being bundled into the Messenger setup flow. Closes #13860 ## How to test 1. Go to Settings → Inboxes → Add Inbox → Facebook Messenger. 2. Click Login with Facebook. 3. Verify the OAuth scope does not include `instagram_basic` or `instagram_manage_messages`. 4. Reauthorize an existing Facebook Messenger inbox with `instagram_id` present. 5. Verify the reauth scope still includes `instagram_basic` and `instagram_manage_messages`. --------- Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com> --- .../spec/useFacebookPageConnect.spec.js | 3 ++- .../composables/useFacebookPageConnect.js | 8 ++----- .../dashboard/helper/facebookScopes.js | 22 +++++++++++++++++++ .../settings/inbox/facebook/Reauthorize.vue | 9 ++++++-- 4 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 app/javascript/dashboard/helper/facebookScopes.js diff --git a/app/javascript/dashboard/composables/spec/useFacebookPageConnect.spec.js b/app/javascript/dashboard/composables/spec/useFacebookPageConnect.spec.js index 5d9edb993..4ec17e753 100644 --- a/app/javascript/dashboard/composables/spec/useFacebookPageConnect.spec.js +++ b/app/javascript/dashboard/composables/spec/useFacebookPageConnect.spec.js @@ -70,7 +70,8 @@ describe('useFacebookPageConnect', () => { ACCOUNT_ID ); expect(window.FB.login).toHaveBeenCalledWith(expect.any(Function), { - scope: expect.stringContaining('pages_show_list'), + scope: + 'pages_manage_metadata,business_management,pages_messaging,pages_show_list,pages_read_engagement', }); }); diff --git a/app/javascript/dashboard/composables/useFacebookPageConnect.js b/app/javascript/dashboard/composables/useFacebookPageConnect.js index 46a177d58..dbe06dd0d 100644 --- a/app/javascript/dashboard/composables/useFacebookPageConnect.js +++ b/app/javascript/dashboard/composables/useFacebookPageConnect.js @@ -1,13 +1,9 @@ import { ref } from 'vue'; import { useMapGetter } from 'dashboard/composables/store'; import ChannelApi from 'dashboard/api/channels'; +import { buildFacebookLoginScopes } from 'dashboard/helper/facebookScopes'; import { setupFacebookSdk } from 'dashboard/routes/dashboard/settings/inbox/channels/whatsapp/utils'; -// Page-management + messaging scopes required to list pages and create a -// Channel::FacebookPage inbox (mirrors the standalone settings flow). -const FB_PAGE_SCOPES = - 'pages_manage_metadata,business_management,pages_messaging,instagram_basic,pages_show_list,pages_read_engagement,instagram_manage_messages'; - // Headless half of the Facebook Page connect flow: load the Meta SDK, run // FB.login for page scopes, and fetch the user's pages. The caller owns the // page-picker UI and the channel creation, because choosing a page is an @@ -51,7 +47,7 @@ export function useFacebookPageConnect() { : null ); }, - { scope: FB_PAGE_SCOPES } + { scope: buildFacebookLoginScopes() } ); }); diff --git a/app/javascript/dashboard/helper/facebookScopes.js b/app/javascript/dashboard/helper/facebookScopes.js new file mode 100644 index 000000000..755b3f465 --- /dev/null +++ b/app/javascript/dashboard/helper/facebookScopes.js @@ -0,0 +1,22 @@ +export const FACEBOOK_PAGE_SCOPES = [ + 'pages_manage_metadata', + 'business_management', + 'pages_messaging', + 'pages_show_list', + 'pages_read_engagement', +]; + +export const INSTAGRAM_SCOPES = [ + 'instagram_basic', + 'instagram_manage_messages', +]; + +export const buildFacebookLoginScopes = ({ + includeInstagramScopes = false, +} = {}) => { + const scopes = [...FACEBOOK_PAGE_SCOPES]; + if (includeInstagramScopes) { + scopes.push(...INSTAGRAM_SCOPES); + } + return scopes.join(','); +}; diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/facebook/Reauthorize.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/facebook/Reauthorize.vue index dd566f131..cf25177ea 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/facebook/Reauthorize.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/facebook/Reauthorize.vue @@ -4,6 +4,7 @@ import InboxReconnectionRequired from '../components/InboxReconnectionRequired.v import { useAlert } from 'dashboard/composables'; import { loadScript } from 'dashboard/helper/DOMHelpers'; +import { buildFacebookLoginScopes } from 'dashboard/helper/facebookScopes'; import * as Sentry from '@sentry/vue'; export default { @@ -20,6 +21,11 @@ export default { inboxId() { return this.inbox.id; }, + facebookLoginScopes() { + return buildFacebookLoginScopes({ + includeInstagramScopes: !!this.inbox.instagram_id, + }); + }, }, mounted() { window.fbAsyncInit = this.runFBInit; @@ -77,8 +83,7 @@ export default { } }, { - scope: - 'pages_manage_metadata,business_management,pages_messaging,instagram_basic,pages_show_list,pages_read_engagement,instagram_manage_messages', + scope: this.facebookLoginScopes, auth_type: 'reauthorize', } );