Skip to main content
A session lets your application execute approved calls without asking for a passkey signature each time. The user grants the authority once; your application keeps the session signer and uses the embedded wallet to prepare and submit later intents. Start with the shared embedded wallet setup, authenticate the user, and keep the returned accountAddress. Configure the same sponsorship endpoints before granting or executing a session. The examples below use the public @rhinestone/1auth 0.10.1 release and its viem ^2.55.0 peer dependency.
1

Create a session signer

Generate an ECDSA key for the session. Only send its public address to Rhinestone.
This flow uses buildSmartSessionHeadlessSignatures(), which requires a locally accessible Hex private key. Keep it in storage appropriate to its value and environment. A non-exportable KMS or HSM key requires a custom signer and session-key signature implementation, which this guide does not cover.
2

Define the authority

Grant one ERC-20 transfer action on Base Sepolia. The recipient is fixed, each transfer is capped at 10 tokens, and that function can execute up to 25 times during the 24-hour window.
definePermissions() derives the selector and calldata constraints from the ABI. The name and ABI make the review readable, but they are app-supplied metadata. The contract address, selector, parameter rules, validity window, and usage limit define the authority.See Session limits before granting broader actions or using assets from another chain.
3

Ask the user to grant the session

Use the initialized oneAuth client and authenticated account from the embedded wallet setup:
The embedded wallet shows the scope, collects the owner’s passkey authorization, and installs or enables the session-key configuration. No target chain is selected implicitly.
4

Persist the signer and handle

Store both halves before starting headless execution. The signer is the capability; the handle describes the approved onchain configuration.
The stable, account-scoped key remains available after the in-memory grant result is gone. If an account has multiple grants, store a grant map and selected grantId under that account namespace instead of overwriting this record.sessionStorage survives a page refresh but not a tab close. Use encrypted application storage or a protected backend secret store when the session must last longer. Never send the private key to Rhinestone.Rhinestone separately stores public grant metadata so the handle can be recovered from the same account namespace. It cannot recover the private signer.
5

Prepare, sign, and submit

Create a headless client with the same provider, app identity, WebAuthn namespace, and sponsorship callbacks as your embedded wallet client. Reuse your integration’s configuration rather than creating another app registration. The sponsorship import below is the URL or callback configuration already passed to OneAuthClient; export it from your existing integration config.
prepareIntent() fixes the quote and returns the data the session signer must sign. buildSmartSessionHeadlessSignatures() rebuilds the per-chain session-key signatures from the saved handle. submitIntent() forwards those signatures without another passkey dialog, and the onchain validator rejects calls outside the grant.

Try a scoped session

This testnet demo grants a narrower action than the transfer example above: mint 0.1 mUSD to your own account on Base Sepolia, up to 25 times within 24 hours. Grant the permission once, then mint without another passkey prompt. Fees are sponsored, and the session key stays in this tab’s sessionStorage.