Agent skill

authentication

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).

Stars 6
Forks 1

Install this agent skill to your Project

npx add-skill https://github.com/mgd34msu/goodvibes-plugin/tree/main/plugins/goodvibes/skills/outcome/authentication

Metadata

Additional technical details for this skill

tags
auth login sign-up session jwt oauth middleware rbac
version
1.0.0
category
outcome

SKILL.md

Resources

scripts/
  auth-checklist.sh
references/
  decision-tree.md

Authentication Implementation Workflow

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.

When to Use This Skill

Use when implementing:

  • User login and sign-up flows
  • Session management (cookies, JWT, server-side sessions)
  • OAuth integration (Google, GitHub, etc.)
  • Protected routes and API endpoints
  • Middleware-based authentication
  • Role-based access control (RBAC)
  • Token refresh mechanisms
  • Password reset flows

Prerequisites

Before starting:

  1. Understand project framework (Next.js, Remix, Express, etc.)
  2. Have database schema planned (if using database-backed auth)
  3. Know authentication approach (managed service vs self-hosted)
  4. Access to environment variable configuration

Workflow Steps

Step 1: Discovery

Use discover to understand existing authentication patterns:

yaml
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:

  • Existing auth hooks, utilities, or middleware
  • Session storage mechanism (cookies, localStorage, server-side)
  • Protected route patterns
  • Auth provider setup (if using third-party)

Decision Point: If auth is already partially implemented, read existing files to understand the pattern before extending it.

Step 2: Detect Stack

Use detect_stack to determine framework and identify auth approach:

yaml
detect_stack:
  path: "."

Framework Detection:

  • Next.js (App Router): Use middleware.ts + Server Actions + cookies
  • Next.js (Pages Router): Use getServerSideProps + API routes + NextAuth
  • Remix: Use loader/action auth + session cookies
  • Express/Fastify: Use middleware + session store
  • tRPC: Use context + middleware
  • GraphQL: Use context + directives

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.

Step 3: Implementation Planning

Based on framework and decision tree, plan which files to create/modify:

Common Files Needed:

  1. Middleware (middleware.ts, auth.middleware.ts)

    • Intercept requests
    • Verify authentication status
    • Redirect unauthenticated users
  2. Auth Utilities (lib/auth.ts, utils/auth.ts)

    • Session creation/validation
    • Token generation/verification
    • Password hashing (bcrypt, argon2)
  3. Auth API Routes (/api/auth/login, /api/auth/signup, /api/auth/logout)

    • Handle authentication requests
    • Set session cookies
    • Return auth state
  4. Protected Route Wrappers (withAuth, requireAuth)

    • HOCs or server utilities
    • Check auth before rendering
    • Redirect or return 401
  5. Client Hooks (useAuth, useSession)

    • Access current user
    • Manage client-side auth state
    • Trigger login/logout

Framework-Specific Patterns:

Next.js App Router:

typescript
// 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:

typescript
// 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:

typescript
// 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' });
  }
}

Step 4: Write Configuration and Core Files

Use precision_write in batch mode to create auth infrastructure:

yaml
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

  • Implement full validation (zod, yup, etc.)
  • Include proper error handling
  • Hash passwords with bcrypt/argon2
  • Use secure session configuration
  • Add CSRF protection where applicable

Step 5: Install Dependencies

Use precision_exec to install required packages:

yaml
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):

yaml
precision_exec:
  commands:
    - cmd: "npx prisma migrate dev --name add_user_auth"
      timeout_ms: 60000
    - cmd: "npx prisma generate"
  verbosity: standard

Step 6: Security Verification

Use analysis-engine tools to verify security:

1. Scan for Hardcoded Secrets:

yaml
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:

  • Move to .env or .env.local
  • Use process.env.VAR_NAME to access
  • Add to .gitignore if not already present

2. Audit Environment Variables:

yaml
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_SECRET
  • DATABASE_URL (if using database)
  • OAuth credentials (GOOGLE_CLIENT_ID, GITHUB_CLIENT_SECRET, etc.)
  • NEXTAUTH_URL and NEXTAUTH_SECRET (for NextAuth)

3. Validate Implementation:

yaml
# 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"

Step 7: Protected Routes Implementation

