Skip to main content
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.

How SIWE Works

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.
SIWE authentication flow

Provisioning During Sign-In

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.
const tc = new TinyCloudWeb({
  manifest: {
    app_id: 'com.example.encrypted-app',
    name: 'Encrypted App',
    defaults: false,
    permissions: [
      {
        service: 'tinycloud.encryption',
        path: 'urn:tinycloud:encryption:did:pkh:eip155:1:0x1234...abcd:default',
        actions: ['decrypt'],
      },
    ],
  },
});

await tc.signIn(); // Ensures the owner-owned encryption network exists

Web SDK Sign-In

Calling signIn() in the browser triggers the wallet popup for the user to approve.
import { TinyCloudWeb } from '@tinycloud/web-sdk';

const tc = new TinyCloudWeb({
  notifications: { popups: true },
  persistSession: true,
});

const session = await tc.signIn();
console.log('Signed in:', session.address);
console.log('Space:', tc.spaceId);

Web SDK Configuration Reference

OptionTypeDefaultDescription
tinycloudHostsstring[]['https://node.tinycloud.xyz']TinyCloud node endpoints
spacePrefixstring''Prefix for space ID derivation
autoCreateSpacebooleantrueCreate space on first sign-in
kvPrefixstring''Prefix prepended to all KV keys
persistSessionbooleantruePersist session data in browser storage. Set false to disable.
sessionStorageISessionStorageBrowserSessionStorageCustom storage backend for persisted sessions
sessionStorageKeyPrefixstring'tinycloud:session:'Prefix used for persisted session keys
sessionExpirationMsnumber604800000 (7d)Requested session TTL in milliseconds

Node SDK Sign-In

The Node SDK signs the SIWE message automatically using the provided private key — no user interaction required.
import { TinyCloudNode } from '@tinycloud/node-sdk';

const tc = new TinyCloudNode({
  privateKey: process.env.WALLET_PRIVATE_KEY,
  host: 'https://node.tinycloud.xyz',
  prefix: 'my-app',
});

await tc.signIn();
console.log('Signed in:', tc.spaceId);

Node SDK Configuration Reference

OptionTypeDefaultDescription
privateKeystring-Ethereum private key (hex). Omit for session-only mode.
hoststring'https://node.tinycloud.xyz'TinyCloud node endpoint
prefixstring''Prefix for space ID derivation
autoCreateSpacebooleantrueCreate space on first sign-in
sessionExpirationMsnumber604800000 (7d)Session TTL in milliseconds
Never hardcode private keys in source code. Always use environment variables or a secrets manager.

Session-Only Mode (Node SDK)

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 mode
const 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 delegations
const 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.

Session Persistence

Sessions can be persisted so users do not need to re-authenticate on every page reload or process restart.
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:
const restored = await tc.restoreSession();

if (restored.status === 'restored') {
  console.log('Session restored');
} else {
  await tc.signIn(); // Fresh sign-in required
}

Session Expiry

Sessions have a limited lifetime. When a session expires, operations will fail and the user must re-authenticate.
// Configure expiry duration
const 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.

Sign Out

Clear the current session and remove persisted credentials.
await tc.signOut();
// Session cleared from localStorage/sessionStorage/memory
After signing out, all operations will fail until a new signIn() is completed. Persisted sessions are deleted permanently.

Complete Example

A full authentication flow with session persistence and expiry handling:
import { BrowserSessionStorage, TinyCloudWeb } from '@tinycloud/web-sdk';

const tc = new TinyCloudWeb({
  tinycloudHosts: ['https://node.tinycloud.xyz'],
  spacePrefix: 'my-app',
  autoCreateSpace: true,
  notifications: { popups: true },
  persistSession: true,
  sessionStorage: new BrowserSessionStorage({ storage: globalThis.localStorage }),
  sessionStorageKeyPrefix: 'my-app',
});

async function ensureAuthenticated() {
  // Try to resume an existing session first
  const restored = await tc.restoreSession();

  if (restored.status !== 'restored') {
    // No valid session -- trigger wallet sign-in
    await tc.signIn();
  }

  console.log('Space:', tc.spaceId);
}

async function handleSignOut() {
  await tc.signOut();
  console.log('Signed out');
}