Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Auth Integration

ASecurity

Use when implementing authentication - login/signup forms, session management, protected routes, or role-based access control. NOT when non-auth UI, plain data fetching, or unrelated backend logic. Triggers: "login page", "signup form", "auth setup", "protected route", "role-based access", "Better Auth", "NextAuth".

416 stars
0 votes
0 copies
1 views
Added 2/8/2026
developmenttypescriptgobashsqlreactnextjsnodeapidatabasebackend

Works with

cliapi

Security Analysis

A100/100

Scanned 2/12/2026

Install to Claude Code

$npx -y skills add aiskillstore/marketplace --skill auth-integration --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Auth Integration?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Auth Integration
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/aiskillstore-auth-integration/badge)](https://www.skillsdirectory.com/skills/aiskillstore-auth-integration)

More formats (shields.io, HTML) on the badges page.

Download with Pro
Files
SKILL.md
---
name: auth-integration
description: |
  Use when implementing authentication - login/signup forms, session management, protected routes, or role-based access control.
  NOT when non-auth UI, plain data fetching, or unrelated backend logic.
  Triggers: "login page", "signup form", "auth setup", "protected route", "role-based access", "Better Auth", "NextAuth".
---

# Better Auth Integration Skill

## Overview

Expert guidance for authentication implementation using Better Auth/NextAuth v5, including login/signup forms, session management with Zustand, protected routes via middleware, and role-based access control for ERP systems.

## When This Skill Applies

This skill triggers when users request:
- **Auth Setup**: "Setup Better Auth", "Configure authentication", "Auth providers"
- **Auth Forms**: "Login page", "Signup form", "Forgot password", "Email verification"
- **Session Management**: "Auth store", "Session handling", "Zustand auth"
- **Protected Routes**: "Protected dashboard", "Auth middleware", "Route guards"
- **Role-Based Access**: "Role guard", "Permission check", "Admin only", "Teacher access"

## Core Rules

### 1. Provider Setup

```typescript
// app/auth/[...auth]/route.ts
import { auth } from '@/lib/auth';
import { toNextJsHandler } from 'better-auth/next-js';

export const { GET, POST } = toNextJsHandler(auth);

// lib/auth.ts
import { betterAuth } from 'better-auth';
import { prismaAdapter } from 'better-auth/adapters/prisma';

export const auth = betterAuth({
  database: prismaAdapter(prisma),
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
  },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    },
  },
  session: {
    expiresIn: 60 * 60 * 24 * 7, // 7 days
    updateAge: 60 * 60 * 24, // 24 hours
  },
});
```

**Requirements:**
- Use Better Auth v5 for Next.js App Router
- Configure providers (Google, Email/Password)
- Enable email verification for new users
- Set appropriate session expiration
- Use environment variables for secrets (never hardcode)
- Prisma adapter for database integration

### 2. Auth Forms with Validation

```tsx
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { signIn } from '@/lib/auth/client';

const loginSchema = z.object({
  email: z.string().email('Invalid email address'),
  password: z.string().min(8, 'Password must be at least 8 characters'),
});

type LoginFormData = z.infer<typeof loginSchema>;

export default function LoginForm() {
  const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<LoginFormData>({
    resolver: zodResolver(loginSchema),
  });

  const onSubmit = async (data: LoginFormData) => {
    await signIn.email({
      email: data.email,
      password: data.password,
    });
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
      <div>
        <label className="block text-sm font-medium mb-2">Email</label>
        <input
          {...register('email')}
          type="email"
          className="w-full px-4 py-2 rounded-lg border"
        />
        {errors.email && <p className="text-red-500 text-sm mt-1">{errors.email.message}</p>}
      </div>
      <div>
        <label className="block text-sm font-medium mb-2">Password</label>
        <input
          {...register('password')}
          type="password"
          className="w-full px-4 py-2 rounded-lg border"
        />
        {errors.password && <p className="text-red-500 text-sm mt-1">{errors.password.message}</p>}
      </div>
      <button
        type="submit"
        disabled={isSubmitting}
        className="w-full py-2 bg-blue-500 text-white rounded-lg disabled:opacity-50"
      >
        {isSubmitting ? 'Signing in...' : 'Sign In'}
      </button>
    </form>
  );
}
```

**Requirements:**
- Use React Hook Form + Zod for validation
- shadcn/ui components for form inputs
- Clear error messages with localization support
- Loading states for better UX
- Accessibility: proper labels, ARIA attributes
- Password strength indicator for signup

### 3. Session Management

```typescript
import { create } from 'zustand';
import { authClient } from '@/lib/auth/client';

interface AuthState {
  user: User | null;
  session: Session | null;
  isLoading: boolean;
  isAuthenticated: boolean;
  role: string | null;
  hydrateAuth: () => Promise<void>;
  signIn: (email: string, password: string) => Promise<void>;
  signOut: () => Promise<void>;
  refresh: () => Promise<void>;
}

export const useAuthStore = create<AuthState>((set, get) => ({
  user: null,
  session: null,
  isLoading: true,
  isAuthenticated: false,
  role: null,

  hydrateAuth: async () => {
    set({ isLoading: true });
    try {
      const session = await authClient.getSession();
      set({
        user: session.user,
        session: session,
        isAuthenticated: !!session,
        role: session.user?.role || null,
        isLoading: false,
      });
    } catch (error) {
      set({ isLoading: false, isAuthenticated: false });
    }
  },

  signIn: async (email: string, password: string) => {
    await authClient.signIn.email({ email, password });
    await get().hydrateAuth();
  },

  signOut: async () => {
    await authClient.signOut();
    set({
      user: null,
      session: null,
      isAuthenticated: false,
      role: null,
    });
  },

  refresh: async () => {
    await get().hydrateAuth();
  },
}));

export const useAuth = () => {
  const auth = useAuthStore();

  useEffect(() => {
    if (!auth.user && !auth.isLoading) {
      auth.hydrateAuth();
    }
  }, []);

  return auth;
};
```

**Requirements:**
- Use Zustand for client-side auth state
- Sync with Better Auth session
- Type-safe user and session data
- Automatic session refresh on hydration
- Secure cookie storage (httpOnly, secure, sameSite)
- Clear sessions on sign out

### 4. Protected Routes

```typescript
import { authMiddleware } from 'better-auth/next-js';
import { NextResponse } from 'next/server';

export default authMiddleware({
  pathPrefix: '/dashboard',

  callback: async (request) => {
    const { user } = request;

    // Redirect to login if not authenticated
    if (!user) {
      return NextResponse.redirect(new URL('/auth/login', request.url));
    }

    // Role-based access control
    const path = request.nextUrl.pathname;

    if (path.startsWith('/dashboard/admin') && user.role !== 'admin') {
      return NextResponse.redirect(new URL('/dashboard', request.url));
    }

    if (path.startsWith('/dashboard/teacher') && user.role !== 'teacher' && user.role !== 'admin') {
      return NextResponse.redirect(new URL('/dashboard', request.url));
    }

    return NextResponse.next();
  },
});

export const config = {
  matcher: ['/dashboard/:path*'],
};
```

```tsx
import { useRouter } from 'next/navigation';
import { useAuth } from '@/hooks/useAuth';

export function withAuth<P extends object>(
  WrappedComponent: React.ComponentType<P>,
  allowedRoles?: string[]
) {
  return function AuthGuard(props: P) {
    const { isAuthenticated, user, isLoading } = useAuth();
    const router = useRouter();

    useEffect(() => {
      if (!isLoading && !isAuthenticated) {
        router.push('/auth/login');
      }

      if (!isLoading && isAuthenticated && allowedRoles) {
        if (!allowedRoles.includes(user?.role || '')) {
          router.push('/unauthorized');
        }
      }
    }, [isAuthenticated, isLoading, user, router]);

    if (isLoading) {
      return <LoadingSkeleton />;
    }

    if (!isAuthenticated || (allowedRoles && !allowedRoles.includes(user?.role || ''))) {
      return null;
    }

    return <WrappedComponent {...props} />;
  };
}
```

**Requirements:**
- Middleware for server-side route protection
- Path matchers for protected routes
- Role-based access control in middleware
- Client-side auth guard HOC for extra protection
- Redirect unauthorized users to appropriate pages
- Loading states during auth checks

### 5. Role-Based Access Control

```typescript
export const ROLES = {
  ADMIN: 'admin',
  TEACHER: 'teacher',
  STUDENT: 'student',
  PARENT: 'parent',
} as const;

export const PERMISSIONS = {
  // Admin permissions
  MANAGE_USERS: 'manage:users',
  MANAGE_COURSES: 'manage:courses',
  VIEW_ALL_DATA: 'view:all_data',

  // Teacher permissions
  VIEW_CLASS: 'view:class',
  MANAGE_STUDENTS: 'manage:students',
  CREATE_ASSIGNMENTS: 'create:assignments',

  // Student permissions
  VIEW_OWN_DATA: 'view:own_data',
  SUBMIT_ASSIGNMENTS: 'submit:assignments',
} as const;

export const hasRole = (user: User | null, role: string): boolean => {
  return user?.role === role || user?.role === ROLES.ADMIN;
};

export const hasPermission = (user: User | null, permission: string): boolean => {
  if (!user) return false;
  if (user.role === ROLES.ADMIN) return true;

  const rolePermissions = {
    [ROLES.ADMIN]: Object.values(PERMISSIONS),
    [ROLES.TEACHER]: [
      PERMISSIONS.VIEW_CLASS,
      PERMISSIONS.MANAGE_STUDENTS,
      PERMISSIONS.CREATE_ASSIGNMENTS,
    ],
    [ROLES.STUDENT]: [
      PERMISSIONS.VIEW_OWN_DATA,
      PERMISSIONS.SUBMIT_ASSIGNMENTS,
    ],
    [ROLES.PARENT]: [
      PERMISSIONS.VIEW_OWN_DATA,
    ],
  };

  return rolePermissions[user.role]?.includes(permission) ?? false;
};

export const PermissionGuard = ({
  permission,
  fallback = null,
  children,
}: {
  permission: string;
  fallback?: React.ReactNode;
  children: React.ReactNode;
}) => {
  const { user } = useAuth();

  if (!hasPermission(user, permission)) {
    return <>{fallback}</>;
  }

  return <>{children}</>;
};
```

**Requirements:**
- Define roles and permissions clearly
- Admin has all permissions by default
- Type-safe permission checking
- Permission-aware components
- Server-side permission verification for sensitive actions
- Audit logs for permission checks

## Output Requirements

### Code Files

1. **Auth Configuration**:
   - `lib/auth.ts` - Better Auth setup
   - `app/auth/[...auth]/route.ts` - Auth API routes

2. **Forms**:
   - `app/auth/login/page.tsx` - Login form
   - `app/auth/signup/page.tsx` - Signup form
   - `app/auth/forgot-password/page.tsx` - Password reset

3. **Session Management**:
   - `lib/auth-store.ts` - Zustand auth store
   - `hooks/useAuth.ts` - Auth hook

4. **Protected Routes**:
   - `middleware.ts` - Route protection
   - `components/AuthGuard.tsx` - Auth guard HOC

### Integration Requirements

- **shadcn/ui**: Use shadcn form components
- **@ui-ux-designer**: Ensure responsive, accessible forms
- **@nextjs-app-router**: Follow Next.js App Router patterns
- **@react-component**: Use functional components with hooks

### Documentation

- **PHR**: Create Prompt History Record for auth decisions
- **ADR**: Document auth strategy (JWT vs DB sessions, provider choice)
- **Comments**: Document security considerations

## Workflow

1. **Analyze Auth Requirements**
   - Identify auth providers needed (Google, Email/Password)
   - Determine role-based access needs
   - Check email verification requirements

2. **Setup Auth Provider**
   - Configure Better Auth with providers
   - Setup database adapter (Prisma)
   - Configure session settings

3. **Create Auth Forms**
   - Build login form with validation
   - Create signup with email verification
   - Add password reset flow

4. **Implement Session Management**
   - Create Zustand auth store
   - Sync with Better Auth session
   - Handle session refresh

5. **Protect Routes**
   - Setup middleware for server-side protection
   - Create auth guard HOC for client-side
   - Implement role-based access control

6. **Validate Security**
   - Check OWASP compliance
   - Verify CSRF protection
   - Test session handling

## Quality Checklist

Before completing any auth implementation:

- [ ] **OWASP Secure**: CSRF tokens, XSS protection, secure headers
- [ ] **Password Hash/Verify**: bcrypt/argon2, no plain text storage
- [ ] **Role Guards**: Middleware + client-side role checks
- [ ] **Logout Clear Sessions**: Clear cookies, Zustand store, redirect
- [ ] **Responsive Mobile Login**: Mobile-friendly forms, touch targets 44px+
- [ ] **Email Verification**: Required for new accounts
- [ ] **Session Expiration**: Reasonable timeout (7-30 days)
- [ ] **Secure Cookies**: httpOnly, secure, sameSite='strict'
- [ ] **Rate Limiting**: Prevent brute force attacks
- [ ] **Audit Logging**: Log auth events for security monitoring

## Common Patterns

### Login Page with Google Auth

```tsx
'use client';

import { useState } from 'react';
import { signIn } from '@/lib/auth/client';
import { useRouter } from 'next/navigation';

export default function LoginPage() {
  const router = useRouter();
  const [error, setError] = useState('');

  const handleGoogleSignIn = async () => {
    try {
      await signIn.social({
        provider: 'google',
        callbackURL: '/dashboard',
      });
    } catch (err) {
      setError('Failed to sign in with Google');
    }
  };

  const handleEmailSignIn = async (email: string, password: string) => {
    try {
      await signIn.email({
        email,
        password,
        callbackURL: '/dashboard',
      });
      router.push('/dashboard');
    } catch (err) {
      setError('Invalid email or password');
    }
  };

  return (
    <div className="min-h-screen flex items-center justify-center bg-gray-50">
      <div className="max-w-md w-full space-y-8 p-8 bg-white rounded-lg shadow-md">
        <h1 className="text-3xl font-bold text-center">Sign In</h1>

        {error && (
          <div className="p-3 bg-red-100 text-red-700 rounded-lg">
            {error}
          </div>
        )}

        <button
          onClick={handleGoogleSignIn}
          className="w-full flex items-center justify-center px-4 py-3 border border-gray-300 rounded-lg hover:bg-gray-50"
        >
          Sign in with Google
        </button>

        <div className="relative">
          <div className="absolute inset-0 flex items-center">
            <div className="w-full border-t border-gray-300" />
          </div>
          <div className="relative flex justify-center text-sm">
            <span className="px-2 bg-white text-gray-500">Or continue with email</span>
          </div>
        </div>

        <LoginForm onSubmit={handleEmailSignIn} />

        <p className="text-center text-sm text-gray-600">
          Don't have an account?{' '}
          <a href="/auth/signup" className="text-blue-600 hover:underline">
            Sign up
          </a>
        </p>
      </div>
    </div>
  );
}
```

### Signup with Email Verification

```tsx
'use client';

import { useState } from 'react';
import { signUp } from '@/lib/auth/client';

export default function SignupPage() {
  const [success, setSuccess] = useState(false);
  const [error, setError] = useState('');

  const handleSignup = async (data: SignupFormData) => {
    try {
      await signUp.email({
        email: data.email,
        password: data.password,
        name: data.name,
      });

      setSuccess(true);
    } catch (err) {
      setError('Failed to create account');
    }
  };

  if (success) {
    return (
      <div className="min-h-screen flex items-center justify-center">
        <div className="text-center">
          <h1 className="text-2xl font-bold mb-4">Check your email</h1>
          <p className="text-gray-600">
            We've sent a verification link to your email address
          </p>
        </div>
      </div>
    );
  }

  return <SignupForm onSubmit={handleSignup} />;
}
```

### Protected Dashboard with Role Guard

```tsx
import { withAuth } from '@/components/AuthGuard';
import { ROLES } from '@/lib/permissions';

function AdminDashboard() {
  const { user } = useAuth();

  return (
    <div className="p-6">
      <h1 className="text-2xl font-bold mb-6">Admin Dashboard</h1>
      <p>Welcome, {user?.name}</p>
    </div>
  );
}

export default withAuth(AdminDashboard, [ROLES.ADMIN]);
```

### Password Strength Indicator

```tsx
export const PasswordStrength = ({ password }: { password: string }) => {
  const getStrength = (pwd: string) => {
    let strength = 0;
    if (pwd.length >= 8) strength++;
    if (/[a-z]/.test(pwd)) strength++;
    if (/[A-Z]/.test(pwd)) strength++;
    if (/[0-9]/.test(pwd)) strength++;
    if (/[^a-zA-Z0-9]/.test(pwd)) strength++;
    return strength;
  };

  const strength = getStrength(password);
  const colors = ['bg-red-500', 'bg-orange-500', 'bg-yellow-500', 'bg-green-500', 'bg-green-600'];
  const labels = ['Weak', 'Fair', 'Good', 'Strong', 'Very Strong'];

  return (
    <div className="mt-2">
      <div className="flex gap-1">
        {[1, 2, 3, 4, 5].map((i) => (
          <div
            key={i}
            className={`h-2 flex-1 rounded ${i <= strength ? colors[strength - 1] : 'bg-gray-200'}`}
          />
        ))}
      </div>
      {password && (
        <p className={`text-sm mt-1 ${colors[strength - 1]?.replace('bg-', 'text-')}`}>
          Password strength: {labels[strength - 1]}
        </p>
      )}
    </div>
  );
};
```

## Security Best Practices

### OWASP Compliance

1. **CSRF Protection**: Use built-in Better Auth CSRF tokens
2. **XSS Prevention**: Sanitize user input, use React's auto-escaping
3. **SQL Injection**: Use Prisma ORM (parameterized queries)
4. **Password Security**: bcrypt/argon2 hashing, minimum 8 characters
5. **Session Security**: httpOnly, secure, sameSite cookies

### Rate Limiting

```typescript
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';

const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(5, '10 s'), // 5 requests per 10 seconds
});

export async function checkRateLimit(identifier: string) {
  const { success } = await ratelimit.limit(identifier);
  return success;
}
```

### Audit Logging

```typescript
export async function logAuthEvent(event: {
  type: 'login' | 'logout' | 'signup' | 'password_reset';
  userId?: string;
  ip?: string;
  userAgent?: string;
}) {
  await prisma.authEvent.create({
    data: {
      ...event,
      timestamp: new Date(),
    },
  });
}
```

## Environment Variables

```bash
# .env.local
AUTH_SECRET=your-super-secret-random-string
BETTER_AUTH_URL=http://localhost:3000

# Google OAuth
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret

# Database
DATABASE_URL=your-database-url
```

## References

- Better Auth: https://www.better-auth.com
- NextAuth v5: https://authjs.dev
- OWASP Authentication Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
- shadcn/ui Forms: https://ui.shadcn.com/docs/components/form
- React Hook Form: https://react-hook-form.com
- Zod Validation: https://zod.dev

Attribution

aiskillstoreaiskillstore
View sourceMore from aiskillstore →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

284722 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2192 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →