feat: sign in to a session, and end it at the canister - #159
Open
sea-snake wants to merge 10 commits into
Open
Conversation
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 23, 2026 22:18
361c2d6 to
3cfbdc8
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
2 times, most recently
from
August 23, 2026 23:36
7d9d63e to
21a1d55
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 23, 2026 23:45
21a1d55 to
c0a342d
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 24, 2026 05:42
c0a342d to
1bb1394
Compare
sea-snake
changed the base branch from
feat/auth-session-minter
to
feat/auth-delegation-storage
August 24, 2026 05:46
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 24, 2026 08:53
1bb1394 to
bab8f0b
Compare
There was a problem hiding this comment.
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) andsessionStorage(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.
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
2 times, most recently
from
August 24, 2026 10:05
f1b2e15 to
5c67e22
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 24, 2026 10:39
5c67e22 to
f8c4102
Compare
MRmarioruci
reviewed
Aug 26, 2026
MRmarioruci
reviewed
Aug 26, 2026
MRmarioruci
approved these changes
Aug 26, 2026
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 29, 2026 10:23
84b2f9b to
d015c0b
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 31, 2026 08:52
75ce974 to
24b2cfb
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 31, 2026 09:34
24b2cfb to
9921b8a
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 31, 2026 10:31
9921b8a to
6769a4f
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 31, 2026 12:51
6769a4f to
777935b
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 31, 2026 13:13
c74b184 to
b0eef9d
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 31, 2026 13:53
7657480 to
01fbf68
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 31, 2026 14:10
01fbf68 to
f5acbb3
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
2 times, most recently
from
August 31, 2026 16:09
69272a0 to
4186ddd
Compare
sea-snake
force-pushed
the
feat/auth-session-acquire
branch
from
August 31, 2026 17:04
4186ddd to
6ecde2c
Compare
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
force-pushed
the
feat/auth-session-acquire
branch
from
August 31, 2026 17:53
6ecde2c to
27d907a
Compare
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.
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.maxTimeToLivekeeps meaning the longest the thing being granted may live.targetsgoes: what an application may call is decided by the delegations minted from the session, not by the session itself.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.identityProviderbecomes 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-pendingand 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 withsession-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 insignOut.