clerk-auth-proxy
npx machina-cli add skill JanSzewczyk/claude-plugins/clerk-auth-proxy --openclawClerk Authentication & Proxy Skill
Implement Clerk authentication in Next.js 16 using the proxy pattern (not middleware!), manage session claims, and handle user metadata.
Reference Files:
- proxy-patterns.md - Next.js 16 proxy configuration
- session-claims.md - Custom session claims and metadata
- onboarding-gate.md - Onboarding flow patterns
- examples.md - Complete code examples
- testing.md - Testing authenticated flows
Critical: Next.js 16 Uses Proxy, NOT Middleware
IMPORTANT: Next.js 16 introduced the proxy pattern which replaces the traditional middleware.ts for Clerk.
| Next.js Version | File Name | Runtime |
|---|---|---|
| 15 and earlier | middleware.ts | Edge Runtime |
| 16+ | proxy.ts | Node.js Runtime |
The proxy pattern provides:
- Full Node.js runtime (not Edge limitations)
- Better async/await support
- Access to all Node.js APIs
- Improved performance
Quick Start
1. Authentication Check in Server Actions
"use server";
import { auth } from "@clerk/nextjs/server";
import type { ActionResponse } from "~/lib/action-types";
export async function myAction(data: InputType): ActionResponse<OutputType> {
// 1. Always check authentication first
const { userId } = await auth();
if (!userId) {
return { success: false, error: "Authentication required" };
}
// 2. Your business logic here
// ...
}
2. Authentication Check in Page Loaders
import { auth } from "@clerk/nextjs/server";
import { redirect, unauthorized } from "next/navigation";
async function loadData() {
const { userId, isAuthenticated, sessionClaims } = await auth();
if (!isAuthenticated) {
return unauthorized();
}
// Check custom session claims
if (sessionClaims?.metadata.onboardingComplete !== true) {
redirect("/onboarding");
}
// Load user data...
}
3. Updating User Metadata
import { clerkClient } from "@clerk/nextjs/server";
const client = await clerkClient();
await client.users.updateUser(userId, {
publicMetadata: {
onboardingComplete: true,
role: "user",
},
});
Key Concepts
Authentication Object
The auth() function returns:
interface AuthObject {
userId: string | null; // Clerk user ID
isAuthenticated: boolean; // Is user logged in
sessionClaims: CustomJwtSessionClaims | null; // Custom claims
redirectToSignIn: (opts?) => Response; // Redirect helper
}
Session Claims Type Definition
Define custom claims in types/clerk.d.ts:
export {};
declare global {
interface CustomJwtSessionClaims {
metadata: {
onboardingComplete?: boolean;
role?: "user" | "admin";
};
}
}
Public vs Private Metadata
| Type | Visibility | Use Case |
|---|---|---|
publicMetadata | Included in session token, readable on client | Onboarding status, roles, preferences |
privateMetadata | Server-only, never sent to client | Internal flags, sensitive data |
unsafeMetadata | User-editable via Clerk components | Profile preferences, settings |
File Locations
| Purpose | File |
|---|---|
| Proxy configuration | proxy.ts (root) |
| Session claims types | types/clerk.d.ts |
| Auth helpers | features/auth/server/db/user.ts |
| Providers setup | components/providers.tsx |
Common Patterns
Protected Server Action
"use server";
import { auth } from "@clerk/nextjs/server";
export async function protectedAction(): ActionResponse {
const { userId, isAuthenticated } = await auth();
if (!isAuthenticated || !userId) {
return { success: false, error: "Unauthorized" };
}
// Action logic...
}
Protected Page with Redirect
import { auth } from "@clerk/nextjs/server";
import { redirect } from "next/navigation";
export default async function ProtectedPage() {
const { userId } = await auth();
if (!userId) {
redirect("/sign-in");
}
// Page content...
}
Onboarding Gate Pattern
See onboarding-gate.md for complete implementation.
Security Checklist
When implementing authentication:
- Always verify
userId- Never trust client-provided user IDs - Check authorization - Verify user owns the resource they're accessing
- Use
server-only- Mark auth modules withserver-onlypackage - Log auth events - Log authentication failures for security monitoring
- Handle edge cases - Expired sessions, revoked tokens
Running and Testing
# Type check
npm run type-check
# Run auth-related tests
npm run test -- features/auth
# E2E tests with authentication
npm run test:e2e
Related Skills
server-actions- For implementing server actions with auth checksfirebase-firestore- For database operations after authentication
Source
git clone https://github.com/JanSzewczyk/claude-plugins/blob/main/plugins/firebase-auth/skills/clerk-auth-proxy/SKILL.mdView on GitHub Overview
This skill implements Clerk authentication in Next.js 16 using the proxy pattern (not middleware). It covers session claims, onboarding gates, and updating user metadata to support authentication, authorization, and user session management.
How This Skill Works
Next.js 16 uses a proxy.ts file (proxy pattern) instead of middleware.ts. The server can call auth() from @clerk/nextjs/server to get userId, isAuthenticated, and sessionClaims, and you update user data with clerkClient().users.updateUser. Custom claims are defined in types/clerk.d.ts to drive onboarding and roles, with publicMetadata and sessionClaims guiding access.
When to Use It
- Protect a server action with an authentication check
- Gate onboarding for new users before full access
- Enforce role-based access for admin vs user
- Update user metadata after completing a flow
- Create a protected route with session-based access
Quick Start
- Step 1: Authentication Check in Server Actions – verify userId via auth() and bail if unauthenticated
- Step 2: Authentication Check in Page Loaders – ensure isAuthenticated, check sessionClaims, and redirect if needed
- Step 3: Updating User Metadata – use clerkClient to update publicMetadata or session claims after user completes a flow
Best Practices
- Call auth() at the start of server actions and loaders to verify authentication
- Check userId and isAuthenticated before proceeding with business logic
- Use sessionClaims.metadata to gate onboarding and role-based flows
- Update user metadata via clerkClient().users.updateUser when state changes
- Prefer the Next.js 16 proxy pattern (proxy.ts) over middleware.ts and keep logic in server context
Example Use Cases
- Add authentication check to a server action
- Implement onboarding gate for new users
- Update user metadata after completing a flow
- Create protected route with role-based access
Frequently Asked Questions
Related Skills
proxy
chaterm/terminal-skills
代理服务器配置
nginx
chaterm/terminal-skills
Nginx configuration and optimization
onboarding-cro
coreyhaines31/marketingskills
When the user wants to optimize post-signup onboarding, user activation, first-run experience, or time-to-value. Also use when the user mentions "onboarding flow," "activation rate," "user activation," "first-run experience," "empty states," "onboarding checklist," "aha moment," "new user experience," "users aren't activating," "nobody completes setup," "low activation rate," "users sign up but don't use the product," "time to value," or "first session experience." Use this whenever users are signing up but not sticking around. For signup/registration optimization, see signup-flow-cro. For ongoing email sequences, see email-sequence.
signup-flow-cro
coreyhaines31/marketingskills
When the user wants to optimize signup, registration, account creation, or trial activation flows. Also use when the user mentions "signup conversions," "registration friction," "signup form optimization," "free trial signup," "reduce signup dropoff," "account creation flow," "people aren't signing up," "signup abandonment," "trial conversion rate," "nobody completes registration," "too many steps to sign up," or "simplify our signup." Use this whenever the user has a signup or registration flow that isn't performing. For post-signup onboarding, see onboarding-cro. For lead capture forms (not account creation), see form-cro.
convex-security-check
waynesutton/convexskills
Quick security audit checklist covering authentication, function exposure, argument validation, row-level access control, and environment variable handling
explain-codebase
suryast/free-ai-agent-skills
Drop into any repo and generate a structured architecture overview. Maps the codebase, identifies entry points, frameworks, and dependencies — then produces a "start here" guide for new contributors.