ZKAuth
Get started

Get started

Your first verified login

Six steps to create a project and complete an experimental Proof V2 registration and login. For production-oriented authentication, begin with the hosted passkey path in Installation.

1. Create a project

Sign in to the dashboard and create a project. Each project provisions its own client on the ZKAuth engine, isolated from every other project.

Create your account ->

2. Copy your API keys

Every project ships with two keys. Use the test key while you build and the live key in production. Both are scoped to that one project and can be rotated at any time.

During setup, add your primary callback URL and exact browser origins. Callback URLs include the path users return to after email/device links; browser origins are only scheme, host, and optional port.

  • zka_test_... for local development and CI.
  • zka_live_... for production traffic.
.env.localbash
# server-only runtime configZKAUTH_API_KEY=zka_test_...ZKAUTH_BASE_URL=https://api.zkauth.dev

Keep keys server-side

Treat keys like secrets. Production applications should put keys behind trusted server code, your own narrow backend proxy, or ZKAuth hosted proxy mode. Never commit keys or ship live keys inside a public bundle.

3. Install the client

The published 2.0 beta wraps the Proof V2 handshake. Do not hand-roll the circuit witness, public-signal ordering, or artifact selection. Proof V2 still requires explicit matching development artifacts and is not production approved.

bash
npm install zkauth-client@beta
lib/zkauth.tsts
import { ZKAuthSDK } from 'zkauth-client'
const proofLabArtifacts = {  wasm: 'http://127.0.0.1:4173/auth_v2.wasm',  zkey: 'http://127.0.0.1:4173/auth_v2.dev-0000.zkey',}
export const zkauth = new ZKAuthSDK({  apiKey: loadServerOnlyProjectKey(),  baseUrl: loadServerOnlyApiBaseUrl(),  experimentalProofV2Artifacts: proofLabArtifacts,})

Browser-hosted flows can initialize with project slug and public client ID instead of a project API key:

browser-auth.tsts
import { ZKAuthSDK } from 'zkauth-client'
const proofLabArtifacts = {  wasm: 'http://127.0.0.1:4173/auth_v2.wasm',  zkey: 'http://127.0.0.1:4173/auth_v2.dev-0000.zkey',}
export const zkauth = new ZKAuthSDK({  hostedProxy: {    projectSlug: 'your-project-slug',    clientId: 'your_public_client_id',  },  experimentalProofV2Artifacts: proofLabArtifacts,})

4. Register a user

On registration the client derives a password-based commitment on the device and sends the salt plus commitment. The engine stores that verifier material, never the password.

ts
const result = await zkauth.register({  email: 'ada@example.com',  password: 'SecurePassword123!',  deviceInfo: { deviceName: 'Chrome on Mac', deviceType: 'desktop' },})
console.log('created user', result.data.userId)

5. Log in and verify

Login requests a server ceremony: the engine checks the exact proof context, atomically consumes the ceremony, and returns a session.

ts
const res = await zkauth.login({  email: 'ada@example.com',  password: 'SecurePassword123!',  deviceInfo: { deviceName: 'Chrome on Mac', deviceType: 'desktop' },})
// The server verified a proof, never the password.console.log('session for', res.data.user.email)const token = res.data.session.token

Proof V2 Lab only

This walkthrough uses zero-contribution development proving keys. Keep password-proof login disabled in production until independent cryptographic review and a production phase-2 ceremony are complete. Prefer passkeys for primary production authentication.

6. Handle email and device gates

Registration sends a verification email, and login must stay blocked until the address is verified.

If the same user logs in from a new device, the engine returns a device-approval response and sends a separate approval email instead of silently trusting the device.

  • Your app should show a clear "check your email" state after registration.
  • Device approval and denial links are separate single-use decisions. Once one link succeeds, the other can no longer change the request.
  • Your callback URL should handle zkauth_action values for email verification, device approval/denial, and password reset.
  • If no safe callback is configured, ZKAuth shows hosted fallback pages instead of redirecting to an unknown URL.
  • Browser origins should stay exact, with no paths or wildcards, so preview and production domains are auditable separately.

Hosted helper pages

If you would rather not build these screens yourself, hosted sign-up/sign-in and hosted forgot-password/reset pages run through the project-bound hosted proxy, so project API keys never reach the browser.

  • Hosted sign-in verifies the engine login and can return a single-use handoff code to an allowlisted callback. Your backend redeems that code with the project API key and creates the app session cookie, so bearer tokens stay out of callback URLs.
  • The account security helper keeps the engine bearer token in memory and covers profile, account stats, recent activity, sessions, devices, and recovery.
  • It also handles shown-once recovery-code export, TOTP setup/reset, MFA disable, and recent-sign-in-guarded hosted-origin passkey registration, inventory, and revocation.
  • Terminating other active sessions stays fresh-session guarded, so the engine must confirm a recent first-factor session before it runs.

Where to next