accounts
Version:
Tempo Accounts SDK
180 lines • 8.42 kB
TypeScript
import { Hex } from 'ox';
import type { Address, Transport } from 'viem';
import * as z from 'zod/mini';
import { type Handler, from } from '../../Handler.js';
import * as Kv from '../../Kv.js';
import * as Session from './session.js';
/**
* Session payload persisted in the session store and surfaced via
* `getSession`. `address` is the account address that signed the
* authentication challenge; `chainId` is the chain echoed in the message.
*/
export type SessionPayload = {
/** Address of the account. */
address: Address;
/** Chain ID echoed into the challenge message. */
chainId: number;
/** Unix timestamp (seconds) when the session was issued. */
issuedAt: number;
/** Unix timestamp (seconds) when the session expires. */
expiresAt: number;
};
/** Zod schemas for the auth handler's request and response payloads. */
export declare namespace schema {
/** Schemas for `POST {path}/challenge`. */
namespace challenge {
/** Request body schema. */
const parameters: z.ZodMiniObject<{
chainId: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
}, z.core.$strip>;
/** Response body schema. */
const returns: z.ZodMiniObject<{
message: z.ZodMiniString<string>;
}, z.core.$strip>;
}
/** Schemas for `POST {path}` (verify). */
namespace verify {
/** Request body schema. */
const parameters: z.ZodMiniObject<{
address: z.ZodMiniTemplateLiteral<`0x${string}`>;
message: z.ZodMiniString<string>;
signature: z.ZodMiniTemplateLiteral<`0x${string}`>;
/**
* When `true`, the server returns the issued session token in the
* response body as `{ token }` and does NOT set a session cookie.
* The caller is responsible for sending it as
* `Authorization: Bearer <token>` on subsequent requests.
*/
returnToken: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
}, z.core.$strip>;
/** Response body schema. */
const returns: z.ZodMiniObject<{
token: z.ZodMiniOptional<z.ZodMiniString<string>>;
}, z.core.$strip>;
}
}
/**
* Server Authentication request handler. Mounts three routes under `path`:
*
* - `POST {path}/challenge` → `{ message }`
* - `POST {path}` → verify and issue a session (cookie via `Set-Cookie`)
* - `POST {path}/logout` → clear the session cookie
*
* The returned handler also exposes `getSession(req)` for resolving the
* current session from a follow-up request's cookie.
*
* The challenge message is wire-formatted as EIP-4361 (SIWE) for ecosystem
* compatibility, but address binding is deferred: the SDK can fold the
* challenge digest into the connect ceremony before the account knows
* which address it will sign with. The wallet supplies the real address at
* verify time and the server uses it as the session subject.
*/
export declare function auth(options?: auth.Options): auth.ReturnType;
export declare namespace auth {
/** Return type of `auth()` — a `Handler` extended with `getSession`. */
type ReturnType = Handler & {
getSession: getSession;
};
/** Resolves the current session from a request's cookie or bearer token. */
type getSession = (req: Session.SessionRequest) => Promise<SessionPayload | undefined>;
/**
* Hook invoked after a SIWE signature is verified but before the
* session token is issued. Returning a `Response` merges its JSON
* body and status onto the verify response. Throwing rejects with
* `401` — the thrown error's `message` is surfaced as the response
* `error` field — and no session is issued.
*/
type onAuthenticate = (params: {
/** Verified address that signed the SIWE message. */
address: Address;
/** Chain ID parsed from the SIWE message. */
chainId: number;
/** Verbatim SIWE message that was signed. */
message: string;
/** Underlying request — useful for headers, IP, etc. */
request: Request;
/** Signature provided by the wallet. */
signature: Hex.Hex;
}) => Response | Promise<Response> | void | Promise<void>;
type Options = from.Options & {
/**
* Whether to issue a session cookie on successful verify. When
* `false`, the verify response always contains `{ token }` in the
* body (the per-request `returnToken` flag is ignored), no
* `Set-Cookie` header is sent, logout does not clear a cookie, and
* `getSession` ignores any incoming cookie — only
* `Authorization: Bearer <token>` is honored. Use this when the SDK
* lives in a non-browser context (CLI, server-to-server) or when
* the host app already manages auth cookies.
* @default true
*/
cookie?: boolean | undefined;
/** Cookie name for the session token. @default "accounts_auth" */
cookieName?: string | undefined;
/** Domain echoed into challenge messages. @default request `Host` header */
domain?: string | undefined;
/**
* Hook invoked after the SIWE signature is verified but before the
* session token is issued. Use to provision a user record, emit
* analytics, or apply application-level allow/deny rules. Throwing
* from this hook rejects the request with `401` and the thrown
* error's `message` is surfaced as the response `error` field.
*/
onAuthenticate?: onAuthenticate | undefined;
/** Path prefix for the auth endpoints. @default "/" */
path?: string | undefined;
/**
* Pinned canonical public origin (e.g. `'https://app.example.com'`).
* When set, the SIWE `domain` and `uri`, and the cookie `Secure` flag,
* are derived from this URL — request `Host`, request URL, and
* `x-forwarded-*` headers are ignored. This is the recommended setting
* for production deployments behind a CDN or reverse proxy: it
* prevents a spoofed `x-forwarded-host` from shifting the SIWE domain
* and a spoofed `x-forwarded-proto: http` from disabling `Secure`.
*/
origin?: string | undefined;
/**
* Whether to issue a session on successful verify. When `false`,
* verify acts as a stateless signature check — no token is generated,
* no entry is written to the session store, and no cookie is sent.
* The verify response is `{}`. `getSession` always returns
* `undefined` and `/logout` is a no-op (still returns `204`). Use
* this when the host application mints its own session token (e.g.
* a JWT inside `onAuthenticate`).
* @default true
*/
session?: boolean | undefined;
/**
* Backing store for both single-use challenges (nonces) and issued
* sessions. Keys are namespaced internally (`challenge:…`, `session:…`).
* @default `Kv.memory()`
*/
store?: Kv.Kv | undefined;
/**
* Viem transport for the Tempo client used to verify signatures. The
* client is always built against the `tempo` chain — Tempo's
* `chain.verifyHash` natively understands `SignatureEnvelope` and
* falls back to ECDSA recovery for plain EOAs.
* @default `http()`
*/
transport?: Transport | undefined;
/**
* Honor `x-forwarded-proto` / `x-forwarded-host` to derive the public
* origin. Required when running behind a trusted reverse proxy that
* terminates TLS (OrbStack on `*.tempo.local`, a CDN, etc.). When
* `false`, forwarded headers are ignored to prevent spoofing on
* deployments that expose the origin server directly. Ignored when
* `origin` is set.
* @default `true` on Cloudflare Workers (always edge-fronted), `false` elsewhere.
*/
trustProxy?: boolean | undefined;
/** TTLs in seconds. */
ttl?: {
/** Challenge (nonce) TTL. @default 600 (10m) */
challenge?: number | undefined;
/** Session TTL. @default 86400 (24h) */
session?: number | undefined;
} | undefined;
};
}
//# sourceMappingURL=auth.d.ts.map