Remove the v1 (fetched-key) connect protocol - #66
Merged
Conversation
Both II instances now run the registration-delegation handshake by default, so the legacy v1 "fetched-key" connect protocol is dead code. Remove it entirely and make the registration-delegation flow the single, unconditional connect path. The per-instance `registration_delegation` flag existed only to select v1 vs the new flow, so it and its env vars go too. auth.rs - Remove the `/oauth/finish` handler (`finish` + `FinishQuery`), the `finishing_page` poll, the v1 `connect_callback` POST handler (key-request + completion cases), `ConnectCallback`, `KeyClaim`, `authz_known`, the `connect_error` HTML page, and the `finish_secret` machinery (`fresh_secret`/`sha256`/`ct_eq`, the `REPEAT_KEY_REQUESTS` counter + `repeat_key_requests()`, and `AuthzPending.finish_secret_hash`). - Collapse the `registration_delegation` conditionals: `authorize` always mints the registration key and builds the v2 link; the pinned callback page and redeem endpoint are always served (no more 404 guard). - Consolidate the link builders — `ii_mcp_url_v2` becomes the sole `ii_mcp_url`. - Rewrite the module docs to describe the single flow. identities.rs - Remove the `IiInstance::registration_delegation` field, the MCP_REGISTRATION_DELEGATION / _PROD env vars, and the now-unused `env_flag`. - Remove `session_pubkey_b64` and `grant_is_live` (v1-only). Keep `set_grant_expiration`/`set_permissions` (the Phase-2 redemption calls them), refreshing their v1-flavored docs. main.rs - Drop the `/oauth/finish` route; make `/oauth/connect/callback` GET-only. - Remove the `/version` `repeat_key_requests` and `registration_delegation` fields and the per-protocol startup-log branch. Also removed the two v1-only page assets (connect-finishing.html, connect-error.html), rewrote the README Auth/connect sections and the monitoring check descriptions that referenced the v1 `finish_url` hand-back, and dropped or reworked the v1-only tests. Verified: cargo build/test (120 passing) + clippy clean (no new warnings); monitoring node --test 17 passing. Smoke test confirms /oauth/finish now 404s, POST /oauth/connect/callback 405s, the pinned page GET serves 200, and /version no longer reports the removed fields. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wx6xR88QhyQCtrKUyXgiRL
There was a problem hiding this comment.
Pull request overview
This PR removes the legacy v1 “fetched-key” Internet Identity MCP connect protocol and makes the registration-delegation handshake the single, unconditional connect flow across both II instances. It simplifies the auth/connect surface area by deleting v1-only handlers, flags/env vars, assets, and operational signals, while updating docs and monitoring to describe/validate only the v2 flow.
Changes:
- Remove v1 connect endpoints and supporting machinery (
/oauth/finish, POST/oauth/connect/callback, finish-secret + repeat-key-requests observability) and make the pinned callback page + redeem endpoint the only connect path. - Remove the per-instance
registration_delegationtoggle (and related env vars) so both instances always run the same flow. - Update README and monitoring checks/docs to reflect the pinned-callback + redeem-based handshake and new
/versionpayload.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/main.rs | Removes v1 routes and per-protocol logging/version fields; makes connect callback GET-only. |
| src/identities.rs | Deletes per-instance protocol flag/env handling and v1-only session helpers; refreshes docs around v2 registration. |
| src/auth.rs | Removes v1 finish/callback POST flow and consolidates to pinned callback page + redeem with mcp_register_v2. |
| src/assets/connect-finishing.html | Deletes v1 finishing/polling interstitial asset. |
| src/assets/connect-error.html | Deletes v1 connect error page asset. |
| README.md | Rewrites auth/connect documentation to describe only registration-delegation and updated /version fields. |
| monitoring/mcp-status/README.md | Updates monitoring doc text to match the pinned callback + fetch redemption flow. |
| monitoring/mcp-status/checks.test.js | Updates test expectations/comments for the new connect flow (no finish_url). |
| monitoring/mcp-status/checks.js | Updates health-check descriptions/comments to reflect the pinned callback + redeem fetch model. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The comment's 'it' was ambiguous — a reader could take it to mean the whole connect flow works without JS, when only the outbound 302 redirect to II does (the pinned callback page still needs JS to read the fragment and POST the delegation). Scope the statement to that hop. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wx6xR88QhyQCtrKUyXgiRL
aterga
pushed a commit
that referenced
this pull request
Jul 20, 2026
Rebased onto main after #64 (identity tools take derivation_origin only), reconciliation is now carried by #66, so this narrows to the non-auth improvements that main still lacks: - call_canister: document the candid? arg; state the OQL query-call rejection accurately (fires when get_canister_candid reports oql: true, not on any OQL canister). - discover: reframe open_app as the one-call entry point; note the domain argument accepts a domain or URL. - App Connect: add the SSRF-hardening note (CWE-918), scoped precisely (user-supplied fetches are address-pinned; dashboard/registry enrichment uses the redirect guard only). - OQL: define the CWE-674 guard (1 MiB / 128-depth pre-parse check over textual Candid; the OQL query path is JSON and only shares the size cap). - Creating canisters: correct the CMC recovery hint (re-notify with the same arguments; the block index alone is not enough). - Run/Deploy: self-contained binary via include_str!; OAUTH_CLIENTS_FILE is always used (default oauth-clients.json, read on startup, best-effort write), needs a writable path; graceful SIGTERM/SIGINT drain; landing page. - Try it: fix the stateless plain-JSON example (drop the SSE parsing and session-id dance, show the bearer token, label the read anonymous). - Domain identities: correct the stale custom-derivation-origin note (the app_url path resolves declared/known origins via resolve_app; only a raw derivation_origin is used verbatim). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014T9N8USDfNK5yzznPGg7Ym
aterga
pushed a commit
that referenced
this pull request
Jul 21, 2026
Rebased onto main after #64 (identity tools take derivation_origin only), reconciliation is now carried by #66, so this narrows to the non-auth improvements that main still lacks: - call_canister: document the candid? arg; state the OQL query-call rejection accurately (fires when get_canister_candid reports oql: true, not on any OQL canister). - discover: reframe open_app as the one-call entry point; note the domain argument accepts a domain or URL. - App Connect: add the SSRF-hardening note (CWE-918), scoped precisely (user-supplied fetches are address-pinned; dashboard/registry enrichment uses the redirect guard only). - OQL: define the CWE-674 guard (1 MiB / 128-depth pre-parse check over textual Candid; the OQL query path is JSON and only shares the size cap). - Creating canisters: correct the CMC recovery hint (re-notify with the same arguments; the block index alone is not enough). - Run/Deploy: self-contained binary via include_str!; OAUTH_CLIENTS_FILE is always used (default oauth-clients.json, read on startup, best-effort write), needs a writable path; graceful SIGTERM/SIGINT drain; landing page. - Try it: fix the stateless plain-JSON example (drop the SSE parsing and session-id dance, show the bearer token, label the read anonymous). - Domain identities: correct the stale custom-derivation-origin note (the app_url path resolves declared/known origins via resolve_app; only a raw derivation_origin is used verbatim). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014T9N8USDfNK5yzznPGg7Ym
aterga
pushed a commit
that referenced
this pull request
Jul 21, 2026
Rebased onto main after #64 (identity tools take derivation_origin only), reconciliation is now carried by #66, so this narrows to the non-auth improvements that main still lacks: - call_canister: document the candid? arg; state the OQL query-call rejection accurately (fires when get_canister_candid reports oql: true, not on any OQL canister). - discover: reframe open_app as the one-call entry point; note the domain argument accepts a domain or URL. - App Connect: add the SSRF-hardening note (CWE-918), scoped precisely (user-supplied fetches are address-pinned; dashboard/registry enrichment uses the redirect guard only). - OQL: define the CWE-674 guard (1 MiB / 128-depth pre-parse check over textual Candid; the OQL query path is JSON and only shares the size cap). - Creating canisters: correct the CMC recovery hint (re-notify with the same arguments; the block index alone is not enough). - Run/Deploy: self-contained binary via include_str!; OAUTH_CLIENTS_FILE is always used (default oauth-clients.json, read on startup, best-effort write), needs a writable path; graceful SIGTERM/SIGINT drain; landing page. - Try it: fix the stateless plain-JSON example (drop the SSE parsing and session-id dance, show the bearer token, label the read anonymous). - Domain identities: correct the stale custom-derivation-origin note (the app_url path resolves declared/known origins via resolve_app; only a raw derivation_origin is used verbatim). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014T9N8USDfNK5yzznPGg7Ym
aterga
pushed a commit
that referenced
this pull request
Jul 22, 2026
Rebased onto main after #64 (identity tools take derivation_origin only), reconciliation is now carried by #66, so this narrows to the non-auth improvements that main still lacks: - call_canister: document the candid? arg; state the OQL query-call rejection accurately (fires when get_canister_candid reports oql: true, not on any OQL canister). - discover: reframe open_app as the one-call entry point; note the domain argument accepts a domain or URL. - App Connect: add the SSRF-hardening note (CWE-918), scoped precisely (user-supplied fetches are address-pinned; dashboard/registry enrichment uses the redirect guard only). - OQL: define the CWE-674 guard (1 MiB / 128-depth pre-parse check over textual Candid; the OQL query path is JSON and only shares the size cap). - Creating canisters: correct the CMC recovery hint (re-notify with the same arguments; the block index alone is not enough). - Run/Deploy: self-contained binary via include_str!; OAUTH_CLIENTS_FILE is always used (default oauth-clients.json, read on startup, best-effort write), needs a writable path; graceful SIGTERM/SIGINT drain; landing page. - Try it: fix the stateless plain-JSON example (drop the SSE parsing and session-id dance, show the bearer token, label the read anonymous). - Domain identities: correct the stale custom-derivation-origin note (the app_url path resolves declared/known origins via resolve_app; only a raw derivation_origin is used verbatim). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014T9N8USDfNK5yzznPGg7Ym
aterga
pushed a commit
that referenced
this pull request
Jul 23, 2026
Rebased onto main after #64 (identity tools take derivation_origin only), reconciliation is now carried by #66, so this narrows to the non-auth improvements that main still lacks: - call_canister: document the candid? arg; state the OQL query-call rejection accurately (fires when get_canister_candid reports oql: true, not on any OQL canister). - discover: reframe open_app as the one-call entry point; note the domain argument accepts a domain or URL. - App Connect: add the SSRF-hardening note (CWE-918), scoped precisely (user-supplied fetches are address-pinned; dashboard/registry enrichment uses the redirect guard only). - OQL: define the CWE-674 guard (1 MiB / 128-depth pre-parse check over textual Candid; the OQL query path is JSON and only shares the size cap). - Creating canisters: correct the CMC recovery hint (re-notify with the same arguments; the block index alone is not enough). - Run/Deploy: self-contained binary via include_str!; OAUTH_CLIENTS_FILE is always used (default oauth-clients.json, read on startup, best-effort write), needs a writable path; graceful SIGTERM/SIGINT drain; landing page. - Try it: fix the stateless plain-JSON example (drop the SSE parsing and session-id dance, show the bearer token, label the read anonymous). - Domain identities: correct the stale custom-derivation-origin note (the app_url path resolves declared/known origins via resolve_app; only a raw derivation_origin is used verbatim). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014T9N8USDfNK5yzznPGg7Ym
aterga
pushed a commit
that referenced
this pull request
Jul 28, 2026
Rebased onto main after #64 (identity tools take derivation_origin only), reconciliation is now carried by #66, so this narrows to the non-auth improvements that main still lacks: - call_canister: document the candid? arg; state the OQL query-call rejection accurately (fires when get_canister_candid reports oql: true, not on any OQL canister). - discover: reframe open_app as the one-call entry point; note the domain argument accepts a domain or URL. - App Connect: add the SSRF-hardening note (CWE-918), scoped precisely (user-supplied fetches are address-pinned; dashboard/registry enrichment uses the redirect guard only). - OQL: define the CWE-674 guard (1 MiB / 128-depth pre-parse check over textual Candid; the OQL query path is JSON and only shares the size cap). - Creating canisters: correct the CMC recovery hint (re-notify with the same arguments; the block index alone is not enough). - Run/Deploy: self-contained binary via include_str!; OAUTH_CLIENTS_FILE is always used (default oauth-clients.json, read on startup, best-effort write), needs a writable path; graceful SIGTERM/SIGINT drain; landing page. - Try it: fix the stateless plain-JSON example (drop the SSE parsing and session-id dance, show the bearer token, label the read anonymous). - Domain identities: correct the stale custom-derivation-origin note (the app_url path resolves declared/known origins via resolve_app; only a raw derivation_origin is used verbatim). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014T9N8USDfNK5yzznPGg7Ym
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.
What
Both II instances now run the registration-delegation handshake by default, so the legacy v1 "fetched-key" connect protocol is dead code. This removes it entirely and makes the registration-delegation flow the single, unconditional connect path. The per-instance
registration_delegationflag existed only to select v1 vs. the new flow, so it and its env vars go too.Net: 9 files changed, +340 / −1054.
Changes
src/auth.rs/oauth/finishhandler (finish+FinishQuery), thefinishing_pagepoll, the v1connect_callbackPOST handler (key-request + completion cases),ConnectCallback,KeyClaim,authz_known, theconnect_errorHTML page, and thefinish_secretmachinery (fresh_secret/sha256/ct_eq, theREPEAT_KEY_REQUESTScounter +repeat_key_requests(), andAuthzPending.finish_secret_hash).registration_delegationconditionals:authorizealways mints the registration key and builds the v2 link; the pinned callback page and redeem endpoint are always served (no more 404 guard).ii_mcp_url_v2becomes the soleii_mcp_url.src/identities.rsIiInstance::registration_delegationfield, theMCP_REGISTRATION_DELEGATION/_PRODenv vars, and the now-unusedenv_flag.session_pubkey_b64andgrant_is_live(v1-only). Keepset_grant_expiration/set_permissions(the Phase-2 redemption calls them), refreshing their v1-flavored docs.src/main.rs/oauth/finishroute; make/oauth/connect/callbackGET-only./versionrepeat_key_requestsandregistration_delegationfields and the per-protocol startup-log branch.Assets & docs
connect-finishing.html,connect-error.html).finish_urlhand-back.Verification
cargo build— clean (only the two pre-existing warnings,tool_router/ok; no new ones).cargo test— 115 passing, 0 failing.cargo clippy— output identical to the base branch; no new lints.monitoring/mcp-statusnode --test— 17 passing.connect-finishing,connect-error,MCP_REGISTRATION_DELEGATION,registration_delegation,oauth/finish,finish_secret,repeat_key_requests,connect_callback, baremcp_register).🤖 Generated with Claude Code
https://claude.ai/code/session_01Wx6xR88QhyQCtrKUyXgiRL
Generated by Claude Code