From shipwithai-auth
Diagnose and fix issues in existing auth setups. Scans environment, files, security, middleware, OAuth, database, and dangerous code patterns. Produces scored health report with actionable fixes.
How this skill is triggered — by the user, by Claude, or both
Slash command
/shipwithai-auth:auth-doctorThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Health check for existing authentication setups. Detects misconfigurations, missing files, security issues, and dangerous code patterns across Better Auth and Firebase Auth projects.
Health check for existing authentication setups. Detects misconfigurations, missing files, security issues, and dangerous code patterns across Better Auth and Firebase Auth projects.
/shipwithai-auth:setup — final validationRun the same discovery logic as skills/auth-setup/SKILL.md → Step 0. This ensures setup and doctor use identical detection.
Scan for:
1a. Framework & Versions (same as setup Step 0a/0b):
next.config.* → Next.js (extract version from package.json)1b. Auth Provider (same as setup Step 0d):
better-auth in deps → Better Authfirebase in deps → Firebase@clerk/nextjs, next-auth, @supabase/ssr → respective provider/shipwithai-auth:setup first."1c. ORM & Database (same as setup Step 0c):
drizzle.config.ts → Drizzle | prisma/schema.prisma → Prisma1d. Package Manager (same as setup Step 0f):
1e. UI Library (same as setup Step 0g):
components.json → shadcn/ui | Tailwind | MUI/Chakra/Mantine1e. Existing Auth Pages & Routes (same as setup Step 0e):
src/app/(auth)/login/, src/app/(auth)/register/, etc.src/app/api/auth/src/middleware.ts, middleware.ts1f. Auth-specific detection:
.env.local or .env → configured env varsGOOGLE_CLIENT_ID, GITHUB_CLIENT_ID, APPLE_CLIENT_IDresend in deps or RESEND_API_KEY in envOutput the detection summary before proceeding:
🔍 Auth Doctor — Scanning project...
Framework: Next.js 14.2.18 (App Router)
Provider: Better Auth ([email protected])
ORM: Drizzle ([email protected])
Database: SQLite (better-sqlite3)
Package mgr: npm
UI: shadcn/ui (new-york)
OAuth: Google ✓, GitHub ✗
Email: Resend ✓
Run each category. If $ARGUMENTS specifies a category, run ONLY that one. Otherwise run all 8.
env)Check .env.local exists:
.env.local (or .env as fallback)Check provider-specific required vars:
| Provider | Required |
|---|---|
| Better Auth | BETTER_AUTH_SECRET, BETTER_AUTH_URL |
| Firebase | NEXT_PUBLIC_FIREBASE_API_KEY, NEXT_PUBLIC_FIREBASE_PROJECT_ID, NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, FIREBASE_PROJECT_ID, FIREBASE_CLIENT_EMAIL, FIREBASE_PRIVATE_KEY |
Check var quality (not just existence):
BETTER_AUTH_SECRET — must be ≥32 chars (recommend 64 hex chars from openssl rand -hex 32)BETTER_AUTH_URL — must start with http:// or https://NEXT_PUBLIC_FIREBASE_API_KEY — must start with AIzaFIREBASE_PRIVATE_KEY — must contain -----BEGINCheck for test keys in production:
BETTER_AUTH_URL=http://localhost in a project with NODE_ENV=production indicatorsRESEND_API_KEY=re_test_ (test key can't send to real emails)Check OAuth var pairs:
GOOGLE_CLIENT_ID exists → GOOGLE_CLIENT_SECRET must also exist (and vice versa)GITHUB_CLIENT_ID exists → GITHUB_CLIENT_SECRET must also existAPPLE_CLIENT_ID exists → APPLE_CLIENT_SECRET must also existCheck email vars (if Resend detected):
RESEND_API_KEY — must start with re_EMAIL_FROM — must be a valid email format[email protected] — can only send to account owner emailfiles)Check all required files per provider:
Better Auth required files:
src/db/schema.ts — Drizzle schema with auth tables
src/lib/db.ts — Drizzle client
src/lib/auth.ts — Better Auth server config
src/lib/auth-client.ts — Better Auth client
src/app/api/auth/[...all]/route.ts — API route handler
src/middleware.ts — Route protection middleware
src/app/(auth)/login/page.tsx — Login page
src/app/(auth)/register/page.tsx — Register page
src/app/(auth)/forgot-password/page.tsx — Forgot password page
src/app/(auth)/reset-password/page.tsx — Reset password page
src/app/(protected)/layout.tsx — Protected layout with session check
src/app/(protected)/dashboard/page.tsx — Dashboard page
src/app/(protected)/dashboard/dashboard-client.tsx — Dashboard client component
src/components/icons.tsx — OAuth provider icons
.env.example — Env var template
drizzle.config.ts — Drizzle Kit config
Firebase required files:
src/lib/firebase.ts — Client SDK init
src/lib/firebase-admin.ts — Admin SDK init
src/lib/firebase-session.ts — Session cookie helpers
src/lib/auth-server.ts — getServerUser() helper
src/app/api/auth/session/route.ts — Session API with CSRF
src/middleware.ts — Route protection middleware
src/app/(auth)/login/page.tsx — Login page
src/app/(auth)/register/page.tsx — Register page
src/app/(auth)/forgot-password/page.tsx — Forgot password page
src/app/(auth)/reset-password/page.tsx — Reset password page
src/app/(protected)/layout.tsx — Protected layout with session verification
src/app/(protected)/dashboard/page.tsx — Dashboard page
src/app/(protected)/dashboard/dashboard-client.tsx — Dashboard client component
src/components/icons.tsx — OAuth provider icons
.env.example — Env var template
For each missing file: Report ❌ with the source asset path to copy from.
Cross-reference imports: For each existing file, check that its imports resolve:
import ... from "..." statements@/lib/auth, @/components/icons, etc.) have corresponding filesdeps)Check provider packages installed:
package.json dependencies + devDependenciesCheck for known breaking versions:
better-auth < 0.4.0 — major API changesdrizzle-kit with driver field instead of dialect — deprecated in 0.21+shadcn > 2.1.0 with Tailwind v3 — incompatible (pitfall #44)next >= 16 with middleware.ts — deprecated in favor of proxy.ts (pitfall #37)Check peer dependency conflicts:
npm ls 2>&1 | grep "peer dep" | head -20
Check node_modules exists:
security)Check .gitignore:
.env and .env.local must be listedsqlite.db should be listed (if SQLite).env not in .gitignoreScan for hardcoded secrets in source files:
src/ for patterns: sk_live_, sk_test_, re_, AIza, -----BEGIN, whsec_.env* files and node_modules/.ts/.tsx source filesCheck next.config for security headers:
assets/config/next.config.tsCheck for better-sqlite3 in serverComponentsExternalPackages (Better Auth + SQLite):
experimental.serverComponentsExternalPackagesserverExternalPackagespatterns)These checks map directly to SKILL.md Critical Code Rules R1–R8.
R1 — Module-scope SDK instantiation:
src/lib/email.ts for new Resend( at module scope (outside functions)src/lib/auth.ts for new Stripe( or new Resend( at module scopeR4 — Better Auth middleware using auth() wrapper:
src/middleware.ts for export { auth as middleware } or export default auth(auth() is Auth.js (NextAuth v5), not Better AuthR5 — Firebase middleware decoding JWT:
src/middleware.ts for atob(, Buffer.from(.*base64, firebase-admin, verifyIdToken, verifySessionCookieR2 — Redirect before session cookie (Firebase):
router.push without preceding await createSessionCookieR3 — Sign-out order (Firebase):
signOut()R7 — Missing Suspense wrapper:
reset-password/page.tsx for useSearchParams() without <Suspense>next build fails in Next.js 14+R8 — Missing files from checklist:
auth-client.ts specificallymiddleware)Check middleware exists:
src/middleware.ts or middleware.tsCheck middleware pattern matches provider:
| Provider | Correct pattern | Wrong pattern |
|---|---|---|
| Better Auth | request.cookies.get("better-auth.session_token") | auth(), getSession(), headers() |
| Firebase | request.cookies.get("__session") | verifyIdToken, firebase-admin, atob |
Check route matcher:
export const config = { matcher: [...] } — middleware runs on all routes including static assets/dashboard, /profile, etc.)/login, /register, /api/auth)Check for headers() import (Better Auth):
headers() from next/headers is NOT available in Edge Runtime middlewareoauth)For each detected OAuth provider (Google, GitHub, Apple):
Check env vars complete:
Check auth config includes the provider:
socialProviders in src/lib/auth.ts should list the providerCheck callback URL format:
{BETTER_AUTH_URL}/api/auth/callback/{provider}https://{PROJECT}.firebaseapp.com/__/auth/handlerCheck for common Google OAuth mistakes (Firebase):
references/05-firebase-auth-guide.mddatabase)Better Auth + Drizzle:
Check drizzle.config.ts:
dialect: "sqlite" (NOT driver: "better-sqlite")driver fieldCheck schema has auth tables:
src/db/schema.tsuser, session, account, verification tablesCheck db.ts passes schema:
drizzle(client, { schema }) — schema must be imported and passedCheck auth.ts passes schema to adapter:
drizzleAdapter(db, { provider: "sqlite", schema }) — schema must be passedCheck database file exists (SQLite):
sqlite.db doesn't exist — needs npx drizzle-kit push to create tablesCheck migration status:
drizzle/ directory has migration files, check they've been appliedAfter all checks complete, produce a scored report:
╔══════════════════════════════════════════════════╗
║ 🔐 Auth Doctor — Health Report ║
╠══════════════════════════════════════════════════╣
║ Provider: Better Auth ║
║ Score: 18/22 checks passed ║
╚══════════════════════════════════════════════════╝
Category Status Issues
─────────────────────────────────────────
1. Environment Variables ✅ 0
2. File Structure ❌ 2 missing files
3. Dependencies ✅ 0
4. Security ⚠️ 1 warning
5. Code Patterns ✅ 0
6. Middleware ✅ 0
7. OAuth Configuration ❌ 1 critical
8. Database ⚠️ 1 warning
──── CRITICAL (fix immediately) ─────────
❌ src/components/icons.tsx missing
→ Copy from plugin: assets/components/shared/icons.tsx
❌ GITHUB_CLIENT_ID set but GITHUB_CLIENT_SECRET missing
→ Add GITHUB_CLIENT_SECRET to .env.local
──── WARNINGS (review recommended) ──────
⚠️ No security headers in next.config
→ Merge from plugin: assets/config/next.config.ts
⚠️ sqlite.db not found — run: npx drizzle-kit push
Ordering rules:
After presenting the report:
Found {N} issues ({X} critical, {Y} warnings).
Would you like me to fix them?
A) Fix all — apply all safe fixes automatically
B) Fix critical only — fix only ❌ items
C) Show me the fixes first — explain what I'd change, then confirm
D) Skip — I'll fix them manually
CRITICAL rules for fixing:
.env.local values without user confirmation (may contain real secrets)driver → dialect: safe to auto-fixAfter fixes are applied, re-run ONLY the failed categories to confirm they now pass.
If all checks pass:
✅ All issues resolved! Auth setup is healthy.
Next steps:
- Run `npm run build` to verify the full build
- Test the auth flow: register → verify email → login → dashboard → sign out
- Review references/09-common-pitfalls.md for 60 production pitfalls
npx claudepluginhub mangalahq/shipwithai-plugins --plugin shipwithai-authProvides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.