fix(chrome-ext): keep embed params through side-panel SSO login - #430
Merged
Conversation
The side panel authenticates the storage-partitioned mentor iframe by
routing it through /sso-login-complete, which installs the session into
the iframe's (empty) partitioned storage and then redirects to the chat.
Two bugs dropped the embed params (embed / mode / component /
extra-body-classes) on that final hop, so the iframe landed on a bare
/platform/{tenant}/{mentorId} with the full app chrome instead of the
intended embedded chat view:
- panel.js passed the target as ?redirect-to=, but SsoLogin reads the
incoming redirect from searchParams.get('redirect-path'). The param was
silently ignored and the login fell through to defaultRedirectPath '/',
losing the query. Pass ?redirect-path= instead.
- sso-login-complete now prefers an explicit ?redirect-path= over any
value SsoLogin resolved from localStorage, so a stale redirect-to left
by a prior failed-auth cycle in the partitioned iframe store can't win
and drop the params.
Also delegates media features to the iframe (allow="microphone; camera;
display-capture; autoplay") and removes the temporary mic diagnostic.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
It is a thin app-router client wrapper around the SDK's <SsoLogin> plus a small inline resolveRedirectPath; consistent with the other app-router page.tsx entries already excluded (exercised via E2E). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… allow policy - sso-login-complete: only honor a same-origin, path-absolute redirect-path (leading single slash, no // or /\ authority) before preferring it over localStorage, since SsoLogin navigates to origin+redirectPath (open-redirect guard). - panel.js: stop overwriting the iframe allow policy — the widget already sets a superset (microphone */camera */display-capture *, plus clipboard/midi/ geolocation/encrypted-media) that the override was silently revoking. - panel.js: bound the iframe-install poll to ~30s so a failed sign-in doesn't leave the interval running for the panel's lifetime. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The side-panel chat lands on /?embed=... then redirects to
/platform/{tenant}/{mentorId}. MentorProvider re-resolves the mentor once
already on that page and calls redirectToMentor again, but the query was only
forwarded when pathname === '/', so the second call dropped embed / mode /
component / extra-body-classes — flipping useEmbedMode() off and rendering the
full app chrome instead of the embedded chat.
Carry just those four embed-context keys from the live URL on every mentor
redirect (redirectToMentor + redirectToNoMentorsPage), regardless of the
current path, so they survive the re-resolve. Only those keys are forwarded, so
tokens and other one-shot params never leak into the mentor URL.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
PR E2E - OKFull report, traces and screenshots
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
In the Chrome side-panel extension, after auth the mentor iframe landed on a bare
/platform/{tenant}/{mentorId}— the embed query params (embed=true,mode=anonymous,component=chat,extra-body-classes=iframed-externally) were dropped, so it rendered the full app chrome instead of the intended embedded chat view.Root cause
panel.jsroutes the storage-partitioned mentor iframe through/sso-login-completeto install the session, passing the desired chat URL. It passed it as?redirect-to=, butSsoLoginreads the incoming redirect fromsearchParams.get('redirect-path')(redirect-toonly names the localStorage fallback key, never the URL). The param was silently ignored, the login fell through todefaultRedirectPath = '/', and the app then redirected/→/platform/{tenant}/{mentorId}with an empty query.Fix
panel.js— pass?redirect-path=(the paramSsoLoginactually reads).app/sso-login-complete/page.tsx— prefer an explicit?redirect-path=over any stalelocalStorage['redirect-to'](a prior failed-auth cycle can populate it in the partitioned iframe store), so it can't override the embed target.Review follow-ups addressed (local
/code-review)redirect-pathis now only honored if it's a same-origin, path-absolute value (leading single slash, no//or/\authority), sinceSsoLoginnavigates toorigin + redirectPath.allowpolicy (MEDIUM) — stopped overwriting the iframe permissions policy; the widget already sets a superset (microphone */camera */display-capture *, plus clipboard/midi/geolocation/encrypted-media).Coverage
app/sso-login-complete/page.tsxadded tocheck-test-coverage.shexclusions — a thin app-router client wrapper around the SDK<SsoLogin>, consistent with the other excluded page wrappers (exercised via E2E; journey coverage maps it to01-authentication/55-free-credits-checkout-onboarding).Known follow-ups (tracked separately, out of scope here)
getUserMedialimitation; needs an extension-origin capture path.isAuthed()ignores token expiry — pre-existing; an expired token can install and stick.panel.htmlstill points at a dev ngrok URL — the extension needs a productionmentorurlbefore it can ship./sso-login-completehost-auth approach into@iblai/agent-ai'sauthrelyonhost.Testing
Local ngrok build. Full pre-push gate (typecheck/lint/build/11,118 unit tests/coverage/E2E-journey/
claudereview) passed green; landed via authorized--no-verifydue to the known post-green-hook network SIGPIPE on this repo.🤖 Generated with Claude Code