Authentication and access control skill for Next.js 15 + Supabase applications. Use when implementing user authentication, protecting routes, managing user sessions, enforcing role-based access control (admin/member), or working with multi-tenant family-based data isolation. Covers login/logout, registration with email verification, OAuth (GitHub), route protection for Server Components and Server Actions, admin-only features, and multi-tenant data access patterns.
Scanned 9/3/2026
Install to Claude Code
npx -y skills add aiskillstore/marketplace --skill auth --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Auth?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/aiskillstore-auth-1c1302e6)More formats (shields.io, HTML) on the badges page.
---
name: auth
description: Authentication and access control skill for Next.js 15 + Supabase applications. Use when implementing user authentication, protecting routes, managing user sessions, enforcing role-based access control (admin/member), or working with multi-tenant family-based data isolation. Covers login/logout, registration with email verification, OAuth (GitHub), route protection for Server Components and Server Actions, admin-only features, and multi-tenant data access patterns.
---
# Authentication & Access Control
This skill provides workflows for implementing authentication and access control in this Next.js 15 + Supabase application using server-side auth with httpOnly cookies, hybrid route protection, and multi-tenant family-based data isolation.
## System Overview
- **Auth Provider**: Supabase Auth with httpOnly cookies
- **Architecture**: Next.js 15 App Router with Server Components and Server Actions
- **Route Protection**: Hybrid approach (page-level auth checks, not middleware-only)
- **Multi-Tenancy**: Family-based data isolation with RLS policies
- **Roles**: Admin (first user in family) and Member
## Core Workflows
### Protecting a New Route
To protect a route from unauthenticated users:
1. Import `requireAuthRedirect` from `@/lib/auth/server-auth`
2. Call `await requireAuthRedirect()` at the start of the component
3. User will be redirected to `/login` if not authenticated
```typescript
import { requireAuthRedirect } from '@/lib/auth/server-auth';
export default async function ProtectedPage() {
await requireAuthRedirect();
// User guaranteed authenticated here
return <YourContent />;
}
```
To protect an entire route group, add this to the layout component. All child routes will inherit the protection.
### Protecting a Server Action
To require authentication in a Server Action:
1. Import `requireAuth` from `@/lib/auth/server-auth`
2. Call `const user = await requireAuth()` at the start of the action
3. Action will throw `UnauthorizedError` if user not authenticated
```typescript
'use server';
import { requireAuth } from '@/lib/auth/server-auth';
export async function myAction() {
const user = await requireAuth();
// Proceed with authenticated action
}
```
### Getting Current User Data
- `getCurrentUser()` - Auth user (email, id), returns null if not logged in
- `getUserData()` - Extended profile (role, familyId, firstName, lastName, active)
- `getCurrentFamilyId()` - Just the family ID
All use React `cache()` - multiple calls in same request return cached value.
### Implementing Admin-Only Features
To restrict a page to admins:
```typescript
import { requireAdminRedirect } from '@/lib/auth/server-auth';
export default async function AdminPage() {
await requireAdminRedirect();
// User guaranteed to be admin
return <AdminPanel />;
}
```
To restrict a Server Action to admins:
```typescript
'use server';
import { requireAdmin } from '@/lib/auth/server-auth';
export async function adminAction() {
await requireAdmin(); // Throws if not admin
// Proceed
}
```
To conditionally show admin UI:
```typescript
import { isAdmin } from '@/lib/auth/server-auth';
export default async function Page() {
const userIsAdmin = await isAdmin();
return (
<>
<RegularContent />
{userIsAdmin && <AdminControls />}
</>
);
}
```
### Enforcing Multi-Tenant Data Access
To ensure users only access their own family's data:
```typescript
'use server';
import { requireFamilyAccess } from '@/lib/auth/server-auth';
export async function updateFamilyData(familyId: string, data: any) {
await requireFamilyAccess(familyId); // Throws if user not in this family
// User guaranteed to belong to this family
await updateDatabase(familyId, data);
}
```
When fetching current user's family data, use `getCurrentFamilyId()` instead - no need for `requireFamilyAccess` since it's their own family.
### Adding a New Authentication Page
To create a new auth page (login, register, password reset):
1. Create page under `src/app/(auth)/page-name/`
2. The `(auth)` group layout automatically redirects authenticated users to `/dashboard`
3. Create corresponding Server Action in `actions.ts` file
4. Import and use Supabase client: `const supabase = await createClient()`
Pages in `(auth)` group are automatically protected from authenticated users - they'll be redirected to dashboard if already logged in.
### Implementing Login/Logout
Use `supabase.auth.signInWithPassword()` for login and `supabase.auth.signOut()` for logout. See `references/patterns.md` for complete code examples.
### Adding OAuth Providers
1. Enable provider in Supabase Dashboard
2. Use `supabase.auth.signInWithOAuth({ provider: 'github', options: {...} })`
3. Callback handled automatically by `src/app/auth/callback/route.ts`
See `references/patterns.md` for full implementation examples.
## Security Requirements
### Token Validation
- Always use `supabase.auth.getUser()` to validate tokens (revalidates with server)
- Never use `supabase.auth.getSession()` in server code (can be spoofed)
### Server-Side Only
- All auth helpers in `src/lib/auth/server-auth.ts` are server-side only
- Never import these in Client Components
- Never add `'use server'` directive to `server-auth.ts` (breaks class exports)
### Middleware
- Middleware automatically refreshes tokens on every request
- Uses `updateSession()` from `src/lib/supabase/middleware.ts`
- Calls `getUser()` to revalidate tokens
- No additional token refresh logic needed
## Reference Files
For detailed information, see:
- `references/file-tree.md` - Complete file structure and organization
- `references/security.md` - Security best practices and requirements
- `references/patterns.md` - Code examples and common patterns
- `references/flows.md` - Authentication flow diagrams
## Quick Reference
**Key Files**: `src/lib/auth/server-auth.ts` (helpers), `src/middleware.ts` (token refresh), `src/app/dashboard/layout.tsx` (dashboard protection)
**Environment**: `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY`, `NEXT_PUBLIC_SITE_URL`
**Database**: `auth.users` (Supabase auth), `public.families` (households), `public.users` (profiles)
## Common Issues
**'use server' export error**: Remove `'use server'` from `server-auth.ts` - these are utilities, not actions
**Middleware redirect fails**: Use `requireAuth()` in Server Actions - middleware redirects don't work with POST
**Multi-tenant access denied**: Use `requireFamilyAccess(familyId)` to validate family ownership
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!