Skip to content

feat(be): let an app sign its own session out - #4245

Open
sea-snake wants to merge 103 commits into
feat/session-refresh-stampsfrom
feat/app-revoke-session
Open

feat(be): let an app sign its own session out#4245
sea-snake wants to merge 103 commits into
feat/session-refresh-stampsfrom
feat/app-revoke-session

Conversation

@sea-snake

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

Copy link
Copy Markdown
Contributor

Design: #4224. Overview: #4230.

Signing out of an app cleared browser state and invalidated nothing already issued. app_revoke_session : () -> (variant { Ok; Err : AppSessionError }) removes the session record, so the app's access ends within one delegation lifetime instead of running to the original expiry.

  • No authorization check beyond the match refresh already performs, because a caller cannot produce another session's principal and can only ever remove its own.
  • A session that is already gone is Ok, so sign-out is idempotent: a client that retries, or signs out twice, gets the same answer without reasoning about whether its session was still there. Only a storage failure comes back as an error — the same error type its two siblings already return, so this is consistency with its own family rather than a new convention.
  • It finds the session without the expiry check, so signing out of an already-expired session still clears the record.

The app deliberately cannot revoke anything else. "Sign out everywhere" is the II frontend's operation (#4246), not something a dapp can trigger.

Revocation latency is exactly the app-delegation TTL, by construction: revoking stops new mints and one already issued runs out. mcp.rs documents the same residue for its grants.

Tests: session_removal_tests (3) plus PocketIC coverage that a refresh working before sign-out returns NoMatchingSession after, three sign-outs in a list all succeed, an expired session is still signed out and its record and index entry go with it, and signing one browser out leaves another browser's session on the same account working.

@sea-snake
sea-snake requested a review from a team as a code owner August 19, 2026 01:27
@zeropath-ai

zeropath-ai Bot commented Aug 19, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to 0b155a4.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► src/canister_tests/src/api/internet_identity/api_v2.rs
    Add app_revoke_session function
► src/frontend/src/lib/generated/internet_identity_idl.js
    Introduce app_revoke_session in IDL
► src/frontend/src/lib/generated/internet_identity_types.d.ts
    Add app_revoke_session type definition
► src/internet_identity/internet_identity.did
    Declare app_revoke_session in service interface
► src/internet_identity/src/main.rs
    Expose app_revoke_session update method
► src/internet_identity/src/sessions.rs
    Add app_revoke_session implementation
► src/internet_identity/src/storage.rs
    Implement revoke_session storage function
► src/internet_identity/src/storage/tests.rs
    Add tests for session removal scenarios
► src/internet_identity/tests/integration/sessions.rs
    Update imports to include app_revoke_session and related types
► src/internet_identity/tests/integration/sessions.rs
    Add tests for signing out and session management

Copilot AI lite review requested due to automatic review settings August 19, 2026 01:48
@sea-snake
sea-snake force-pushed the feat/app-revoke-session branch from 0c075d2 to 9ce7a2c Compare August 19, 2026 01:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sea-snake
sea-snake force-pushed the feat/app-revoke-session branch from 9ce7a2c to 354343e Compare August 19, 2026 02:57
@sea-snake
sea-snake force-pushed the feat/app-revoke-session branch from 354343e to a650a94 Compare August 19, 2026 03:47
@sea-snake
sea-snake force-pushed the feat/app-revoke-session branch from a650a94 to 2b70415 Compare August 19, 2026 06:28
@sea-snake
sea-snake force-pushed the feat/app-revoke-session branch from 2b70415 to 678bf30 Compare August 19, 2026 07:07
@sea-snake
sea-snake force-pushed the feat/app-revoke-session branch from 678bf30 to 783da5a Compare August 19, 2026 08:17
@sea-snake
sea-snake force-pushed the feat/app-revoke-session branch from 783da5a to 69ab376 Compare August 19, 2026 08:37
@sea-snake
sea-snake force-pushed the feat/app-revoke-session branch from 69ab376 to 4919341 Compare August 19, 2026 10:21
@sea-snake
sea-snake force-pushed the feat/app-revoke-session branch from 4919341 to 1b98bba Compare August 20, 2026 10:57
@sea-snake
sea-snake force-pushed the feat/app-revoke-session branch from 1b98bba to b943144 Compare August 20, 2026 13:08
@sea-snake
sea-snake force-pushed the feat/app-revoke-session branch from b943144 to 418c0f2 Compare August 20, 2026 13:52
@sea-snake
sea-snake force-pushed the feat/app-revoke-session branch from 418c0f2 to 6aea53c Compare August 20, 2026 15:24
sea-snake and others added 23 commits September 8, 2026 00:25
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVi99RYo2jyi2kCurgovNJ
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVi99RYo2jyi2kCurgovNJ
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVi99RYo2jyi2kCurgovNJ

# Conflicts:
#	src/internet_identity/src/storage/tests.rs
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVi99RYo2jyi2kCurgovNJ
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVi99RYo2jyi2kCurgovNJ
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVi99RYo2jyi2kCurgovNJ

# Conflicts:
#	src/internet_identity/tests/integration/sessions.rs
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVi99RYo2jyi2kCurgovNJ
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVi99RYo2jyi2kCurgovNJ
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVi99RYo2jyi2kCurgovNJ
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVi99RYo2jyi2kCurgovNJ
The expiry check stays in the delegation path, where this branch moved it:
a session past its bounds is still the caller's to sign out.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVi99RYo2jyi2kCurgovNJ
# Conflicts:
#	src/internet_identity/src/sessions.rs
`app_revoke_session` was the odd one of its three siblings: no error channel, so
`.expect` caught only the `Err` and `Ok(false)` reported a successful sign-out
for a session left active. It returns `variant { Ok; Err : AppSessionError }`
now, like `app_prepare_delegation` and `app_get_delegation`, and the trap has no
job left. A session that is not there is still `Ok` — the caller wanted it gone
and it is gone, and they cannot tell a pruned session from one that never
existed.

`revoke_session` walked the list twice, once to check the session was there and
once to remove it, only so it could answer `Ok(false)`. With the not-found error
one `retain` does both.

`match_session` becomes `find_caller_session`: one finds the caller's session,
the other authorizes it, and the return types say so. The comment above the
sign-out now gives the narrower reason the two differ — not that an absent
session needs revoking, but that a present-and-expired one must not be refused.
Which nothing tested, so it does now.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVi99RYo2jyi2kCurgovNJ
@sea-snake
sea-snake removed this pull request from stack #4276 September 9, 2026 20:34
@sea-snake
sea-snake added this pull request to stack #4323 September 9, 2026 20:34
@sea-snake
sea-snake removed this pull request from stack #4323 September 9, 2026 20:42
@sea-snake
sea-snake added this pull request to stack #4325 September 9, 2026 20:43
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.

3 participants