I’m building a Forge app (Confluence Cloud, UI Kit) that audits spaces and helps
admins clean up empty ones. Two of its features have no public API, and I want to
check whether the workaround I’ve built is acceptable for a Marketplace listing
before I invest in the listing itself.
None of these are reachable with OAuth scopes; they authenticate with a browser
session.
What I’ve implemented
The admin pastes their own tenant.session.token, and the app calls those endpoints
server-side. Specifically:
- Stored with Forge’s encrypted secret storage (
storage.setSecret), keyed by the
saving user’saccountIdtaken fromreq.context— never from a payload, so no
caller can read another user’s. - Never returned to the browser. Written once, read only by the backend resolver.
- Configurable TTL (default 12h), deleted automatically on expiry and immediately
when Confluence rejects the session. - Egress declared as
external.fetch.backend: ['*.atlassian.net'], with a runtime
check that the target really is anhttps://*.atlassian.netorigin before the
cookie is attached, and redirects followed manually so a response can’t replay it
to another host. - Both features are opt-in toggles, off by default.
My questions
- Would an app that asks an admin to supply their own session cookie, handled as
above, pass Marketplace security review? I’ve read the
App approval guidelines
and the Security guidelines —
neither addresses user-supplied session credentials directly, so I’d rather ask
than assume. - Separately from the credential question: does calling undocumented
.action
endpoints or internal GraphQL disqualify an app from listing, even where no
public alternative exists? - If the answer to either is no, is there a supported route to this functionality
that I’ve missed?
I’m intentionally asking before investing further in these features because I don’t want to build something that can’t ultimately be listed. If the recommended guidance is that Marketplace apps should not rely on browser session credentials or undocumented endpoints, I’m happy to exclude these features from the listed version and only ship functionality backed by supported APIs. My goal is to understand whether there’s a supported approach I’ve overlooked.