ZKAuth
Get started

Guides

Examples

Patterns you can adapt. The rule across all of them: the API key and session token live on the server; the browser talks to your backend or a ZKAuth-hosted proxy that injects project keys server-side.

Server-side keys only

The framework packages verify sessions and API keys from trusted server code. React components must call app-owned proxy routes, and hosted browser flows must use hosted proxy mode. Never pass a project API key to browser code.

Next.js: protect a route handler

Use @zkauth/nextjs for App Router route handlers, Server Components, Server Actions, and proxy redirects.

app/api/private/route.tsts
// app/api/private/route.tsimport { withRouteAuth } from '@zkauth/nextjs'
export const GET = withRouteAuth(async (_request, _context, auth) => {  return Response.json({    userId: auth.user.id,    email: auth.user.email,  })})

React: provider and components

Use @zkauth/react against your own proxy endpoints. The package does not accept or send project API keys.

auth-panel.tsxtsx
'use client'import { SignIn, UserButton, ZKAuthProvider } from '@zkauth/react'
export function AuthPanel() {  return (    <ZKAuthProvider apiBasePath="/api/zkauth">      <UserButton />      <SignIn />    </ZKAuthProvider>  )}

Express: protect a route

Use @zkauth/express to verify bearer tokens or thezkauth_session cookie and attach typed auth state to the request.

server.tsts
import express from 'express'import { createZKAuthExpress } from '@zkauth/express'
const app = express()const auth = createZKAuthExpress({  apiKey: loadServerOnlyProjectKey(),  baseUrl: loadServerOnlyApiBaseUrl(),})
app.get('/api/profile', auth.requireAuth(), (req, res) => {  res.json({ user: req.zkauth?.session?.user })})

Hono: protect an edge route

Use @zkauth/hono in Web-standard runtimes and read auth state from the Hono context.

app.tsts
import { Hono } from 'hono'import {  createZKAuthHono,  getZKAuth,  type ZKAuthHonoVariables,} from '@zkauth/hono'
const app = new Hono<{ Variables: ZKAuthHonoVariables }>()const auth = createZKAuthHono({  apiKey: loadServerOnlyProjectKey(),  baseUrl: loadServerOnlyApiBaseUrl(),})
app.get('/api/profile', auth.requireAuth(), (c) => {  return c.json({ user: getZKAuth(c)?.session?.user })})

Other languages

For stacks without a first-class package, use the HTTPS API with a server-side x-api-key header. See the API reference for the request and response shapes.