ZKAuth
Get started

Core concepts

Authentication

ZKAuth centers on zero-knowledge password auth. OPAQUE and WebAuthn are exposed as helper surfaces for teams that want to build those browser flows through a server-side proxy.

Zero-knowledge password proofs

The default method. The client turns the password into a zero-knowledge proof and sends only the proof. The engine verifies it with a Groth16 verifier and stores a verifier value, never the password or a reversible hash of it.

ts
// The client derives the proof locally; the server only verifies it.await zkauth.register({ email, password, deviceInfo })const session = await zkauth.login({ email, password, deviceInfo })

Each attempt includes deviceInfo so the engine can bind the proof to a device and apply replay protection. A tampered or replayed proof is rejected.

Project-bound hosted sign-up/sign-in helper pages use the same proof boundary through the hosted proxy. They can register accounts and verify engine login without exposing project API keys.

  • After engine sign-in, hosted UI can return a single-use handoff code to an allowlisted callback for server-side redemption.
  • The hosted account security helper can use the in-memory bearer token for account and security controls.

OPAQUE helpers

OPAQUE is a password-authenticated key exchange (PAKE). The server stores an opaque credential it cannot use to recover the password, even offline.

Because OPAQUE runs in the browser, route its steps through a backend proxy so your project key stays server-side.

route.tsts
// app/api/zkauth/opaque/[...path]/route.ts (your backend)// Forwards browser OPAQUE steps to the engine with your project key,// so the key is never exposed to client code.export const POST = (req: Request) =>  fetch(`${loadServerOnlyApiBaseUrl()}/api/v1/opaque/${path}`, {    method: 'POST',    headers: { 'x-api-key': loadServerOnlyProjectKey(), 'content-type': 'application/json' },    body: await req.text(),  })

Built-in proxy

The dashboard ships authenticated proxy routes at /api/zkauth/opaque/[...path] and /api/zkauth/webauthn/[...path] as a working reference for this pattern.

WebAuthn helper flows

The engine issues registration and authentication options, and verifies the authenticator’s response.

  • Ceremonies require the relying-party ID and origin to match the domain serving them.
  • Treat this as a helper surface, not a broad hardware compatibility guarantee.

ZKAuth also has a hosted passkey verification helper for credentials registered on the hosted WebAuthn origin. Use your own backend proxy for passkeys registered on your application domain.

bash
# Engine configuration for passkey ceremoniesWEBAUTHN_RP_ID=your-app-domain.comWEBAUTHN_ORIGIN=https://your-app-domain.com

Origin must match

Passkey ceremonies fail if WEBAUTHN_RP_ID / WEBAUTHN_ORIGINdon’t match the domain the browser flow runs on. Configure them per environment.

Sessions

A successful login returns a bearer session token. Keep it server-side when you can, read the current user and session metadata through /auth/me, rotate active tokens with /auth/refresh, and revoke the current token with logout.

ts
const res = await zkauth.login({ email, password, deviceInfo })
// The token is on the instance; also store it in an http-only, secure cookie.const token = res.data.session.tokenconst current = await zkauth.getCurrentUser()await zkauth.logout() // revokes the current session

Session listing lives under /security/sessions and includes device, last-activity, expiry, MFA, and sensitive-session metadata. Account stats and recent login activity are available through bearer dashboard endpoints and are used by the hosted account helper.

Terminating all other sessions keeps the current session active, and the engine requires a fresh first-factor session for that account-wide action. Use logout to revoke the current one.

Replay protection & trusted devices

  • Proof freshness: each proof is single-use; replays are rejected on the hot path.
  • Tamper rejection: modified proofs fail verification.
  • Trusted devices: deviceInfo registers a device fingerprint; mismatches can be challenged with separate single-use approval and denial links.

For the exact guarantees and the boundaries we don’t cross, read Security and Limitations.