Skip to content

feat(be): sign a session to the II frontend at sign-in - #4268

Open
sea-snake wants to merge 4 commits into
feat/session-cap-per-identityfrom
feat/sign-in-creates-a-session
Open

feat(be): sign a session to the II frontend at sign-in#4268
sea-snake wants to merge 4 commits into
feat/session-cap-per-identityfrom
feat/sign-in-creates-a-session

Conversation

@sea-snake

@sea-snake sea-snake commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Design: #4224. Overview: #4230. This is the caller #4266 and #4264 were waiting for, so it removes their #[allow(dead_code)] annotations.

prepare_account_session / get_account_session. The first creates a session and signs its delegation to the II frontend's key; the second witnesses it. A separate pair from prepare_account_delegation, not an option on it: both mint, but one proves a live session and identifies the account by its principal while the other proves an access method and names the anchor outright. Merging them would mean one method with two authorizers and two argument shapes, and would drag the frontend's internal surface into the public API.

The browser proof is checked before anything is written, using the verifier from #4264. So is the account: an account the identity does not hold is the one failure a caller can provoke, and returning it after the writes would leave a browser registered for a sign-in that never happened.

Every later failure traps rather than returning. On the IC, returning an error commits state and only a trap rolls the message back, so once the browser registration is written a failure has to trap or a caller could be told "no" and still have a browser enrolled.

valid_for is the lifetime the user chose at consent, clamped by the canister to between 10 minutes and 30 days. Every ceremony creates, so it always applies: the replacement's expiry is measured from the ceremony that made it, and no session is renewed in place.

Tests: integration/sessions.rs (18) drives the real ceremony — creating and verifying a session, a request for another identity refused, the registry cap dropping the least recently used and ending its sessions, the key proof's rejections at the endpoint, rotation keeping the entry, a retired key returning as a new browser, and the registration archived with the name redacted.

@zeropath-ai

zeropath-ai Bot commented Aug 22, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to a899c6b.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► src/canister_tests/src/api/archive.rs
Enhancement ► src/canister_tests/src/api/internet_identity/api_v2.rs
Enhancement ► src/canister_tests/src/framework.rs
Enhancement ► src/frontend/src/lib/generated/internet_identity_idl.js
Enhancement ► src/frontend/src/lib/generated/internet_identity_types.d.ts
Enhancement ► src/internet_identity/internet_identity.did
Enhancement ► src/internet_identity/src/main.rs
Enhancement ► src/internet_identity/src/sessions.rs
Enhancement ► src/internet_identity/src/storage.rs
Enhancement ► src/internet_identity/tests/integration/main.rs
Enhancement ► src/internet_identity/tests/integration/sessions.rs

@sea-snake
sea-snake force-pushed the feat/sign-in-creates-a-session branch from 8a56cdc to afa4f93 Compare August 22, 2026 18:44
@sea-snake
sea-snake force-pushed the feat/sign-in-creates-a-session branch from afa4f93 to 1ab21d9 Compare August 22, 2026 19:06
@sea-snake
sea-snake force-pushed the feat/sign-in-creates-a-session branch from 1ab21d9 to b0ccd19 Compare August 22, 2026 19:25
`prepare_account_session` creates a session and signs its delegation to the
frontend's key; `get_account_session` witnesses it. This is what gives the
storage beneath a caller, so the `allow(dead_code)` it carried goes with it.

The request carries the browser's key, the successor it rotates to, and both
proofs, which are checked before anything is written. So is the account: an
account the identity does not hold is the one failure a caller can provoke, and
returning it after the writes would leave a browser registered for a sign-in
that never happened. Every failure after the first write traps instead, rolling
the whole message back, because on the IC returning an error commits.

`valid_for` is the lifetime the user chose at consent, clamped by the canister
to between ten minutes and thirty days. Every ceremony creates, so it always
applies: the replacement's expiry is measured from the ceremony that made it,
and no session is renewed in place.

This is a separate pair from `prepare_account_delegation`, not an option on it.
Both mint, but one proves a live session and identifies the account by its
principal while the other proves an access method and names the anchor outright.
Merging them would mean one method with two authorizers and two argument shapes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature:revocable-app-sessions Design: revocable app sessions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant