Quick start
The fastest path from zero to a working auth backend. Takes about 5 minutes.
What you need
- Docker
- A terminal
1. Run IdentSphere + Postgres
# Postgres
docker run -d --name identsphere-pg \
-e POSTGRES_USER=IdentSphere -e POSTGRES_PASSWORD=demo -e POSTGRES_DB=IdentSphere \
-p 5432:5432 postgres:16-alpine
# IdentSphere server
docker run -d --name identsphere \
-p 4000:4000 \
-e DATABASE_URL=postgres://IdentSphere:demo@host.docker.internal:5432/IdentSphere \
-e IDENTSPHERE_JWT_SECRET=$(openssl rand -base64 48) \
-e IDENTSPHERE_APP_NAME="My App" \
-e IDENTSPHERE_PUBLIC_BASE_URL=http://localhost:5173 \
-e IDENTSPHERE_FROM_EMAIL=demo@example.com \
ghcr.io/identsphere/server
On startup, IdentSphere runs all pending migrations against the database. Subsequent boots see no pending migrations and start instantly.
2. Verify with curl
# Register
curl -s http://localhost:4000/v1/auth/register \
-H 'Content-Type: application/json' \
-d '{
"email": "alice@example.com",
"password": "correcthorsebattery",
"organization_name": "Acme",
"display_name": "Alice"
}' | jq
# Login
curl -s -c cookies.txt http://localhost:4000/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"alice@example.com","password":"correcthorsebattery"}' | jq
# Current session
curl -s -b cookies.txt http://localhost:4000/v1/auth/session | jq
You should see:
register: 201 with aSuccesspayload (access token + user + capabilities)login: 200 with the same shape/session: 200 with the user + computed capabilities
3. Wire up your frontend
Pick your stack:
React (recommended — typed hooks ship in @identsphere/react)
npm install @identsphere/react @tanstack/react-query
import { AuthProvider, useSession, useLogin } from "@identsphere/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<AuthProvider config={{ apiBaseUrl: "http://localhost:4000" }}>
<YourApp />
</AuthProvider>
</QueryClientProvider>
);
}
function SignIn() {
const login = useLogin();
return (
<form onSubmit={async (e) => {
e.preventDefault();
const fd = new FormData(e.currentTarget);
await login.mutateAsync({
email: fd.get("email") as string,
password: fd.get("password") as string,
});
}}>
<input name="email" type="email" />
<input name="password" type="password" />
<button>Sign in</button>
</form>
);
}
Any other language
IdentSphere is pure REST + standard JWTs. Your backend in Python / Go / Node / Ruby
/ Java validates tokens against /v1/auth/jwks.json using any JWT library in
that language.
See Python, Go, Node, or REST overview.
4. Wire up email
The Docker image above uses LogOnlySender — verification + reset emails print
to stdout. For real email, set:
IDENTSPHERE_EMAIL_BACKEND=smtp
SMTP_HOST=smtp.resend.com
SMTP_USERNAME=resend
SMTP_PASSWORD=<your-key>
Supported backends:
log(default)smtp(works with any provider: SES, Postmark, Mailgun, Resend, etc.)resend(native Resend API, behind theresendcargo feature)
See Configuration → Providers.
5. Production checklist
Before going live:
-
IDENTSPHERE_COOKIES_SECURE=true(requires HTTPS) -
IDENTSPHERE_JWT_SECRETfrom a real secret manager - Use RS256 (
IDENTSPHERE_RSA_PRIVATE_KEY_PEM) instead of HS256 for downstream JWKS - Email backend pointed at a verified domain
- Storage backend on S3 / R2 / GCS (not local disk)
- Session cache on Redis if you expect >1k req/s
- Rate-limit layer (tower-governor, nginx, Cloudflare) in front of
/v1/auth/login,/v1/auth/password/forgot,/v1/auth/email-otp/request - CORS allowlist tuned to your frontend origins
- Audit log export (Splunk / Datadog / S3) wired up