npx claudepluginhub himself65/auth-specThis skill uses the workspace's default tool permissions.
You are scaffolding authentication (signin + signup) for the user's project.
references/axum-sqlx.rsreferences/express-prisma.tsreferences/fastapi-sqlalchemy.pyreferences/features/api-key.mdreferences/features/captcha.mdreferences/features/email-otp.mdreferences/features/kv-cache.mdreferences/features/magic-link.mdreferences/features/multi-session.mdreferences/features/organization.mdreferences/features/passkey.mdreferences/features/password-breach.mdreferences/features/phone-number.mdreferences/features/rate-limiting.mdreferences/features/two-factor.mdreferences/features/username.mdreferences/go-chi.goreferences/nextjs-drizzle.tsreferences/pitfalls/api-error-handling.mdreferences/pitfalls/api-key-shared-utils.mdImplements framework-agnostic TypeScript authentication with email/password, OAuth (Google, GitHub, Discord), 2FA (TOTP, SMS), passkeys/WebAuthn, session management, RBAC, rate limiting, and database adapters. Use for secure auth systems.
Sets up Neon Auth in Next.js, React SPA, or Node.js apps. Configures auth routes, session management, social providers, and generates UI components.
Adds complete user authentication system with login/registration, OAuth, JWT tokens, permission controls, and protected routes. Detects stacks like React/Vue frontend and FastAPI/Express/Next.js backend.
Share bugs, ideas, or general feedback.
You are scaffolding authentication (signin + signup) for the user's project.
Before asking any questions, scan the user's project to detect their stack:
next.config.*, package.json, go.mod, Cargo.toml, pyproject.toml, build.gradle*, pom.xml)prisma/schema.prisma, drizzle.config.*, alembic/, diesel.toml, ormconfig.*)Use what you find to pre-select the best options in the questions below. If the project clearly uses a specific stack, set that as the recommended option.
Use the AskUserQuestion tool to ask the user to make selections. Ask up to 3 questions in a single AskUserQuestion call so the user can answer everything at once.
Ask "Which language and framework are you using?" with header "Framework".
Pick the top 4 most relevant options based on what you detected in the project. If you detected the framework, put it first and mark it "(Recommended)". If you could not detect it, use these defaults:
The user can always pick "Other" to specify a different stack.
Ask "Which database and ORM/query layer?" with header "Database".
Again, pick the top 4 most relevant options based on the project. If detected, mark it "(Recommended)". Defaults:
Ask "How should sessions be managed?" with header "Sessions".
After the user answers the stack questions, use AskUserQuestion again to ask which additional auth features they want. Use multiSelect: true so they can pick multiple features at once.
Ask "Which authentication methods do you want to add?" with header "Auth methods". Set multiSelect to true.
Ask "Which security features do you want?" with header "Security". Set multiSelect to true.
Ask "Any additional capabilities?" with header "Extras". Set multiSelect to true.
Do not write any code until the user has answered all questions. Once you have their selections, proceed to Step 5.
Generate the core auth (schema + endpoints below) plus any selected features. For each selected feature, read the matching reference file from references/features/ to get the schema additions, endpoint specs, and implementation details.
Dependency: If the user selects Rate Limiting, also read references/features/kv-cache.md and generate the KV cache module first — rate limiting depends on it. The KV cache is a general-purpose utility that other features can also use, so generate it as a standalone module.
| Feature | Reference file |
|---|---|
| Email OTP | references/features/email-otp.md |
| Magic Link | references/features/magic-link.md |
| Phone Number | references/features/phone-number.md |
| Passkey | references/features/passkey.md |
| Two-Factor Auth | references/features/two-factor.md |
| Captcha | references/features/captcha.md |
| Password Breach | references/features/password-breach.md |
| Rate Limiting | references/features/rate-limiting.md |
| KV Cache | references/features/kv-cache.md |
| Multi-Session | references/features/multi-session.md |
| Username Auth | references/features/username.md |
| Organization/Teams | references/features/organization.md |
| API Keys | references/features/api-key.md |
Generate the following core auth using the schema and endpoint specs below.
Adapt everything to the user's language/framework idioms:
email_verified (snake_case) in Python/Go/Rust, emailVerified (camelCase) in JS/TS, EmailVerified (PascalCase) in C#std::string in C++, String in Rust/Java, string in Go/TS)uuid.New() (Go), Uuid::new_v4() (Rust), crypto.randomUUID() (JS), uuid4() (Python), boost::uuids::random_generator() (C++), etc.bcrypt (Go/JS/Python), argon2 (Rust), libsodium (C/C++), etc.Create these tables/models:
User
| Field | Type | Constraints |
|---|---|---|
| id | string | primary key |
| string | unique, not null | |
| name | string | nullable |
| emailVerified | boolean | default false |
| createdAt | datetime | default now |
| updatedAt | datetime | auto-update |
Session
| Field | Type | Constraints |
|---|---|---|
| id | string | primary key |
| userId | string | foreign key -> User, not null |
| token | string | unique, not null |
| expiresAt | datetime | not null |
| createdAt | datetime | default now |
Account
| Field | Type | Constraints |
|---|---|---|
| id | string | primary key |
| userId | string | foreign key -> User, not null |
| providerId | string | not null (e.g. "credential") |
| passwordHash | string | nullable |
| createdAt | datetime | default now |
| updatedAt | datetime | auto-update |
POST /api/auth/sign-up
{ email, password, name? }200 OK status and same response shape as a successful sign-up — do not return 409 or any error that reveals the email is taken. The response should be indistinguishable from a real sign-up. Implementation: attempt the insert, catch the unique constraint violation, hash the password anyway (to keep timing consistent), and return a fake success with a dummy user ID and token (that won't actually work as a session). This prevents attackers from discovering which emails are registered via the sign-up endpoint.POST /api/auth/sign-in
{ email, password }GET /api/auth/session
POST /api/auth/sign-out
crypto.randomUUID(), uuid.New(), Uuid::new_v4(), secrets.token_hex(), etc.)After generating all code, run the database migration automatically so the user doesn't hit "table does not exist" errors. Use the project's existing database driver/connection to execute the migration SQL.
For JS/TS projects using @neondatabase/serverless, the tagged-template sql function cannot run plain SQL strings. Use sql.query(statement) instead when executing migration statements programmatically.
Before generating code, read all files in references/pitfalls/ and follow their rules strictly. These are real bugs encountered in production.
| Pitfall | Reference file |
|---|---|
| API routes must catch DB errors | references/pitfalls/api-error-handling.md |
| Sign-up catch must not re-throw | references/pitfalls/signup-rethrow.md |
| Auth helpers must not throw | references/pitfalls/auth-helpers-no-throw.md |
| Client must handle non-JSON | references/pitfalls/client-json-parsing.md |
| OAuth redirect must not use request.url | references/pitfalls/oauth-redirect-request-url.md |
| API key hash/gen must not be duplicated | references/pitfalls/api-key-shared-utils.md |
Full working examples are in the references/ directory alongside this skill. Use the matching reference as a starting point and adapt to the user's specific setup:
| File | Stack |
|---|---|
nextjs-drizzle.ts | Next.js App Router + Drizzle + PostgreSQL |
express-prisma.ts | Express + Prisma + PostgreSQL |
go-chi.go | Go + Chi + database/sql + PostgreSQL |
fastapi-sqlalchemy.py | FastAPI + SQLAlchemy + PostgreSQL |
axum-sqlx.rs | Rust + Axum + sqlx + PostgreSQL |
spring-boot.kt | Kotlin + Spring Boot + JPA + PostgreSQL |
If the user's stack doesn't match any reference, use the closest one as a structural guide and adapt idioms accordingly.