Create route protection utilities:

Server-Side Protection (Next.js App Router):

typescript
// 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):

typescript
// 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:

yaml
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

Step 8: Test Implementation

Use suggest_test_cases to generate auth-specific test scenarios:

yaml
suggest_test_cases:
  file: "lib/auth.ts"
  category: "authentication"

Expected Test Cases:

  • Valid login with correct credentials
  • Login failure with incorrect password
  • Sign-up with valid data
  • Sign-up with duplicate email
  • Protected route redirects unauthenticated users
  • Session token refresh
  • Logout clears session
  • CSRF token validation
  • Password reset flow

Run Validation Script:

bash
bash scripts/auth-checklist.sh .

Expected Exit Code: 0 (all checks pass)

Manual Testing Checklist:

  1. Sign up new user
  2. Verify password is hashed in database
  3. Log in with credentials
  4. Access protected route (should succeed)
  5. Log out
  6. Access protected route (should redirect to login)
  7. Test OAuth flow (if implemented)
  8. Verify session persists across page reloads
  9. Test token expiration and refresh

Common Patterns by Framework

Next.js (App Router)

Session Management:

  • Use cookies() from 'next/headers'
  • Set httpOnly, secure, sameSite cookies
  • Validate in middleware.ts and Server Components

Protected Routes:

  • Server-side: await requireAuth() in page/layout
  • Client-side: useAuth() hook with redirectTo
  • API routes: check cookies in route handlers

OAuth:

  • Use NextAuth for simplicity
  • Or implement manual OAuth flow with redirect URIs

Remix

Session Management:

  • Use createCookieSessionStorage
  • Validate in loaders
  • Commit session in actions

Protected Routes:

  • Check session in loader, throw redirect() if unauthenticated
  • Use getSession() utility consistently

OAuth:

  • Use remix-auth strategies
  • Handle callbacks in dedicated routes

Express/Fastify

Session Management:

  • Use express-session + Redis store
  • Or JWT tokens in Authorization header

Protected Routes:

  • Middleware functions: requireAuth, optionalAuth
  • Apply to specific routes or globally

OAuth:

  • Use passport.js strategies
  • Configure serialize/deserialize user

Error Handling

Follow error-recovery protocol for auth failures:

Login Failures

typescript
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
}

Session Validation Failures

typescript
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
  }
}

Database Errors

typescript
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;
}

Security Checklist

Before marking implementation complete:

  • Passwords hashed with bcrypt (cost 10+) or argon2
  • Session tokens are random (crypto.randomBytes) or signed JWT
  • Cookies are httpOnly, secure (in prod), sameSite: 'lax' or 'strict'
  • CSRF protection enabled (for cookie-based auth)
  • Rate limiting on login/signup endpoints
  • Input validation on all auth endpoints
  • No sensitive data in error messages
  • Environment variables documented in .env.example
  • No hardcoded secrets in source code
  • Session expiration configured (1-7 days typical)
  • Logout clears all auth tokens/sessions
  • OAuth redirect URIs whitelisted

References

  • references/decision-tree.md - Managed vs self-hosted vs serverless comparison
  • .goodvibes/memory/patterns.json - Project-specific auth patterns
  • scripts/auth-checklist.sh - Automated validation script

Troubleshooting

"Session not persisting across requests"

Likely Causes:

  • Cookie not being set (check response headers)
  • httpOnly preventing client-side access (expected)
  • sameSite: 'strict' blocking cross-origin (use 'lax')
  • Cookie domain mismatch

Fix:

  1. Check cookie configuration in auth code
  2. Verify cookies are in response: precision_exec: { cmd: "curl -v localhost:3000/api/auth/login" }
  3. Ensure middleware reads cookies correctly

"JWT token invalid after server restart"

Likely Causes:

  • JWT_SECRET changes between restarts
  • Secret not in .env file
  • Different secret in different environments

Fix:

  1. Move JWT_SECRET to .env: JWT_SECRET=<random-256-bit-hex>
  2. Generate with: openssl rand -hex 32
  3. Never commit .env to git

"OAuth callback fails with redirect_uri_mismatch"

Likely Causes:

  • Callback URL not whitelisted in OAuth provider dashboard
  • http vs https mismatch
  • Port number missing

