fix(instagram,facebook): prevent broken page-grant channels and guide reconnection#1679
fix(instagram,facebook): prevent broken page-grant channels and guide reconnection#1679giladresisi wants to merge 2 commits into
Conversation
… reconnection
Selecting a Facebook page the app was never granted stored a broken
token ("undefined___..." for Instagram), and every publish then failed
with Graph code 190 dressed up as a misleading "missing permissions"
error, with no reconnect prompt and no way out. This was easy to hit:
the picker also offered pages discovered via the Business Manager API
that were never granted in the OAuth dialog, and Facebook's granular
consent lets users grant an Instagram account without its linked page.
Reproduction: connect an Instagram (Facebook Business) channel and
grant a Facebook page that is not the one linked to the Instagram
account. The account could still be selected in Postiz, the channel
connected, and every post then failed with the permissions error.
- pages(): verify every candidate page with the same page-node
access_token call used when the selection is saved, and only offer
pages the app can actually publish through (the Business-Manager page
list can report tokens the page node refuses, so the node call is the
only reliable check); Facebook filters on its edge tokens, which its
own save path uses
- handleErrors(): classify Graph code 190 as refresh-token, so a post
from an already-broken channel marks it refreshNeeded and emails the
user; subsequent posts keep failing with a reconnect email until fixed
- reword the refresh-error email: no posts can be published until the
channel is reconnected; re-adding the same account replaces the broken
connection and keeps scheduled posts (no deletion needed)
- updateIntegration(): clear refreshNeeded when a channel is re-added
over an existing one, so re-adding fully heals a flagged channel
- generateAuthUrl(): auth_type=rerequest so declined permissions/assets
are re-prompted on reconnect and a bad grant can be repaired
- frontend: "Before you continue" guidance popup on the Add Channel,
reconnect and half-connected paths for Instagram/Facebook (select the
page the Instagram account is connected to; use Facebook's "Edit
settings" to change a previous selection); half-connected IG/FB
channels restart the OAuth flow instead of opening the in-app picker;
"Back to Postiz" button on the full-page empty selection state;
connect errors surfaced in the page-selection modal; new i18n keys
translated across all locales
Validated end to end: with the wrong page granted, the Instagram
account is no longer offered (empty selection + Back to Postiz);
posting from a previously-broken channel triggers the refresh-needed
flow (email, channel badge, Reconnect channel menu); reconnecting
through the guidance popup and the Facebook screens with the correct
page heals the channel in place with all scheduled posts intact.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Contribution-checker quality warning Heuristics that flagged:
If this is a genuine contribution, please add detail to your PR description and tighten the diff scope before reviewers look at it. |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
| const { access_token } = await ( | ||
| await fetch( | ||
| `https://graph.facebook.com/v20.0/${p.instagram_business_account.id}?fields=name,profile_picture_url&access_token=${accessToken}` | ||
| `https://graph.facebook.com/v20.0/${p.id}?fields=access_token&access_token=${accessToken}` | ||
| ) | ||
| ).json()), | ||
| id: p.instagram_business_account.id, | ||
| }; | ||
| }) | ||
| ); | ||
| ).json(); | ||
|
|
||
| if (!access_token) { | ||
| return null; | ||
| } |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
…Meta channels Facebook page grants are per Meta app and per user, not per channel: re-authorizing any Instagram/Facebook channel with a narrowed page selection revokes the unchecked pages' grants and invalidates their page tokens — silently breaking every other Postiz channel that uses them (verified experimentally in both directions: granting only the Instagram-linked page broke the Facebook page channel with an unmapped code-190 "Unknown Error", and granting only the Facebook page broke the Instagram channel with the code-190 permissions error; re-granting both pages fixed both channels). Add a line to the "Before you continue" guidance popup telling users their page selection applies to all their Facebook/Instagram channels and that unchecking pages used by other channels will break them. Translated across all locales. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Contribution-checker quality warning Heuristics that flagged:
If this is a genuine contribution, please add detail to your PR description and tighten the diff scope before reviewers look at it. |
Problem
Connecting an Instagram (Facebook Business) or Facebook Page channel while granting the wrong Facebook page silently stores a broken token —
undefined___<user-token>for Instagram — and every publish then fails with Graph code 190 disguised as a misleading "missing permissions" error. There is no reconnect prompt and no way out short of support.This is easy to hit for two reasons:
Reproduction
Connect an Instagram (Facebook Business) channel and, in the Facebook dialog, grant a page that is not the one linked to the Instagram account. Postiz still offered the IG account in the picker; selecting it connected a channel whose token is
undefined___…; every post then failed with "The account is missing some permissions…" — with no indication the channel needed reconnecting.Fix
Prevention (silent, no new UI in the picker):
pages()(Instagram) now verifies every candidate page with the same page-nodeaccess_tokencall the save path uses, and only offers pages the app can actually publish through. (The Business-Manager edge can report a token the page node refuses, so the node call is the only check that keeps the picker and the save consistent.) The Facebook provider filters on its edge tokens, which its own save path reads.auth_type=rerequeston the OAuth URL, so declined permissions/assets are re-prompted and a bad grant can actually be repaired on reconnect.Recovery for already-broken channels:
refresh-token: the next post from a broken channel marks itrefreshNeededand emails the user; subsequent posts keep failing with a reconnect email until fixed.updateIntegration()clearsrefreshNeededwhen a channel is re-added over an existing one, so "Add Channel with the same account" fully heals a flagged channel.Guidance UI (Instagram/Facebook only):
Shared-grant hazard (second commit)
Facebook page grants are per Meta app and per user, not per channel: re-authorizing any Instagram/Facebook channel with a narrowed page selection revokes the unchecked pages' grants and invalidates their page tokens — silently breaking every other Postiz channel that depends on them. Verified experimentally in both directions:
The code-190 → refresh-token classification in this PR already routes such casualties into the reconnect flow at their next post. The second commit additionally adds a line to the "Before you continue" popup warning users that their page selection applies to all their Meta channels and that unchecking pages used by other channels will break them (translated across all locales).
Post-fix validation (manual, real Facebook/Instagram accounts)
refreshNeededclears, and all scheduled posts survive.🤖 Generated with Claude Code