auth-integration
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".
Best use case
auth-integration is best used when you need a repeatable AI agent workflow instead of a one-off prompt. It is especially useful for teams working in multi. 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".
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".
Users should expect a more consistent workflow output, faster repeated execution, and less time spent rewriting prompts from scratch.
Practical example
Example input
Use the "auth-integration" skill to help with this workflow task. Context: 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".
Example output
A structured workflow result with clearer steps, more consistent formatting, and an output that is easier to reuse in the next run.
When to use this skill
- Use this skill when you want a reusable workflow rather than writing the same prompt again and again.
When not to use this skill
- Do not use this when you only need a one-off answer and do not need a reusable workflow.
- Do not use it if you cannot install or maintain the related files, repository context, or supporting tools.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/auth-integration/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How auth-integration Compares
| Feature / Agent | auth-integration | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
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".
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# 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.devRelated Skills
authentication-setup
Design and implement authentication and authorization systems. Use when setting up user login, JWT tokens, OAuth, session management, or role-based access control. Handles password security, token management, SSO integration.
stripe-integration
Implement Stripe payment processing for robust, PCI-compliant payment flows including checkout, subscriptions, and webhooks. Use when integrating Stripe payments, building subscription systems, or implementing secure checkout flows.
seo-authority-builder
Analyzes content for E-E-A-T signals and suggests improvements to build authority and trust. Identifies missing credibility elements. Use PROACTIVELY for YMYL topics.
paypal-integration
Integrate PayPal payment processing with support for express checkout, subscriptions, and refund management. Use when implementing PayPal payments, processing online transactions, or building e-commerce checkout flows.
payment-integration
Integrate Stripe, PayPal, and payment processors. Handles checkout flows, subscriptions, webhooks, and PCI compliance. Use PROACTIVELY when implementing payments, billing, or subscription features.
nextjs-supabase-auth
Expert integration of Supabase Auth with Next.js App Router Use when: supabase auth next, authentication next.js, login supabase, auth middleware, protected route.
microsoft-azure-webjobs-extensions-authentication-events-dotnet
Microsoft Entra Authentication Events SDK for .NET. Azure Functions triggers for custom authentication extensions. Use for token enrichment, custom claims, attribute collection, and OTP customization in Entra ID. Triggers: "Authentication Events", "WebJobsAuthenticationEventsTrigger", "OnTokenIssuanceStart", "OnAttributeCollectionStart", "custom claims", "token enrichment", "Entra custom extension", "authentication extension".
hubspot-integration
Expert patterns for HubSpot CRM integration including OAuth authentication, CRM objects, associations, batch operations, webhooks, and custom objects. Covers Node.js and Python SDKs. Use when: hubspot, hubspot api, hubspot crm, hubspot integration, contacts api.
clerk-auth
Expert patterns for Clerk auth implementation, middleware, organizations, webhooks, and user sync Use when: adding authentication, clerk auth, user authentication, sign in, sign up.
broken-authentication
This skill should be used when the user asks to "test for broken authentication vulnerabilities", "assess session management security", "perform credential stuffing tests", "evaluate ...
broken-authentication-testing
This skill should be used when the user asks to "test for broken authentication vulnerabilities", "assess session management security", "perform credential stuffing tests", "evaluate password policies", "test for session fixation", or "identify authentication bypass flaws". It provides comprehensive techniques for identifying authentication and session management weaknesses in web applications.
auth-implementation-patterns
Master authentication and authorization patterns including JWT, OAuth2, session management, and RBAC to build secure, scalable access control systems. Use when implementing auth systems, securing APIs, or debugging security issues.