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.
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.
# server-only runtime configZKAUTH_API_KEY=zka_test_...ZKAUTH_BASE_URL=https://api.zkauth.devKeep keys server-side
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.
npm install zkauth-client@betaimport { 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:
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.
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.
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.tokenProof V2 Lab only
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_actionvalues 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
- Authentication: choose between ZK proofs, OPAQUE, and passkeys.
- API reference: the raw HTTPS contract behind the client.
- Deployment: promote from test keys to live traffic.