Fix:

  1. Check OAuth provider settings
  2. Add callback URL exactly as it appears in error
  3. For local dev, use http://localhost:3000/api/auth/callback/google (example)

"Protected routes not redirecting"

Likely Causes:

  • Middleware not configured correctly
  • Matcher pattern doesn't match route
  • Session validation failing silently

Fix:

  1. Check middleware.ts config.matcher
  2. Add logging to middleware to verify it's running
  3. Test session validation independently

Next Steps After Implementation

  1. Add role-based access control (RBAC):

    • Add role field to User model
    • Create permission checking utilities
    • Protect admin routes
  2. Implement password reset:

    • Generate reset tokens
    • Send email with reset link
    • Validate token and update password
  3. Add email verification:

    • Generate verification tokens on signup
    • Send verification email
    • Verify token and mark user as verified
  4. Set up refresh tokens:

    • Issue short-lived access tokens (15 min)
    • Issue long-lived refresh tokens (7 days)
    • Rotate refresh tokens on use
  5. Add audit logging:

    • Log all login attempts (success and failure)
    • Track IP addresses and user agents
    • Monitor for suspicious activity

Summary

This workflow provides:

  • Framework-agnostic authentication implementation
  • Security-first approach with validation
  • Integration with GoodVibes precision tools
  • Automated verification via scripts
  • Error handling and troubleshooting

Follow each step sequentially, using precision tools for all file operations and validation.

Expand your agent's capabilities with these related and highly-rated skills.

mgd34msu/goodvibes-plugin

testing-strategy

Load PROACTIVELY when task involves writing tests, improving coverage, or test infrastructure. Use when user says "add tests", "write unit tests", "set up E2E testing", "improve coverage", or "add mocks". Covers Vitest/Jest unit tests, React Testing Library component tests, Playwright E2E tests, MSW API mocking, test organization and naming, fixture management, coverage targets and thresholds, snapshot testing, and CI integration.

6 1
Explore
mgd34msu/goodvibes-plugin

api-design

Load PROACTIVELY when task involves building or modifying API endpoints. Use when user says "build an API", "add an endpoint", "create a REST route", "set up GraphQL", or "add tRPC procedures". Covers route design and file organization, request validation with Zod, response formatting, error handling patterns, middleware composition, authentication guards, rate limiting, pagination, and API documentation generation.

6 1
Explore
mgd34msu/goodvibes-plugin

ai-integration

Load PROACTIVELY when task involves AI, LLM, or machine learning features. Use when user says "add AI chat", "implement streaming responses", "build a RAG pipeline", "add embeddings", or "integrate OpenAI". Covers chat interfaces, streaming with Vercel AI SDK, retrieval-augmented generation, vector search, embeddings pipelines, tool/function calling, and provider abstraction for OpenAI, Anthropic, and local models.

6 1
Explore
mgd34msu/goodvibes-plugin

payment-integration

Load PROACTIVELY when task involves payments, billing, or subscriptions. Use when user says "add payments", "integrate Stripe", "set up subscriptions", "add a checkout flow", or "handle billing webhooks". Covers Stripe, LemonSqueezy, and Paddle integration, checkout sessions, subscription lifecycle management, webhook verification and handling, customer portal, metered billing, refunds, and PCI compliance considerations.

6 1
Explore
mgd34msu/goodvibes-plugin

state-management

Load PROACTIVELY when task involves application state, data fetching, or form handling. Use when user says "manage state", "add data fetching", "set up Zustand", "handle form validation", or "add React Query". Covers server state (TanStack Query with caching, optimistic updates), client state (Zustand stores), form state (React Hook Form with Zod validation), URL state (search params, routing), and choosing between state solutions.

6 1
Explore
mgd34msu/goodvibes-plugin

database-layer

Load PROACTIVELY when task involves database design, schemas, or data access. Use when user says "set up the database", "create a schema", "add a migration", "write a query", or "set up Prisma". Covers schema design and normalization, ORM setup (Prisma, Drizzle), migration workflows, connection pooling, query optimization, indexing strategies, seeding, and transaction patterns for PostgreSQL, MySQL, SQLite, and MongoDB.

6 1
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results