diff --git a/.sources/VERSIONS b/.sources/VERSIONS index 58dcd2f..76afdea 100644 --- a/.sources/VERSIONS +++ b/.sources/VERSIONS @@ -62,4 +62,4 @@ motoko-core v2.4.0 cdk-rs ic-cdk v0.20.1 / ic-cdk-timers v1.0.0 / ic-cdk-executor v2.0.0 317f55c candid 2025-12-18 # candid v0.10.20, didc v0.5.4 2e4a2cf response-verification v3.1.0 18c5a37 -internetidentity release-2026-07-06 37670ecf +internetidentity release-2026-07-17 8ffbe6f6 diff --git a/.sources/internetidentity b/.sources/internetidentity index 37670ec..8ffbe6f 160000 --- a/.sources/internetidentity +++ b/.sources/internetidentity @@ -1 +1 @@ -Subproject commit 37670ecf4ac0600a9ff596ebc8a5e885e31249cd +Subproject commit 8ffbe6f6424ace469f3a2ae1dd277561cd4e7bbe diff --git a/public/references/internet-identity.did b/public/references/internet-identity.did index 5574be5..9554ab2 100644 --- a/public/references/internet-identity.did +++ b/public/references/internet-identity.did @@ -1124,11 +1124,23 @@ type McpConfig = record { url : opt text; }; -// Result of mcp_register: the expiration (ns since epoch) of the MCP session -// grant just registered. Every server-facing mcp_* call returns Unauthorized -// once it passes; the server reconnects through a new consent flow. -type McpRegistration = record { +// Result of prepare_mcp_registration_delegation: the canister-signature public +// key the registration delegation is rooted at (P_reg), and the (short) +// expiration of that delegation. The frontend fetches the signed delegation via +// get_mcp_registration_delegation and delivers the chain to the trusted MCP +// server, which redeems it with mcp_register_v2. +type PrepareMcpRegistrationDelegation = record { + user_key : UserKey; + expiration : Timestamp; +}; + +// Result of mcp_register_v2: the expiration (ns since epoch) of the MCP session +// grant, plus the access level the user chose at connect (queries = read-only, +// all = full). The server reads permissions to learn the read-only state up +// front (the v2 flow has no completion POST carrying it). +type McpRegistrationV2 = record { expiration : Timestamp; + permissions : Permissions; }; type GetAccountsError = variant { @@ -1819,28 +1831,6 @@ service : (opt InternetIdentityInit) -> { permissions : opt Permissions ) -> (variant { Ok : SignedDelegation; Err : AccountDelegationError }) query; - // Register the trusted MCP server's session key for the anchor: grant the - // key's self-authenticating principal access to the server-facing mcp_* - // methods until the grant expires (grant_ttl_ns clamped to [10 min, 30 - // days]). Called by the /mcp connect flow after user consent, with a key - // the frontend fetched from the *trusted* server's callback — never taken - // from the unauthenticated connect link. No account is chosen here - // (accounts are per-origin and the connector isn't an app) — the app - // account is selected per call on mcp_prepare_delegation. - // - // At most one session per identity: registering replaces any previous - // grant. Requires the identity's MCP config to be enabled with a trusted - // server set, so every session stays revocable via mcp_set_config. - mcp_register : ( - anchor_number : UserNumber, - session_key : SessionKey, - grant_ttl_ns : nat64, - // `opt (queries)` makes every per-app delegation this session later - // mints queries-only (read-only, chosen once for the whole session). - // Omitted (`null`) or `opt (all)` means full, update-capable access. - permissions : opt Permissions - ) -> (variant { Ok : McpRegistration; Err : text }); - // Read the identity's synced trusted-MCP-server config (master toggle + the // trusted server URL). Persisted on-chain, so it follows the identity across // devices. Read by the Settings UI and the /mcp connect flow (which verifies @@ -1905,6 +1895,48 @@ service : (opt InternetIdentityInit) -> { expiration : Timestamp ) -> (variant { Ok : SignedDelegation; Err : SessionDelegationError }) query; + // Mint a short-lived MCP registration delegation (P_reg -> registration_key). + // Authenticated as the identity (only the consenting user can create one). + // registration_key is an ephemeral key the II frontend generates for this + // connect (browser-held — the canister never delegates to a key taken from + // the connect link; the frontend extends the chain to the server's key + // browser-side). P_reg is derived from a fresh random nonce, and the whole + // consent — the anchor, permissions (read-only choice), max_ttl (session- + // grant lifetime), and the identity's current trusted-server URL — is + // recorded on an index entry keyed by P_reg, so mcp_register_v2 recovers it + // server-side and the server cannot alter any of it. + prepare_mcp_registration_delegation : ( + anchor_number : UserNumber, + registration_key : SessionKey, + permissions : opt Permissions, + max_ttl : opt nat64 + ) -> (variant { Ok : PrepareMcpRegistrationDelegation; Err : text }); + + // Fetch the signed registration delegation prepared above, to deliver to the + // trusted MCP server. Authenticated as the identity, like the prepare call. + // user_key is the value the prepare call returned; the seed is recovered + // from it, so no consent parameters need re-passing. + get_mcp_registration_delegation : ( + anchor_number : UserNumber, + registration_key : SessionKey, + user_key : PublicKey, + expiration : Timestamp + ) -> (variant { Ok : SignedDelegation; Err : text }) query; + + // Called by the trusted MCP server, authenticated by the registration + // delegation chain: bind the server's long-lived session_key to the + // consenting anchor. The entire consent — anchor, read-only choice, grant + // lifetime — is recovered from the entry keyed by caller() (the registration + // principal), so the server passes only session_key: it cannot name a + // different anchor, upgrade the access level or stretch the grant, and never + // learns the anchor number. A trusted-server switch or disable since consent + // invalidates the delegation. Usable until the registration delegation + // expires (~5 min); re-registration within that window replaces the anchor's + // single MCP session. + mcp_register_v2 : ( + session_key : SessionKey + ) -> (variant { Ok : McpRegistrationV2; Err : text }); + get_default_account : ( anchor_number : UserNumber, origin : FrontendHostname,