<>ts-stack
Get StartedArchitecturePackagesSpecsGuides
⌘K
Reference
Home
Get StartedOverviewInstallChoose your stackKey concepts
ArchitectureOverviewStack layersBEEF (BRC-62)BRC-100 Wallet InterfaceIdentity & AuthConformance pipeline
PackagesOverviewSDKWalletNetworkOverlaysMessagingMiddlewareHelpers
InfrastructureOverviewmessage-box-serveroverlay-serveruhrp-server-basicuhrp-server-cloud-bucketwabwallet-infrachaintracks-server
SpecsOverviewBRC-100 Wallet InterfaceOverlay HTTPMessage-box HTTPAuthsocket (WebSocket)BRC-31 Auth HandshakeBRC-29 Peer PaymentBRC-121 / HTTP 402ARC BroadcastMerkle ServiceStorage AdapterGASP SyncUHRPAir-Gap Optical (BRC-141)
ConformanceOverviewVector catalogTS runnerContributing vectors
GuidesOverviewBuild a wallet-aware appRun an overlay nodePeer-to-peer messagingHTTP 402 payments
ReferenceOverviewBRC indexRepository health
AboutVersioningContributingDoc agentDocumentation sources
Loading…
Edit this page on GitHub
© 2026 BSV Blockchain. ts-stack is open-source.
GitHubContributingVersioning

Wallet Authentication Backend (WAB)

A TypeScript/Express server that provides presentation-key and Shamir-share recovery workflows for BSV wallet applications, using Twilio verification in production and an explicitly development-only console OTP method.

What it does

WAB enables Twilio phone verification and coordinates key/share storage through SQLite (development) or MySQL (production). A Persona example exists in source but is not registered as a supported method. The DevConsole method is available only when explicitly enabled in a development or test runtime and cannot be activated in production or staging.

Clients authenticate by phone number, recover original presentation keys, optionally receive one-time BSV payments, and can verify a same-or-new phone number to rotate the presentation key. Operators can pin a legacy ambiguous UMP account to one verified outpoint and restore recorded phone associations.

When to deploy this

  • BSV wallet applications needing multi-factor user authentication
  • Key recovery using 2-of-3 threshold system (presentation key + password + recovery key)
  • Development/testing with OTP-based console auth
  • Production deployments with Twilio SMS verification
  • Faucet distribution for new users (with SERVER_PRIVATE_KEY and STORAGE_URL)

Dependencies

TypeRequirement
DatabaseSQLite (dev: ./dev.sqlite3) or MySQL (production: DB_CLIENT, DB_USER, DB_PASS, DB_NAME, DB_HOST, DB_PORT)
External servicesTwilio (if TwilioAuthMethod), Wallet Storage (if faucet enabled), ARC (for transaction broadcasting)
ts-stack packages@bsv/sdk, @bsv/wallet-toolbox

HTTP endpoints

MethodPathPurpose
GET/infoServer configuration info
POST/auth/startStart authentication (methodType, presentationKey, payload)
POST/auth/completeComplete authentication (methodType, presentationKey, payload)
POST/auth/phone-change/startVerify current account and send OTP to requested phone
POST/auth/phone-change/completeVerify OTP and issue a ten-minute change token
POST/auth/phone-change/commitStage the verified phone association and replacement key
POST/auth/phone-change/finalizePromote the key after the wallet publishes its UMP rotation
POST/admin/ump-pinSet/clear a support UMP outpoint pin (admin bearer required)
POST/admin/phone-change/restoreRestore recorded phone associations (admin bearer required)
POST/user/linkedMethodsList user's linked auth methods (presentationKey)
POST/user/unlinkMethodUnlink auth method (presentationKey, methodId)
POST/user/deleteDelete user account (presentationKey)
POST/faucet/requestRequest faucet payment (presentationKey)
POST/account/delete/startStart OTP-confirmed account deletion
POST/account/delete/completeComplete account deletion
POST/share/storeOTP-confirmed Shamir share creation
POST/share/retrieveOTP-confirmed Shamir share recovery
POST/share/updateOTP-confirmed Shamir share rotation
POST/share/deleteOTP-confirmed share/account deletion

WebSocket endpoints

None.

Configuration (env vars)

