Claude Code for Hanko Auth — Workflow Guide
The Setup
You are implementing passwordless authentication using Hanko, which provides passkey-first auth with WebAuthn support and pre-built UI components. Claude Code can integrate Hanko’s auth flow, but it defaults to building password-based login forms and misunderstands the passkey registration and verification flow.
What Claude Code Gets Wrong By Default
-
Builds password fields and bcrypt hashing. Claude generates traditional email/password forms. Hanko is passkey-first — users register with biometrics or security keys via WebAuthn. There are no passwords to hash.
-
Creates custom auth UI components. Claude builds login forms from scratch with controlled inputs. Hanko provides
<hanko-auth>and<hanko-profile>web components that handle the entire auth UI, including passkey registration, email verification, and fallback flows. -
Uses JWT verification with jsonwebtoken. Claude verifies tokens with the
jsonwebtokennpm package. Hanko issues JWTs that should be verified using Hanko’s JWKS endpoint and thejoselibrary for proper key rotation support. -
Ignores the Hanko API URL configuration. Claude hardcodes auth endpoints. Hanko requires a
HANKO_API_URLthat points to your Hanko Cloud instance or self-hosted Hanko backend, and all components need this URL to function.
The CLAUDE.md Configuration
# Hanko Passkey Auth Project
## Architecture
- Auth: Hanko (passkey-first, WebAuthn)
- Components: @teamhanko/hanko-elements (web components)
- Backend: Hanko Cloud or self-hosted Hanko backend
- JWT: Verified via Hanko JWKS endpoint
## Hanko Rules
- Use <hanko-auth> web component for login/register UI
- Use <hanko-profile> web component for user settings
- No password fields — Hanko handles passkeys and email codes
- JWT in cookie, verified with jose library + Hanko JWKS URL
- HANKO_API_URL env var points to Hanko instance
- Register web components: register(HANKO_API_URL) from @teamhanko/hanko-elements
- Access user info: hanko.user.getCurrent() from @teamhanko/hanko-frontend-sdk
## Conventions
- Hanko elements registered once in app entry point
- Auth middleware verifies JWT on protected API routes
- JWKS URL: {HANKO_API_URL}/.well-known/jwks.json
- User ID from JWT sub claim
- Session cookie name: hanko (httpOnly, secure)
- Never build custom auth forms — use Hanko components
Workflow Example
You want to add passkey login to a Next.js app with protected routes. Prompt Claude Code:
“Integrate Hanko auth into this Next.js app. Add the login page with Hanko components, create middleware that verifies the Hanko JWT on protected routes, and add a profile page where users can manage their passkeys.”
Claude Code should register Hanko elements in a client component, create a /login page rendering <hanko-auth>, build Next.js middleware that extracts the JWT cookie and verifies it against the Hanko JWKS endpoint using jose, and add a /profile page with <hanko-profile>.
Common Pitfalls
-
Web component registration in SSR. Claude registers Hanko elements at the module level, which fails during server-side rendering because web components need the DOM. Wrap registration in a
useEffector use"use client"directive with dynamic imports. -
JWKS caching miss. Claude fetches the JWKS endpoint on every request without caching. This adds latency and can hit rate limits. Cache the JWKS response using
jose.createRemoteJWKSet()which handles caching and key rotation automatically. -
Missing redirect after authentication. Claude renders
<hanko-auth>but does not listen for theonAuthFlowCompletedevent. Without this callback, users complete authentication but stay on the login page instead of redirecting to the dashboard.