Show a success screen when the OAuth redirect targets a native app#3107
Conversation
When an OAuth2 client redirects to a custom protocol (e.g. cursor://), the browser hands off to the OS and the tab is left hanging with no feedback. Detect non-web redirect URIs after approve/reject and render an outcome screen instead. The shared outcome card completes the consent card's identity row (dashed pending connector resolves to a check when approved, X when cancelled) and offers an Open-app button to retry the deep link. The device flow's approved/denied screens now reuse the same card.
Greptile SummaryThis PR adds a terminal outcome screen for OAuth2 consent flows that target native apps (custom protocol redirect URIs such as
Confidence Score: 5/5The change is well-scoped to the OAuth2 public routes and introduces no new API surface or auth logic; the native-redirect detection path is straightforward and existing web-redirect behaviour is unchanged. All async boundaries carry proper cancellation guards, the shared No files require special attention. Important Files Changed
Reviews (2): Last reviewed commit: "(fix): address review comments on OAuth ..." | Re-trigger Greptile |
Guard the already-consented fast path against a cancelled effect, hide the account avatar and move the status onto the app avatar when no account label is known, and extract the duplicated isWebRedirect helper to $lib/helpers/oauth2-redirect.
What does this PR do?
When an OAuth2 client's redirect URI uses a custom protocol (e.g.
cursor://for Cursor), the browser hands the redirect off to the OS and the consent tab is left hanging on the consent card with no feedback. This PR detects non-web (http/https) redirect URIs after approve/reject and renders an outcome screen instead.approve()/reject()in the consent card now report completion via a unifiedonDone(outcome, redirectUrl)callback when the redirect is a native deep link (or when there is no redirect), instead of the device-onlyonDeviceDone.outcome-card.svelterenders the terminal state for both the authorization and device flows. It completes the consent card's identity row: the dashed "pending" connector between the app and account avatars resolves to a solid line with a check node when approved, and stays dashed with a neutral X when cancelled.authorizereturns aredirectUrlimmediately) shows the same screen for native redirects.Screenshots
Access granted (desktop / mobile)
Request cancelled (desktop / mobile)
Test plan
bun run check,bun run lint,bun run test:unit(235 passed),bun run buildall pass.Related PRs and Issues