Sign in with Ethereum and manage sessions across Web and Node SDKs
TinyCloud uses Sign-In with Ethereum (SIWE) for authentication. Users prove wallet ownership to establish sessions that authorize access to their space.OpenKey can supply the signer for this SIWE flow in TinyCloud, but OpenKey OAuth is a separate token-based integration. If you are connecting OpenKey to TinyCloud, see TinyCloud Integration.
The authentication flow follows three steps regardless of which SDK you use:
1
Connect wallet
The user connects their Ethereum wallet. In the browser, this triggers a popup (MetaMask, WalletConnect, etc.). In Node.js, the SDK derives the address from the provided private key.
2
Sign SIWE message
The SDK constructs a SIWE message containing the domain, address, chain ID, and requested capabilities (via ReCap). The user (or private key) signs this message to prove ownership.
3
Session established
TinyCloud verifies the signature, creates the user’s space if needed, and issues a session. The session key can perform operations on behalf of the user until it expires.
TinyCloud’s default nonce behavior is sufficient when no relying-party challenge is needed. If you need to verify a nonce in your own auth flow, issue a one-time nonce from your server and pass that through the request. Do not generate nonces in the browser.
With autoCreateSpace: true, SDK sign-in creates the user’s TinyCloud space if
it does not already exist.Encryption networks are provisioned the same way when they are part of the
signed capability request. If a manifest or capabilityRequest includes
tinycloud.encryption/decrypt for a network owned by the signing DID, the SDK
adds a separate tinycloud.encryption/network.create grant to the SIWE ReCap
request. After the session is established, it calls
ensureEncryptionNetwork() for the requested owner-owned network and creates
the network if it is missing.This automatic creation only applies to encryption network IDs owned by the
signed-in user. For a network owned by another DID, the SDK keeps the decrypt
grant but does not request network.create or attempt creation.
import { TinyCloudWeb } from '@tinycloud/web-sdk';// Create an instance with full configurationconst tc = new TinyCloudWeb({ // TinyCloud node(s) to connect to tinycloudHosts: ['https://node.tinycloud.xyz'], // Prefix for space isolation (different prefixes = different spaces) spacePrefix: 'my-app', // Automatically create the space on first sign-in autoCreateSpace: true, // Prefix for all KV keys (optional, for further key isolation) kvPrefix: '', // Show popup notifications for sign-in events notifications: { popups: true }, // Persist the session in browser storage persistSession: true, // Prefix for browser storage keys sessionStorageKeyPrefix: 'my-app',});// Triggers the wallet popup:// 1. Wallet connection prompt (select account)// 2. SIWE message signature promptconst session = await tc.signIn();console.log('Signed in as:', session.address);
You can create a TinyCloudNode instance without a private key. This creates a session-only client that cannot sign in on its own but can receive delegations from other users.
import { TinyCloudNode } from '@tinycloud/node-sdk';// No privateKey -- session-only modeconst tc = new TinyCloudNode({ host: 'https://node.tinycloud.xyz',});// tc.signIn() would fail -- no private key to sign with// But this client can receive and use delegationsconst access = await tc.useDelegation(portableDelegation);const result = await access.kv.get('shared/document');
Session-only mode is useful for services that only need to read delegated data, such as a read-only dashboard or a webhook consumer.
Sessions can be persisted so users do not need to re-authenticate on every page reload or process restart.
Web SDK
Node SDK
The Web SDK supports three storage backends:
import { BrowserSessionStorage, TinyCloudWeb } from '@tinycloud/web-sdk';const tc = new TinyCloudWeb({ persistSession: true, // Use sessionStorage if the session should clear when the tab closes. sessionStorage: new BrowserSessionStorage({ storage: globalThis.sessionStorage }), sessionStorageKeyPrefix: 'my-app',});// On subsequent page loads, restore a valid persisted session.const restored = await tc.restoreSession();if (restored.status === 'restored') { console.log('Session restored:', restored.session.address);}
You can also manually check for an existing session:
The Node SDK provides two session storage implementations:
import { TinyCloudNode, FileSessionStorage } from '@tinycloud/node-sdk';// Persists session to disk -- survives process restartsconst tc = new TinyCloudNode({ privateKey: process.env.WALLET_PRIVATE_KEY, sessionStorage: new FileSessionStorage('./session.json'),});await tc.signIn();// Session saved to ./session.json// On next startup, signIn() reuses the persisted session if still valid
FileSessionStorage is recommended for production services. MemorySessionStorage is the default if no storage is specified.
Sessions have a limited lifetime. When a session expires, operations will fail and the user must re-authenticate.
// Configure expiry durationconst tc = new TinyCloudWeb({ persistSession: true, sessionExpirationMs: 24 * 60 * 60 * 1000, // 24 hours});// Restore a persisted session if it is still valid.const restored = await tc.restoreSession();if (restored.status !== 'restored') { await tc.signIn(); // Re-authenticate}
For long-running Node.js services, use FileSessionStorage and check operation Result objects for auth expiry so you can re-authenticate and retry when needed.