Skip to content

GoPlausible/liquid-auth-cloud

Repository files navigation

Liquid Auth Cloud

@goplausible/liquid-auth-cloud

Liquid Auth on Cloudflare Workers — passwordless FIDO2/WebAuthn authentication with Algorand wallet binding, deployed to the edge with zero idle cost.

Built by GoPlausible, inspired by the Algorand Foundation's Liquid Auth reference server. A ground-up reimplementation that replaces NestJS + MongoDB + Redis + Docker with Cloudflare Workers + KV + Durable Objects — lighter, more scalable, cloud-native, and serverless.

Live deployment: https://liquidauth.goplausible.xyz

Related Projects

Project Package / App Description
Liquid Auth Client (TypeScript) @goplausible/liquid-client Browser client — native WebSocket, FIDO2 + WebRTC signaling
Liquid Auth Android Android wallet app FIDO2 + WebRTC with native OkHttp WebSocket
Regent Wallet React Native / Expo app Cross-platform wallet — FIDO2 passkeys + WebRTC
WebRTC Payment SDK @goplausible/webrtc-payment-sdk Used in — micropayment-gated WebRTC streams on Algorand

What Makes This Different

Concern Original (NestJS) This (Cloudflare Workers)
Runtime Node.js + Express + Docker Cloudflare Worker (V8 isolate)
User storage MongoDB Workers KV
Sessions MongoDB + connect-mongo Durable Object with HMAC-SHA256 signing
WebSocket Redis + Socket.io Durable Objects + native WebSocket
Crypto Node.js crypto tweetnacl + Node crypto (nodejs_compat)
Static assets Express static Worker assets + R2 bucket
Deployment Docker / VM wrangler deploy
Scaling Manual / load balancer Automatic edge scaling, 300+ PoPs
Idle cost Server always running Zero (pay per request)

Key design choices:

  • No Socket.io — native WebSocket with { event, data } JSON protocol, designed for Durable Object Hibernation API
  • Room routing via URL/ws?requestId=xxx puts both peers in the same DO instance without room-join handshakes
  • Dual room broadcast — auth events go to both the wallet room and the requestId room so the offer peer always receives them
  • Discoverable assertions — supports passwordless sign-in without knowing the credential ID (synced passkeys across devices)
  • Proper SHA-512/256 — Algorand address checksums use real SHA-512/256 via Node crypto, not truncated SHA-512

How It Works

  Wallet (FIDO2)                  Cloudflare Edge                    Browser/Dapp
  ==============           =========================          ==================

  1. Scan QR code  ------>     Worker receives request
                               KV stores challenge
                               Returns attestation options

  2. Sign with passkey ----->  Worker verifies attestation
                               KV stores user + credential
                               DO broadcasts auth event
                                         |
                                         v
                               WalletRoom Durable Object -------> WebSocket push
                               (per-requestId signaling room)     "link" event

  3. WebRTC signaling  <-----> DO relays offer/answer  <-------> WebRTC signaling
     (offer/answer/ICE)        candidates between peers          (offer/answer/ICE)

  4. DataChannel opens <======= encrypted P2P ==================> DataChannel opens

Getting Started

Prerequisites

  • Node.js >= 18, npm
  • Wrangler CLI (npm install -g wrangler)
  • A Cloudflare account

Local Development

# From the monorepo root
npm install
npm run dev:cloud         # Starts at http://localhost:8787

Deploy

npm run deploy:cloud

Configuration

Update wrangler.toml:

[vars]
RP_NAME = "Your App Name"
HOSTNAME = "auth.yourdomain.com"
ORIGIN = "https://auth.yourdomain.com"
ANDROID_ORIGINS = "android:apk-key-hash:<YOUR_APK_KEY_HASH>"
SESSION_TTL = "300"

Set secrets:

wrangler secret put SESSION_SECRET

Routes

Pages

Route Description
GET / Demo page — offer side, QR codes, messaging
GET /wallet?requestId=xxx Web wallet — mobile-optimized answer side
GET /.well-known/assetlinks.json Android FIDO2 Digital Asset Links
GET /download/:key Serve files from R2 (APK, assets)
GET /favicon.ico Served from Worker static assets

FIDO2 Registration (Attestation)

Route Description
POST /attestation/request Get WebAuthn registration options
POST /attestation/response Submit signed attestation with Liquid extension

FIDO2 Authentication (Assertion)

Route Description
POST /assertion/request Discoverable assertion (no credId — synced passkeys)
POST /assertion/request/:credId Assertion for a specific credential
POST /assertion/response Submit signed assertion

Session Management

Route Description
GET /auth/session Current session and user info
GET /auth/user Authenticated user (401 if not logged in)
DELETE /auth/keys/:credId Remove a credential
GET /auth/logout Destroy session, redirect to /

WebSocket Signaling

const ws = new WebSocket(`wss://auth.yourdomain.com/ws?requestId=${requestId}`);

// All messages use { event, data } JSON envelope
ws.send(JSON.stringify({ event: "link", data: { requestId } }));

ws.onmessage = (e) => {
  const { event, data } = JSON.parse(e.data);
  // event: link | offer-description | offer-candidate | answer-description | answer-candidate
};

Project Structure

src/
  index.ts          Entry point, routing, CORS, session cookies
  types.ts          Env bindings, StoredUser, StoredSession, events
  encoding.ts       Base64URL, Base32, SHA-512/256, Algorand address codec
  kv.ts             KV storage layer (users, credentials)
  session.ts        Session utilities (HMAC-signed cookies)
  session-store.ts  SessionStore Durable Object
  fido2.ts          FIDO2 attestation/assertion, Liquid extension verification
  wallet-room.ts    WalletRoom Durable Object (WebSocket signaling)
  routes.ts         HTTP route handlers
  demo.ts           Demo page HTML
  wallet.ts         Web wallet page HTML
public/
  favicon.ico       Static asset

Security

  • No private keys on server — all Algorand signing happens on the client device
  • FIDO2 user verification required — all operations require biometric/PIN
  • Proper SHA-512/256 — Algorand address checksums use the correct algorithm (not truncated SHA-512)
  • Rekeyed account support — checks on-chain auth-addr on both mainnet and testnet
  • Cross-platform origins — FIDO2 origin validation includes both web and Android origins
  • HMAC-SHA256 sessions — stored in Durable Object, signed cookies, automatic TTL expiry
  • HttpOnly + Secure + SameSite=None cookies
  • No workers.dev URL — custom domain only, workers_dev and preview_urls disabled
  • Secrets encrypted at restSESSION_SECRET set via wrangler secret put

Documentation

  • Architecture — component design, data flow, migration mapping
  • Sequence Diagrams — registration, authentication, WebSocket, session flows
  • Vision — why edge deployment, principles, design decisions
  • Contributing — development setup and guidelines

License

MIT — see LICENSE.

About

This is a redesigned and revamped version of Algorand Foundation Liquid Auth for cloud and edge implementations instead of relying on server or docker environments

Resources

License

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors