What is Hanko?
Hanko is an open-source authentication solution focused on passkeys — the FIDO2/WebAuthn standard that replaces passwords. It provides drop-in auth components and a full API for user management.
Passwords are dead. Passkeys are the future. Hanko makes it easy.
Quick Start
# Self-host with Docker
docker run -p 8000:8000 -p 8001:8001 ghcr.io/nicebook/hanko:latest
Or use Hanko Cloud (free tier: 10,000 MAU).
Drop-in Web Components
npm install @nicebook/hanko-elements
<!-- Login/Register component -->
<hanko-auth api="https://your-hanko.com"></hanko-auth>
<!-- User profile component -->
<hanko-profile api="https://your-hanko.com"></hanko-profile>
Two HTML tags — complete auth flow with passkeys, email codes, and social login.
React Integration
import { useEffect, useState } from "react";
import { register } from "@nicebook/hanko-elements";
import { Hanko } from "@nicebook/hanko-frontend-sdk";
const hankoApi = process.env.NEXT_PUBLIC_HANKO_API;
const hanko = new Hanko(hankoApi);
// Auth component
export function LoginPage() {
useEffect(() => {
register(hankoApi).catch(console.error);
}, []);
return <hanko-auth />;
}
// Check auth status
export function useUser() {
const [user, setUser] = useState(null);
useEffect(() => {
hanko.user.getCurrent()
.then(setUser)
.catch(() => setUser(null));
}, []);
return user;
}
// Logout
export function LogoutButton() {
const handleLogout = async () => {
await hanko.user.logout();
window.location.href = "/login";
};
return <button onClick={handleLogout}>Logout</button>;
}
The Admin API
export HANKO_URL="https://your-hanko.com"
export HANKO_ADMIN_KEY="your-admin-key"
# List users
curl -s "$HANKO_URL/users" \
-H "Authorization: Bearer $HANKO_ADMIN_KEY" | jq '.[].email'
# Get user
curl -s "$HANKO_URL/users/USER_ID" \
-H "Authorization: Bearer $HANKO_ADMIN_KEY"
# Delete user
curl -X DELETE "$HANKO_URL/users/USER_ID" \
-H "Authorization: Bearer $HANKO_ADMIN_KEY"
Frontend SDK
import { Hanko } from "@nicebook/hanko-frontend-sdk";
const hanko = new Hanko("https://your-hanko.com");
// Register with passkey
await hanko.webauthn.register();
// Login with passkey
await hanko.webauthn.login();
// Email login (passcode)
await hanko.passcode.initialize("user@example.com");
await hanko.passcode.finalize("123456"); // Code from email
// Get current user
const user = await hanko.user.getCurrent();
console.log(user.id, user.email);
// Session validation
const session = hanko.session.get();
if (session.isValid) {
console.log("User is authenticated");
}
Next.js Middleware
// middleware.ts
import { NextRequest, NextResponse } from "next/server";
import { jwtVerify, createRemoteJWKSet } from "jose";
const hankoApi = process.env.HANKO_API_URL;
export async function middleware(req: NextRequest) {
const token = req.cookies.get("hanko")?.value;
if (!token) return NextResponse.redirect(new URL("/login", req.url));
try {
const JWKS = createRemoteJWKSet(new URL(`${hankoApi}/.well-known/jwks.json`));
await jwtVerify(token, JWKS);
return NextResponse.next();
} catch {
return NextResponse.redirect(new URL("/login", req.url));
}
}
export const config = { matcher: ["/dashboard/:path*", "/api/protected/:path*"] };
Why Passkeys?
| Metric | Passwords | Passkeys |
|---|---|---|
| Phishing resistant | No | Yes |
| User friction | High | Low (biometric) |
| Account takeover | Common | Nearly impossible |
| Password reuse | Major risk | N/A |
| Support by | Everyone | Apple, Google, Microsoft |
Need authentication setup or security consulting?
📧 spinov001@gmail.com
🔧 My tools on Apify Store
Passkeys vs passwords — are you ready to switch? Comment!
Top comments (0)