Skip to content

feat: sign in to a session, and end it at the canister - #159

Open
sea-snake wants to merge 10 commits into
feat/auth-session-minterfrom
feat/auth-session-acquire
Open

feat: sign in to a session, and end it at the canister#159
sea-snake wants to merge 10 commits into
feat/auth-session-minterfrom
feat/auth-session-acquire

Conversation

@sea-snake

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

Copy link
Copy Markdown
Contributor

signIn() asks for a session rather than a long-lived delegation. What comes back is restricted to Internet Identity, so a copy of it is worth nothing against an application's own canisters and the only thing it can do is mint.

  • maxTimeToLive keeps meaning the longest the thing being granted may live. targets goes: what an application may call is decided by the delegations minted from the session, not by the session itself.
  • It mints inside the ceremony the user is already waiting through, so the first request afterwards does not wait. That mint is also where the account's key comes from — the session chain is rooted at the session's own key, and only a mint reports the key an application's canisters see. A page load takes it from the stored app credential instead, and mints where there is none, which such a load owes anyway.
  • signOut() ends the session at the canister, so access stops within one delegation lifetime instead of running to the session's expiry. The revoke and the wipe run together: a slow or failing call must not hold up a sign-out the user asked for, and only the wipe may fail it — the idle callback reloads on success alone, and a reload after a failed wipe would restore the session it just tried to end.
  • identityProvider becomes two values. A ceremony is rendered at a URL and delegations are minted by a canister, and they are not the same address.

Teardown covers both slots. This is the layer where a second credential exists, and it is the layer where signOut() starts removing it: an app delegation left behind is minted under a sign-in that has ended and can still be adopted on the next page load. Both removals are attempted whatever either does, and the first failure is reported once neither is left behind.

A ceremony writes to its own slot. The first mint goes to app-pending and is promoted once the session and state are stored, so the slot every tab of the origin acts with is never emptied — a sign-in that fails costs the other tabs nothing, and an abandoned redirect leaves a spent five-minute record instead of having wiped the live one. That makes both halves of a ceremony symmetric with session-pending.

Sign-out is here rather than in its own PR because it is a revoke call, a lock steal and an ordering rule, and it reads better beside the sign-in it undoes. #160 is closed for that reason.

Read hardest: #openSession, shared by sign-in and hydration, and the ordering in signOut.

@sea-snake
sea-snake requested a review from a team as a code owner August 23, 2026 19:40
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 361c2d6 to 3cfbdc8 Compare August 23, 2026 22:18
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch 2 times, most recently from 7d9d63e to 21a1d55 Compare August 23, 2026 23:36
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 21a1d55 to c0a342d Compare August 23, 2026 23:45
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from c0a342d to 1bb1394 Compare August 24, 2026 05:42
@sea-snake
sea-snake changed the base branch from feat/auth-session-minter to feat/auth-delegation-storage August 24, 2026 05:46
Copilot AI lite review requested due to automatic review settings August 24, 2026 08:53
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 1bb1394 to bab8f0b Compare August 24, 2026 08:53

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors AuthClient to authenticate via Internet Identity sessions (ii_session_delegation) and mint short-lived (5-minute) app delegations from that session, while splitting persistence into two stores: an async IdentityStorage for the session signing key and a synchronous/observable SessionStorage for the session delegation chain.

Changes:

  • Replace long-lived delegation sign-in with a session-based flow and mint app delegations during the sign-in ceremony.
  • Split persisted state into identityStorage (key material, async) and sessionStorage (session chain + account key, sync + subscribable), removing the legacy combined storage (storage.ts).
  • Update tests and documentation to reflect the new session-based behavior and configuration options.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/client/storage.test.ts Removes tests for legacy IdbStorage/combined storage that is deleted.
tests/client/auth-client.test.ts Updates/expands AuthClient tests for session sign-in, minting, session restore, subscriptions, and returnTo handling.
tests/client/auth-client-redirect.test.ts Updates redirect-flow tests for session delegation + identity persistence across redirects, including returnTo journaling/navigation.
src/client/storage.ts Removes legacy combined storage abstractions (AuthClientStorage, IdbStorage, LocalStorage, key constants).
src/client/session-delegation.ts Adds ii_session_delegation JSON-RPC request/response handling to build a DelegationChain from the signer response.
src/client/index.ts Removes exports for deleted legacy storage APIs.
src/client/auth-client.ts Implements session sign-in + minting, introduces identity/session storage split, subscription-based reconciliation, and updated identity provider configuration.
docs/src/content/docs/quick-start.md Updates Quick Start to new identityProvider object + agent options for local development.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/client/auth-client.ts
Comment thread docs/src/content/docs/quick-start.md Outdated
Comment thread src/client/session-delegation.ts
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch 2 times, most recently from f1b2e15 to 5c67e22 Compare August 24, 2026 10:05
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 5c67e22 to f8c4102 Compare August 24, 2026 10:39
Comment thread src/client/session-delegation.ts
Comment thread tests/client/auth-client-redirect.test.ts
@sea-snake
sea-snake changed the base branch from feat/auth-delegation-storage to main August 29, 2026 10:22
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 84b2f9b to d015c0b Compare August 29, 2026 10:23
@sea-snake
sea-snake changed the base branch from main to feat/auth-session-minter August 29, 2026 10:23
@sea-snake sea-snake changed the title feat: sign in to a session and mint the app's delegations from it feat: sign in to a session, and end it at the canister Aug 29, 2026
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 75ce974 to 24b2cfb Compare August 31, 2026 08:52
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 24b2cfb to 9921b8a Compare August 31, 2026 09:34
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 9921b8a to 6769a4f Compare August 31, 2026 10:31
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 6769a4f to 777935b Compare August 31, 2026 12:51
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from c74b184 to b0eef9d Compare August 31, 2026 13:13
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 7657480 to 01fbf68 Compare August 31, 2026 13:53
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 01fbf68 to f5acbb3 Compare August 31, 2026 14:10
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch 2 times, most recently from 69272a0 to 4186ddd Compare August 31, 2026 16:09
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 4186ddd to 6ecde2c Compare August 31, 2026 17:04
signIn asks for a session rather than a long-lived delegation, and what
comes back is restricted to Internet Identity — so a copy of it is worth
nothing against an application's own canisters, and the only thing it
can do is mint. maxTimeToLive keeps meaning the longest the thing being
granted may live; targets go, because what an application may call is
decided by the delegations minted from the session rather than by the
session itself.

It mints inside the ceremony the user is already waiting through, so the
first request afterwards does not wait. That mint is also where the
account's key comes from: the session chain is rooted at the session's
own key, and only a mint reports the key an application's canisters see.
A page load takes it from the stored app credential instead, and mints
where there is none — which such a load owes anyway.

signOut ends the session at the canister, so access stops within one
delegation lifetime instead of running to the session's expiry. The
revoke and the wipe run together: a slow or failing call must not hold
up a sign-out the user asked for, and only the wipe may fail it, because
the idle callback reloads on success alone and a reload after a failed
wipe would restore the session it just tried to end.

The identity provider becomes two values. A ceremony is rendered at a
URL and delegations are minted by a canister, and they are not the same
address.
@sea-snake
sea-snake force-pushed the feat/auth-session-acquire branch from 6ecde2c to 27d907a Compare August 31, 2026 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants