Core concepts

Authentication

ZKAuth offers three credential methods. They share one principle: the server verifies that a user knows their secret without ever receiving it. Use one, or combine them.

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.

OPAQUE

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(`${process.env.ZKAUTH_BASE_URL}/api/v1/opaque/${path}`, {    method: 'POST',    headers: { 'x-api-key': process.env.ZKAUTH_API_KEY!, '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 passkeys

Hardware- and platform-backed passkeys via WebAuthn. 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.

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 session token. Send it as a bearer token on user routes, read the current user, and invalidate it on 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 user = await zkauth.getCurrentUser()await zkauth.logout()

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 or denied.

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