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.
// 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.
// 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(), })/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.
# Engine configuration for passkey ceremoniesWEBAUTHN_RP_ID=your-app-domain.comWEBAUTHN_ORIGIN=https://your-app-domain.comWEBAUTHN_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.
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:
deviceInforegisters a device fingerprint; mismatches can be challenged or denied.
For the exact guarantees and the boundaries we don’t cross, read Security.