Help us improve
Share bugs, ideas, or general feedback.
From goodvibes
Orchestrates full authentication workflows for login, sign-up, sessions, JWT/OAuth, protected routes, middleware, RBAC, and security hardening across web frameworks.
npx claudepluginhub mgd34msu/goodvibes-plugin --plugin goodvibesHow this skill is triggered — by the user, by Claude, or both
Slash command
/goodvibes:authenticationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
```
Scaffold signin and signup authentication endpoints for a project. Use when the user wants to add authentication, create login/register flows, or set up auth from scratch.
Implements authentication and authorization patterns: JWT, OAuth2, session management, RBAC. Helps secure APIs and debug auth issues.
Implements auth patterns like JWT, OAuth2, sessions, and RBAC for securing APIs. Use for user auth, API protection, social login, or debugging security issues.
Share bugs, ideas, or general feedback.
scripts/
auth-checklist.sh
references/
decision-tree.md
This skill orchestrates complete authentication implementation from discovery through testing. It replaces library-specific skills (clerk, nextauth, lucia, auth0, firebase-auth, supabase-auth, passport) with a unified workflow that adapts to your stack.
Use when implementing:
Before starting:
Use discover to understand existing authentication patterns:
discover:
queries:
- id: existing-auth
type: grep
pattern: "(useAuth|getSession|withAuth|requireAuth|protect|authenticate)"
glob: "**/*.{ts,tsx,js,jsx}"
- id: middleware-files
type: glob
patterns:
- "**/middleware.{ts,js}"
- "**/auth/**/*.{ts,js}"
- "**/_middleware.{ts,js}"
- id: session-handling
type: grep
pattern: "(session|jwt|token|cookie)"
glob: "**/*.{ts,tsx,js,jsx}"
- id: protected-routes
type: grep
pattern: "(protected|private|requireAuth|withAuth)"
glob: "**/*.{ts,tsx,js,jsx}"
verbosity: files_only
What to look for:
Decision Point: If auth is already partially implemented, read existing files to understand the pattern before extending it.
Use detect_stack to determine framework and identify auth approach:
detect_stack:
path: "."
Framework Detection:
Consult Decision Tree: Read references/decision-tree.md to choose between managed (Clerk, Auth0), self-hosted (NextAuth, Lucia), or serverless (Supabase Auth) based on framework and requirements.
Based on framework and decision tree, plan which files to create/modify:
Common Files Needed:
Middleware (middleware.ts, auth.middleware.ts)
Auth Utilities (lib/auth.ts, utils/auth.ts)
Auth API Routes (/api/auth/login, /api/auth/signup, /api/auth/logout)
Protected Route Wrappers (withAuth, requireAuth)
Client Hooks (useAuth, useSession)
Framework-Specific Patterns:
Next.js App Router:
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('session')?.value;
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/dashboard/:path*', '/api/:path*']
};
Remix:
// app/utils/session.server.ts
import { createCookieSessionStorage } from '@remix-run/node';
const { getSession, commitSession, destroySession } =
createCookieSessionStorage({
cookie: {
name: '__session',
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
secrets: [process.env.SESSION_SECRET],
sameSite: 'lax'
}
});
export { getSession, commitSession, destroySession };
Express:
// middleware/auth.ts
import jwt from 'jsonwebtoken';
import type { Request, Response, NextFunction } from 'express';
export function requireAuth(req: Request, res: Response, next: NextFunction) {
const token = req.headers.authorization?.replace(/^bearer\s+/i, '');
if (!token) {
return res.status(401).json({ error: 'Unauthorized' });
}
try {
const payload = jwt.verify(token, process.env.JWT_SECRET!);
req.user = payload;
next();
} catch (err) {
return res.status(401).json({ error: 'Invalid token' });
}
}
Use precision_write in batch mode to create auth infrastructure:
precision_write:
files:
- path: "middleware.ts"
content: |
# Framework-specific middleware (see patterns above)
- path: "lib/auth.ts"
content: |
# Session validation, token generation
- path: "app/api/auth/login/route.ts"
content: |
# Login endpoint implementation
- path: "app/api/auth/signup/route.ts"
content: |
# Sign-up endpoint with validation
- path: "app/api/auth/logout/route.ts"
content: |
# Logout and session cleanup
verbosity: minimal
CRITICAL: No Placeholders
Use precision_exec to install required packages:
precision_exec:
commands:
# For JWT-based auth
- cmd: "npm install jsonwebtoken bcryptjs"
- cmd: "npm install -D @types/jsonwebtoken @types/bcryptjs"
# For session-based auth
- cmd: "npm install express-session connect-redis"
- cmd: "npm install -D @types/express-session"
# For managed services
- cmd: "npm install @clerk/nextjs" # Clerk
- cmd: "npm install next-auth" # NextAuth
- cmd: "npm install better-auth" # Better Auth (replaces deprecated Lucia)
verbosity: minimal
Run Database Migrations (if needed):
precision_exec:
commands:
- cmd: "npx prisma migrate dev --name add_user_auth"
timeout_ms: 60000
- cmd: "npx prisma generate"
verbosity: standard
Use analysis-engine tools to verify security:
1. Scan for Hardcoded Secrets:
scan_for_secrets:
paths:
- "lib/auth.ts"
- "app/api/auth/**/*.ts"
- "middleware.ts"
Expected Result: Zero secrets found. All API keys, JWT secrets, and credentials must be in .env files.
If secrets found:
.env or .env.localprocess.env.VAR_NAME to access.gitignore if not already present2. Audit Environment Variables:
env_audit:
check_documented: true
Expected Result: All auth-related env vars documented in .env.example or README.
Required Variables (typical):
JWT_SECRET or SESSION_SECRETDATABASE_URL (if using database)GOOGLE_CLIENT_ID, GITHUB_CLIENT_SECRET, etc.)NEXTAUTH_URL and NEXTAUTH_SECRET (for NextAuth)3. Validate Implementation:
# Use precision_grep to validate critical security patterns
precision_grep:
queries:
- id: password_hashing
pattern: "bcrypt|argon2|hashPassword"
path: "lib"
glob: "**/*.ts"
- id: httpOnly_cookies
pattern: "httpOnly.*true|httpOnly:\s*true"
path: "."
glob: "**/*.ts"
- id: csrf_protection
pattern: "csrf|CsrfToken|verifyCsrfToken"
path: "."
glob: "**/*.ts"
output:
format: "count_only"
Create route protection utilities:
Server-Side Protection (Next.js App Router):
// lib/auth.ts
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';
export async function requireAuth() {
const cookieStore = await cookies();
const session = cookieStore.get('session')?.value;
if (!session) {
redirect('/login');
}
const user = await validateSession(session);
if (!user) {
redirect('/login');
}
return user;
}
Client-Side Hook (React):
// hooks/useAuth.ts
import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
export function useAuth(options?: { redirectTo?: string }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const router = useRouter();
useEffect(() => {
fetch('/api/auth/me')
.then(res => res.ok ? res.json() : null)
.then(data => {
if (!data && options?.redirectTo) {
router.push(options.redirectTo);
} else {
setUser(data);
}
})
.finally(() => setLoading(false));
}, [options?.redirectTo, router]);
return { user, loading };
}
Apply to Routes:
Use precision_edit to add auth checks to existing routes:
precision_edit:
files:
- path: "app/dashboard/page.tsx"
edits:
- find: "export default function DashboardPage()"
replace: |
export default async function DashboardPage() {
const user = await requireAuth();
hints:
near_line: 1
Use suggest_test_cases to generate auth-specific test scenarios:
suggest_test_cases:
file: "lib/auth.ts"
category: "authentication"
Expected Test Cases:
Run Validation Script:
bash scripts/auth-checklist.sh .
Expected Exit Code: 0 (all checks pass)
Manual Testing Checklist:
Session Management:
Protected Routes:
OAuth:
Session Management:
Protected Routes:
OAuth:
Session Management:
Protected Routes:
OAuth:
Follow error-recovery protocol for auth failures:
try {
const user = await validateCredentials(email, password);
await createSession(user.id);
return { success: true };
} catch (err) {
if (err instanceof InvalidCredentialsError) {
// Don't leak whether email exists
return { error: 'Invalid email or password' };
}
if (err instanceof UserLockedError) {
return { error: 'Account locked. Contact support.' };
}
throw err; // Unexpected error
}
export async function validateSession(token: string) {
try {
const payload = jwt.verify(token, process.env.JWT_SECRET!);
return await getUserById(payload.userId);
} catch (err) {
if (err instanceof jwt.TokenExpiredError) {
return null; // Let caller handle (refresh or re-login)
}
if (err instanceof jwt.JsonWebTokenError) {
return null; // Invalid token
}
throw err; // Unexpected error
}
}
try {
const user = await db.user.create({
data: { email, passwordHash }
});
} catch (err) {
if (err.code === 'P2002') {
// Prisma unique constraint violation
return { error: 'Email already registered' };
}
throw err;
}
Before marking implementation complete:
references/decision-tree.md - Managed vs self-hosted vs serverless comparison.goodvibes/memory/patterns.json - Project-specific auth patternsscripts/auth-checklist.sh - Automated validation scriptLikely Causes:
Fix:
precision_exec: { cmd: "curl -v localhost:3000/api/auth/login" }Likely Causes:
Fix:
JWT_SECRET=<random-256-bit-hex>openssl rand -hex 32Likely Causes:
Fix:
Likely Causes:
Fix:
Add role-based access control (RBAC):
role field to User modelImplement password reset:
Add email verification:
Set up refresh tokens:
Add audit logging:
This workflow provides:
Follow each step sequentially, using precision tools for all file operations and validation.