VariableRequiredDescription
NODE_ENVNodevelopment or production
PORTNoHTTP server port (default: 3000)
TWILIO_ACCOUNT_SIDNoTwilio account ID (if using TwilioAuthMethod)
TWILIO_AUTH_TOKENNoTwilio auth token
TWILIO_VERIFY_SERVICE_SIDNoTwilio Verify service ID (VAxxxx or VExxxx)
SERVER_PRIVATE_KEYNo256-bit hex key for faucet transactions
STORAGE_URLNoOverlay services URL for faucet (e.g., wallet storage endpoint)
COMMISSION_FEENoCommission fee in satoshis per faucet request (default: 0)
DB_CLIENTNoDatabase client (default: sqlite3; or mysql2)
DB_USERNoDatabase user (production MySQL)
DB_PASSNoDatabase password
DB_NAMENoDatabase name
DB_HOSTNoDatabase host
DB_PORTNoDatabase port
DB_CONNECTION_NAMENoGCP Cloud SQL connection name (for Cloud SQL with Unix socket)
DEV_CONSOLE_AUTH_METHOD_ENABLEDNoDevelopment/test-only explicit console OTP opt-in
WAB_CORS_MODENopublic (default), allowlist, or disabled
WAB_CORS_ALLOWED_ORIGINSNoExact comma-separated origins for allowlist mode
WAB_CORS_ALLOWED_HEADERSNoStrict comma-separated browser request-header allowlist; omit to accept additive well-formed request headers
WAB_MAX_BODY_BYTESNoJSON body ceiling (default 262144)
WAB_MAX_CONCURRENT_REQUESTSNoPer-process in-flight ceiling (default 200)
WAB_ADMIN_TOKENNoAt least 32 random characters; enables authenticated /admin/* support routes
WAB_ADMIN_RATE_LIMIT_MAXNoAdministrative requests per window (default 30)
WAB_ADMIN_RATE_LIMIT_WINDOW_MSNoAdministrative rate-limit window (default 900000)
TRUST_PROXY_HOPSNoExact trusted proxy hop count, 0 through 10

See Public Service Edge Security for endpoint rate limits, errors, CORS/CSP behavior, and the threat model.

Run locally

bash
# Install dependencies
npm install

# Development with auto-restart
npm run dev

# Database migrations
npm run migrate

# Run tests with coverage
npm test

# Build TypeScript
npm run build

# Run production server
npm start

Uses SQLite by default (./dev.sqlite3); MySQL configured via DB_* env vars.

Deploy to production

bash
# Build Docker image
docker build -t wab-server:latest .

# Run with MySQL backend
docker run -d \
  -e NODE_ENV=production \
  -e DB_CLIENT=mysql2 \
  -e DB_HOST=mysql \
  -e DB_USER=root \
  -e DB_PASS=password \
  -e DB_NAME=wab \
  -e TWILIO_ACCOUNT_SID=<sid> \
  -e TWILIO_AUTH_TOKEN=<token> \
  -e TWILIO_VERIFY_SERVICE_SID=<service-id> \
  -e SERVER_PRIVATE_KEY=<hex-key> \
  -e STORAGE_URL=<overlay-url> \
  -p 3000:3000 \
  wab-server:latest

# Or with GCP Cloud SQL
docker run -d \
  -e DB_CLIENT=mysql2 \
  -e DB_CONNECTION_NAME=project:region:instance \
  -e DB_USER=root \
  -e DB_PASS=password \
  -e DB_NAME=wab \
  ... (other env vars)

# Or via docker-compose with MySQL
docker compose up -d

Migrations

Run Knex migrations for schema initialization:

bash
npm run migrate

Creates the core users, auth-method, payment, share, deletion, and abuse-control tables. The UMP support migration adds nullable users.umpTokenOutpoint plus phone_change_sessions and phone_change_history. Back up the database before rollout. Do not remove the history table after users begin changing numbers.

Health checks

GET /healthz is the liveness endpoint and GET /info is the readiness and configuration endpoint. Monitor:

  • Database connectivity (run npm run migrate to verify)
  • Auth method configuration (Twilio credentials, etc.)
  • POST /auth/start endpoint responds with 200/4xx

Spec conformance

  • BRC-100 – Optional integration with @bsv/wallet-toolbox for faucet R-puzzle transactions
  • 2-of-3 Recovery – Presentation key is factor #1 (password #2, recovery key #3) in XOR-based derivation system

Integration with ts-stack

  • Clients implement AuthMethod subclasses for custom verification flows
  • Wallet Toolbox integration for faucet BSV payments and key derivation
  • WalletAuthenticationManager uses WAB for presentation key authentication
  • UMP (User Management Protocol) token system coordinates with presentation keys
  • A WAB UMP pin is an ambiguity-only fallback and must match a wallet-verified lookup candidate
  • Phone changes verify possession by OTP, stage current/pending keys across the UMP publish boundary, and clear a stale pin at finalization while recording reversible association history
  • See how-it-works.md for detailed 2-of-3 cryptographic recovery explanation
  • See UMP account support for the operator workflow

Common pitfalls

  • User identification by config, not presentation key: Auth method's buildConfigFromPayload() extracts unique identifier (e.g., phone number); two devices with same phone return same user's key
  • Twilio setup critical: TWILIO_VERIFY_SERVICE_SID must be VAxxxx (Verify) or VExxxx (Verify Email); wrong SID causes all auth attempts to fail
  • SQLite for dev only: In-memory tables reset on restart; switch to MySQL for production
  • Faucet requires funds: SERVER_PRIVATE_KEY wallet must have UTXOs; transactions fail if insufficient balance
  • Dev console is ephemeral: its OTP store resets on restart and is intentionally unavailable in production/staging
  • Public CORS is intentional for wallet apps on unknown domains; use WAB_CORS_MODE=allowlist only when the deployment has a closed caller set
  • Migration timing: Must run before server startup; Knex handles schema versioning automatically
  • Support token: /admin/* returns 404 when WAB_ADMIN_TOKEN is absent; a non-empty token shorter than 32 characters fails startup
  • Phone takeover: proving possession of a number can transfer its WAB association; support must preserve and audit the returned changeId so a fraudulent transfer can be restored

Source

  • GitHub
  • npm package