Load PROACTIVELY when task involves user identity, login, or access control. Use when user says "add authentication", "set up login", "add OAuth", "protect these routes", "implement RBAC", or "add sign-up". Covers session management, JWT tokens, OAuth2 flows, password reset, email verification, protected route middleware, role-based access control, and security hardening (CSRF, rate limiting, token rotation).
Implements secure authentication systems with session management, OAuth, and protected routes for any web framework.
/plugin marketplace add mgd34msu/goodvibes-plugin/plugin install goodvibes@goodvibes-marketThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/decision-tree.mdscripts/auth-checklist.shscripts/
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.
Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.