Skip to content

fix: resolve rollout plugin iframe auth and org/site resolution - #779

Open
markdaugherty wants to merge 8 commits into
mainfrom
fix-rollout-plugin-iframe-auth
Open

markdaugherty wants to merge 8 commits into
mainfrom
fix-rollout-plugin-iframe-auth

Conversation

@markdaugherty

@markdaugherty markdaugherty commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

The Rollout plugin in DA/EW is currently failing with a Missing IMS Client ID error when attempting a merge on Rollout.

regionalDiff also fails to correctly fetch the site config within an app/plugin due to getPathDetails relying on window.location to parse these values.

Changes implemented here:

  • Add an optional getAccessToken param to daFetch (nx2/utils/api.js): callers can pass a live token getter instead of relying on loadIms()'s origin-dependent getNx() lookup. Threaded through mergeCopy/overwriteCopy/rolloutCopy, regionalDiff → fetchConfig, and source.save/_saveHlx6/_saveDA → isHlx6/getDaApiPath (the hlx6 upgrade-status ping was previously always falling back to loadIms() regardless of the caller's token getter)
  • Rollout plugin (nx + nx2) imports mergeCopy/overwriteCopy via relative path instead of a hardcoded da.live production URL; primes daFetch with a live token read from nx1's daFetch.js
  • regionalDiff accepts explicit org/site instead of always deriving them from location.hash, fixing undefined org/site when mergeCopy/rolloutCopy run outside loc's own app (e.g. the MSM plugin)
  • fetchConfig's cache keyed by org/site instead of a single flat value, with a guard against caching when org/site are missing
  • Added test coverage for getAccessToken's propagation (including through regionalDiff/fetchConfig and isHlx6's upgrade-status ping) and regionalDiff's org/site resolution

Mark Daugherty and others added 2 commits September 24, 2026 12:15
- Add setAccessToken to nx2/utils/api.js so daFetch can use a live
  token getter instead of loadIms()'s origin-dependent getNx() lookup
- Rollout plugin (nx and nx2) now imports mergeCopy/overwriteCopy via
  relative path instead of a hardcoded da.live production URL, and
  primes daFetch with a live token read from nx1's daFetch.js
  (kept current by DA_SDK's ongoing postMessage refresh)
- regionalDiff now accepts explicit org/site instead of always
  deriving them from location.hash, fixing undefined org/site when
  mergeCopy/rolloutCopy run outside loc's own app (e.g. MSM plugin)
- Add test coverage for setAccessToken's override/live-getter behavior
  and regionalDiff's explicit org/site path

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CONFIG_CACHE was a single flat value, so a second call for a
different org/site within one page's lifetime silently reused the
first site's cached translate config. Now relevant since mergeCopy/
rolloutCopy derive org/site per-call rather than once per page.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@aem-code-sync

aem-code-sync Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Hello, I'm the AEM Code Sync Bot and I will run some actions to deploy your branch.
In case there are problems, just click the checkbox below to rerun the respective action.

  • Re-sync branch
Commits

Comment thread nx2/utils/api.js Outdated
Comment on lines +601 to +611
// Lets an iframe-hosted caller (e.g. a DA_SDK plugin) hand daFetch a live
// token instead of falling through to loadIms(), whose dynamic getNx()
// lookup resolves against window.location.origin and can diverge
// from the token the plugin's host frame actually issued.
let overrideAccessToken;
export function setAccessToken(getAccessToken) {
overrideAccessToken = getAccessToken;
}

export const daFetch = async ({ url, opts = { method: 'GET' }, redirect = false }) => {
const { accessToken } = await loadIms();
const accessToken = (await overrideAccessToken?.()) || (await loadIms()).accessToken;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the iframe auth fix makes sense, but I’m a little nervous about introducing a module-global token override here. My concern isn’t that this literally overwrites the user’s IMS session, but that it creates shared mutable auth state in api.js. Today that’s probably okay because this plugin runs in its own iframe/module realm, but it feels brittle if this module is ever reused by multiple callers in one page context.

Would it be possible to make the token source explicit in a backward-compatible way by adding an optional getAccessToken field to daFetch({ ... }) instead?

  daFetch({ url, opts, redirect, getAccessToken })

with something like:

  const accessToken = (await getAccessToken?.()) || (await loadIms()).accessToken;

That keeps existing callers working unchanged (they still fall back to loadIms()), while iframe/plugin callers can inject their own token getter without introducing sticky global auth state. It also makes the auth dependency more local and easier to reason about in tests.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the recommendation. This makes sense to me as a more elegant solution, I'll work on refactoring the changes here.

// loc's own app (e.g. mergeCopy invoked from another app's plugin) can
// call this for different sites within one page's lifetime, and a flat
// cache would silently serve the first site's config to every other one.
const cacheKey = `${org}/${site}`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  const cacheKey = `${org}/${site}`;

If this is ever called with missing values, it’ll cache under "undefined/undefined". That’s probably harmless and not a regression, but it’s a little magic-string-y.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — added an early guard so fetchConfig returns the same "Options not available" error for missing org/site without ever writing to the cache, instead of caching under an undefined/undefined key. See 6e4fa2d.

Addresses review feedback: avoid caching under an 'undefined/undefined'
magic-string key when org or site is missing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mark Daugherty and others added 2 commits September 28, 2026 08:33
Removes the module-global overrideAccessToken/setAccessToken mutable
state from daFetch in favor of an optional getAccessToken callback
passed per-call. Threads getAccessToken through loc project save/copy
flows and both rollout plugins, which now resolve their own token via
initIms() instead of mutating shared auth state.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…DaApiPath

mergeCopy/rolloutCopy pass getAccessToken to regionalDiff, which now
forwards it to fetchConfig's daFetch call instead of always falling
back to loadIms().

source.save (used by saveHtml) resolves its URL via getDaApiPath,
which calls isHlx6's internal upgrade-status ping. That ping ignored
getAccessToken and always fell through to loadIms(), risking an
unwanted sign-in prompt in contexts holding only a getAccessToken
callback. isHlx6 and getDaApiPath now accept and forward it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

This branch was successfully deployed

1 active deployment
fix-rollout-plugin-iframe-auth — c46384ec Deployed Sep 28, 2026 by aem-code-sync[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants