Skip to main content
A session removes the per-transaction wallet prompt, so its safety depends on both key custody and the onchain scope the user approved. Rhinestone coordinates the grant and intent flow; it does not hold the session private key or decide whether an out-of-scope call is valid.

Responsibility boundaries

The onchain validator checks the contract, selector, calldata rules, native value limit, time window, usage limit, and any crosschain claim permit encoded in the approved session. A request outside those rules fails even if Rhinestone prepared or forwarded it. Names and ABI metadata shown during review improve readability only. Only Rhinestone’s maintained clear-signing registry can supply verified display metadata; app-supplied metadata is not an authorization boundary.

Protect the signer

Treat a session key as a bearer credential for everything inside its scope.
  • The session option on sendIntent() takes a viem LocalAccount. With privateKeyToAccount(), keep the extractable private key in protected local or backend secret storage appropriate to the grant’s value.
  • A non-exportable KMS or HSM key needs a custom toAccount() signer; that integration is outside this guide.
  • If a browser must sign, keep the scope short-lived and low-value. Any script that can read the key can use it.
  • Separate keys by user, account, environment, and purpose. Do not reuse one signer across unrelated grants.
  • Persist the grant ID, account, signer address, private key, and handle together. Refuse to sign unless the stored account and signer match the handle.
  • Bind your own backend requests to the authenticated application user and expected smart account before allowing a signing job.
  • Stop scheduling a function on a chain as soon as its counter is exhausted. Other function or chain counters can remain active. Stop all work on expiry or suspected compromise. Onchain rejection is the final backstop, not normal control flow.
See Session limits for the least-authority controls.

Recover grant metadata

Your application can recover public grant records after local handle loss. The user must have an active embedded-wallet session in the account namespace that created the grant. wallet is the @rhinestone/wallet client from Accounts.
The default app-origin account namespace is the exact browser host. A registered app can explicitly configure a shared rpId; its server-authorized sibling origins then use that shared RP and account namespace. A matching clientId alone does not share the account namespace. Reuse the same clientId, rpId, and authenticated account configuration when recovering a shared-RP grant. The recovered handle contains no private signing capability. Pair it only with a signer whose public address matches sessionKeyHandle.sessionKeyAddress and whose stored account matches sessionKeyHandle.accountAddress. If the private key was lost, create a new signer and grant rather than pretending the old session is recoverable.

Revoke authority

Revoke a grant with revokeSessionGrant(). The user must be signed in to the account that owns the grant; they review the revoke and sign it with their passkey, and it runs on every chain the grant is enabled on.
success is true only when the revoke landed on every chain. Each chain whose revoke completed shows as revoked in listSessionGrants(); authority stays active on any chain whose revoke failed.
Deleting a key or handle from application storage does not revoke the onchain session. It stops that copy of the app from using the grant, but a leaked key can still use any unexpired function and chain counter.
Use short expiry windows, low per-call caps, and low per-function use counts so that a leaked key’s reach stays small until revocation lands. Fail closed when grant state or signer consistency cannot be confirmed.

Incident response

If a signer may be compromised:
  1. Stop every worker and browser task that can use it, and reject new signing requests.
  2. Preserve the account address, grant ID, signer address, handle, and affected chain IDs for response.
  3. Revoke the grant with revokeSessionGrant() and check chainResults for every affected chain.
  4. Treat every unexpired function and chain counter as usable until its onchain configuration is confirmed removed or its limits expire.
  5. Remove the signer from application storage, then create a narrower replacement only after identifying the exposure.
Never rotate only the stored handle. Permission IDs and handles describe authority; they are not replacement credentials.