Skip to content

fix: handle COOP policy blocking OAuth popup window.close()#107

Closed
glebedel wants to merge 1 commit intoStackOneHQ:mainfrom
glebedel:fix/coop-popup-close
Closed

fix: handle COOP policy blocking OAuth popup window.close()#107
glebedel wants to merge 1 commit intoStackOneHQ:mainfrom
glebedel:fix/coop-popup-close

Conversation

@glebedel
Copy link
Copy Markdown
Contributor

@glebedel glebedel commented Mar 5, 2026

Problem

When the Hub is embedded in a third-party app (e.g. pa-agent.stackone.space), the host app may set app-url to its own domain. The OAuth callback URL becomes <host-app-origin>/embedded/accounts/callback — a page that doesn't exist, so the OAuth popup has nowhere to land.

Even if the host app omits app-url (using the default https://app.stackone.com), the processMessageCallback origin check was too strict:

if (event.origin !== window.location.origin) {
    return; // blocks messages from app.stackone.com!
}

When the popup lands on app.stackone.com/embedded/accounts/callback and sends a postMessage back to the opener, the message origin is app.stackone.com. Since window.location.origin is the host app's domain (e.g. pa-agent.stackone.space), this check rejects every message — the OAuth flow never completes.

The previous fix (try-catch around popup.close()) only hid the symptom (COOP blocking close()). The root cause is that the message was never received in the first place.

Fix

Expand the origin allowlist to include both:

  • window.location.origin — existing same-origin embedding behavior
  • new URL(dashboardUrl).origin — the OAuth callback origin when Hub uses its default app.stackone.com

Invalid dashboardUrl values are caught and skipped so the fix is backwards-compatible.

How to test

Embed <StackOneHub> (or <stackone-hub>) in an app on a different domain (e.g. localhost:3000 or a staging domain). Without app-url override, click Connect on a GitHub integration → OAuth popup opens → complete OAuth → popup closes and Hub shows success state.

When the OAuth redirect page (e.g. app.stackone.com/embedded/accounts/callback)
sets Cross-Origin-Opener-Policy: same-origin, the opener page loses the ability
to call .close() on the popup window reference. This caused a browser error:

  'Cross-Origin-Opener-Policy policy would block the window.close call.'

The Hub's state was already updated correctly before the close() attempt, so
wrapping the call in try/catch is sufficient: the popup will close itself via
window.close() on the callback page, or the user can close it manually.

Fixes both processMessageCallback and handleOAuthResultFromAnyChannel.
Copilot AI review requested due to automatic review settings March 5, 2026 18:56
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@glebedel
Copy link
Copy Markdown
Contributor Author

glebedel commented Mar 5, 2026

Closing — the same fix was already shipped in 0.12.9 via #103 (useMemo-based allowedOrigins). The only change needed in pa-agent was removing the app-url override, which has been done separately.

@glebedel glebedel closed this Mar 5, 2026
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