Add preventUniversalLinks prop to sandbox hosts from UL handoff#10
Merged
artemlitch merged 1 commit intomasterfrom May 7, 2026
Merged
Add preventUniversalLinks prop to sandbox hosts from UL handoff#10artemlitch merged 1 commit intomasterfrom
artemlitch merged 1 commit intomasterfrom
Conversation
When iOS triggers a Universal Link handoff mid-flow inside a WebView, the user is yanked into the linked third-party app and the embedded flow breaks. This shows up most commonly in embedded auth: e.g. a Goodreads sign-in WebView whose post-Amazon-SSO redirect lands on a UL-eligible URL like /ap-handler/sign-in?IDP=lwa, sending the user into the installed Goodreads app. iOS does not expose a way to predict UL handoff at the navigation delegate — UL is decided in WebKit's process before decidePolicyForNavigationAction fires. The only nav type iOS reliably does NOT consider for UL handoff is host-app-initiated [webView loadRequest:]. This adds a preventUniversalLinks prop (NSArray<NSString *>) for iOS: when set, top-frame navigations whose host matches an entry are canceled and re-issued via [webView loadRequest:]. Match is domain-suffix with a dot boundary, so passing 'goodreads.com' covers 'goodreads.com', 'www.goodreads.com', and any subdomain — but not 'evilgoodreads.com'. The prop takes a host list rather than a boolean because reissuing every top-frame nav unconditionally breaks anything that's not a plain GET — POST form bodies are stripped by NSURLRequest in the navigation action, and reissuing single-use OAuth codes (Amazon callbacks etc.) double-consumes them. Only hosts that actually have AASA registered for this app's bundle ID are at risk of UL handoff, so the app declares them. An associated-object flag on the WKWebView breaks the cancel/reissue loop: the reissued nav re-enters decidePolicyForNavigationAction with the flag set, the impl clears it and falls through to the normal handler. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> (cherry picked from commit 7fbf264)
1 task
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.
Summary
Adds a
preventUniversalLinksprop (iOS) that lists hosts whose top-frame navigations should be sandboxed from Universal Link handoff. For listed hosts, the navigation is canceled indecidePolicyForNavigationActionand re-issued via[webView loadRequest:]— the only nav type iOS reliably does not consider for UL handoff.Why
When iOS triggers a Universal Link handoff mid-flow inside a WebView, the user is yanked into the linked third-party app and the embedded flow breaks. Most commonly hit in embedded auth: e.g. a Goodreads sign-in WebView whose post-Amazon-SSO redirect lands on a UL-eligible URL like
/ap-handler/sign-in?IDP=lwa, sending the user into the installed Goodreads app.iOS does not expose a way to predict UL handoff at the navigation delegate — UL is decided in WebKit's process before
decidePolicyForNavigationAction:fires.API
'goodreads.com'coversgoodreads.com,www.goodreads.com, and any subdomain — but notevilgoodreads.com.NSURLRequestin the navigation action, and reissuing single-use OAuth codes (Amazon callbacks etc.) double-consumes them.WKWebViewinstance breaks the cancel/reissue loop.Files
apple/RNCWebViewImpl.{h,m}— cancel/reissue logic with loop guardapple/RNCWebView.mm— Fabric prop array conversion (mirrorssuppressMenuItemspattern)apple/RNCWebViewManager.mm— Paper prop registrationsrc/RNCWebViewNativeComponent.ts,src/WebViewTypes.ts— TS spec + JSDoclib/*— rebuilt to matchTest plan
Verified end-to-end on a physical iPhone via the Bookwise consumer (readwiseio/rekindled#9205):
🤖 Generated with Claude Code