Repository navigation
Add ICRC-167: Browser URL Transport draft standard - #246
Merged
Merged
Conversation
Promotes the "Browser URL Transport" idea to a draft transport standard. Defines an ICRC-25 transport channel over browser URL navigation, carrying JSON-RPC messages in the URL hash fragment so message contents are never sent to a backend. Suitable for top-level redirects and native/mobile deep links where a window.postMessage channel (ICRC-29) is unavailable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address working-group feedback: - Require domain-verified deep links (App Links / Universal Links) and forbid custom URI schemes, which any app can register and use to intercept a returned delegation. - Allow the request to be a JSON-RPC 2.0 batch so a relying party can request e.g. a delegation and accounts in a single navigation. - Validate the callback against a relying-party-declared allow-list at /.well-known/ii-auth-callbacks (exact match, strict fail-closed fetch) instead of accepting an arbitrary callback, and add a `state` param the signer echoes back to bind the response to the initiating request. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address further working-group feedback: - Document that an interaction may span several sequential round-trips (a later request depending on an earlier response), driven by the relying party, with signer per-origin permission state avoiding re-establishment between hops. - Add signer-initiated interactions: a signer navigates to one of the relying party's declared callbacks with `init` + `transport` in place of a `message`, prompting the relying party to begin an ordinary request flow (modelled on OIDC third-party-initiated login). The declared callbacks double as init entry points, so no second endpoint or well-known key is introduced. The relying party must validate the untrusted `transport` before navigating to it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The signer that initiates is reached over this same URL transport, so a `transport` param is redundant and would be an attacker-suppliable destination. Remove it: `init` is now a pure trigger, and the relying party determines the signer exactly as for any relying-party-initiated interaction, so it never navigates to a signer chosen by untrusted input. Drop the now-unneeded untrusted-transport validation and error case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On a signer-initiated first hop, a relying party that supports multiple signers otherwise has to prompt the user to pick one. Add an optional `signer` hint (the signer's origin) so the initiating signer can preselect the intended one. Unlike the removed `transport`, the hint only selects among signers the relying party already knows: an unrecognised value is ignored and the relying party never navigates to a signer solely because the init navigation named it, so the untrusted-destination property is preserved. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Expand the Deep Links section with concrete setup steps and official documentation links for the platforms where a browser-to-app hand-off is reliable (iOS Universal Links, Android App Links). Correct the desktop story: verified browser-to-native-app hand-off does not work there. macOS opens Universal Links in the browser by default, and on modern Windows a supported link opened in a modern browser stays in the browser (only the deprecated Edge Legacy launched the app; the only browser-firing option is a forbidden custom protocol). Recommend the browser transport or a developer-implemented loopback (127.0.0.1) callback (RFC 8252) for native desktop apps, noting loopback does not fit the origin-based callback allow-list. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Loading a declared callback with no `message` is already an ordinary entry into the relying party's flow, so a signer initiates simply by navigating the user to a declared callback — no `init` marker or `signer` hint is needed. Simplify the Signer-Initiated Interaction section and its cross-references accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A native desktop app reaches a signer by opening a web page it controls that acts as an ordinary relying party over any applicable transport, and forwarding the messages to the app over a loopback (127.0.0.1) server (RFC 8252). The page's callback is its own https URL, so the callback allow-list applies normally; the loopback is only the page-to-app bridge, not a signer callback. Drop the irrelevant ICRC-29 suggestion and the incorrect "loopback callback doesn't fit the allow-list" framing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…k steps) Replace the vague desktop paragraph with a concrete three-step pattern: the native app opens a web page it controls, that page runs the flow as an ordinary relying party, and it relays the result to the app over a local channel (e.g. a loopback server). State plainly that only the web page participates in the transport and the relay is out of scope. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MRmarioruci
approved these changes
Sep 10, 2026
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.
Promotes the Browser URL Transport entry (previously
![IDEA]) to a draft transport standard, as ICRC-167.What it defines
An ICRC-25 transport channel based on browser URL navigation, following the same document shape as ICRC-29 and ICRC-94:
callbackURL with the JSON-RPC response in the URL.window.postMessage(ICRC-29) isn't available: top-level redirects between two web pages and native/mobile deep links.Interaction models
messagemay be a JSON-RPC 2.0 batch, so a relying party requests e.g. a delegation (ICRC-34) and accounts/attributes in a single navigation (parallel).initin place of amessage, prompting the relying party to begin an ordinary request flow (modelled on OIDC third-party-initiated login). An optionalsignerhint lets it preselect which of the relying party's known signers to use.initis a pure trigger and the hint can only select among already-trusted signers, so the relying party never navigates to an untrusted destination. The declared callbacks double as init entry points, so no second endpoint is introduced.Safety design
callbackis attacker-craftable, so the signer honors it only when it exact-matches an entry the relying party declares at/.well-known/ii-auth-callbacks(reusing II's allow-list, strict fail-closed fetch: no redirects, no credentials,no-store,application/json, size cap, same-origin entries, no fragments, CORS). The declared callbacks are the complete set of URLs a signer may navigate the browser to for that RP. Astateparam the signer echoes back binds a response to the initiating request (the callback itself must stay static to match the allow-list).Changes
topics/icrc_167_browser_url_transport.md.README.md: Transport Channel table entry updated from![IDEA]to![DRAFT]with a link.Companion registry issue: dfinity/ICRC#167