clerk-auth
Clerk auth with API version 2025-11-10 breaking changes (billing endpoints, payment_source→payment_method), Next.js v6 async auth(), PKCE for custom OAuth, credential stuffing defense. Use when: troubleshooting "Missing Clerk Secret Key", JWKS errors, authorizedParties CSRF, JWT size limits (1.2KB), 431 header errors (Vite dev mode), or testing with 424242 OTP.
Best use case
clerk-auth is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Clerk auth with API version 2025-11-10 breaking changes (billing endpoints, payment_source→payment_method), Next.js v6 async auth(), PKCE for custom OAuth, credential stuffing defense. Use when: troubleshooting "Missing Clerk Secret Key", JWKS errors, authorizedParties CSRF, JWT size limits (1.2KB), 431 header errors (Vite dev mode), or testing with 424242 OTP.
Teams using clerk-auth should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/clerk-auth/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How clerk-auth Compares
| Feature / Agent | clerk-auth | 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?
Clerk auth with API version 2025-11-10 breaking changes (billing endpoints, payment_source→payment_method), Next.js v6 async auth(), PKCE for custom OAuth, credential stuffing defense. Use when: troubleshooting "Missing Clerk Secret Key", JWKS errors, authorizedParties CSRF, JWT size limits (1.2KB), 431 header errors (Vite dev mode), or testing with 424242 OTP.
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
# Clerk Auth - Breaking Changes & Error Prevention Guide
**Package Versions**: @clerk/nextjs@6.35.4, @clerk/backend@2.23.2, @clerk/clerk-react@5.56.2, @clerk/testing@1.13.18
**Breaking Changes**: Nov 2025 - API version 2025-11-10, Oct 2024 - Next.js v6 async auth()
**Last Updated**: 2025-11-22
---
## What's New in v6.35.x & API 2025-11-10 (Nov 2025)
### 1. API Version 2025-11-10 (Nov 10, 2025) - BREAKING CHANGES ⚠️
**Affects:** Applications using Clerk Billing/Commerce APIs
**Critical Changes:**
- **Endpoint URLs:** `/commerce/` → `/billing/` (30+ endpoints)
```
GET /v1/commerce/plans → GET /v1/billing/plans
GET /v1/commerce/statements → GET /v1/billing/statements
POST /v1/me/commerce/checkouts → POST /v1/me/billing/checkouts
```
- **Field Terminology:** `payment_source` → `payment_method`
```typescript
// OLD (deprecated)
{ payment_source_id: "...", payment_source: {...} }
// NEW (required)
{ payment_method_id: "...", payment_method: {...} }
```
- **Removed Fields:** Plans responses no longer include:
- `amount`, `amount_formatted` (use `fee.amount` instead)
- `currency`, `currency_symbol` (use fee objects)
- `payer_type` (use `for_payer_type`)
- `annual_monthly_amount`, `annual_amount`
- **Removed Endpoints:**
- Invoices endpoint (use statements)
- Products endpoint
- **Null Handling:** Explicit rules - `null` means "doesn't exist", omitted means "not asserting existence"
**Migration:** Update SDK to v6.35.0+ which includes support for API version 2025-11-10.
**Official Guide:** https://clerk.com/docs/guides/development/upgrading/upgrade-guides/2025-11-10
### 2. Next.js v6 Async auth() (Oct 2024) - BREAKING CHANGE ⚠️
**Affects:** All Next.js Server Components using `auth()`
```typescript
// ❌ OLD (v5 - synchronous)
const { userId } = auth()
// ✅ NEW (v6 - asynchronous)
const { userId } = await auth()
```
**Also affects:** `auth.protect()` is now async in middleware
```typescript
// ❌ OLD (v5)
auth.protect()
// ✅ NEW (v6)
await auth.protect()
```
**Compatibility:** Next.js 15, 16 supported. Static rendering by default.
### 3. PKCE Support for Custom OAuth (Nov 12, 2025)
Custom OIDC providers and social connections now support PKCE (Proof Key for Code Exchange) for enhanced security in native/mobile applications where client secrets cannot be safely stored.
**Use case:** Mobile apps, native apps, public clients that can't securely store secrets.
### 4. Client Trust: Credential Stuffing Defense (Nov 14, 2025)
Automatic secondary authentication when users sign in from unrecognized devices:
- Activates for users with valid passwords but no 2FA
- No configuration required
- Included in all Clerk plans
**How it works:** Clerk automatically prompts for additional verification (email code, backup code) when detecting sign-in from new device.
### 5. Next.js 16 Support (Nov 2025)
**@clerk/nextjs v6.35.2+** includes cache invalidation improvements for Next.js 16 during sign-out.
---
## Critical Patterns & Error Prevention
### Next.js v6: Async auth() Helper
**Pattern:**
```typescript
import { auth } from '@clerk/nextjs/server'
export default async function Page() {
const { userId } = await auth() // ← Must await
if (!userId) {
return <div>Unauthorized</div>
}
return <div>User ID: {userId}</div>
}
```
### Cloudflare Workers: authorizedParties (CSRF Prevention)
**CRITICAL:** Always set `authorizedParties` to prevent CSRF attacks
```typescript
import { verifyToken } from '@clerk/backend'
const { data, error } = await verifyToken(token, {
secretKey: c.env.CLERK_SECRET_KEY,
// REQUIRED: Prevent CSRF attacks
authorizedParties: ['https://yourdomain.com'],
})
```
**Why:** Without `authorizedParties`, attackers can use valid tokens from other domains.
**Source:** https://clerk.com/docs/reference/backend/verify-token
---
## JWT Templates - Size Limits & Shortcodes
### JWT Size Limitation: 1.2KB for Custom Claims ⚠️
**Problem**: Browser cookies limited to 4KB. Clerk's default claims consume ~2.8KB, leaving **1.2KB for custom claims**.
**⚠️ Development Note**: When testing custom JWT claims in Vite dev mode, you may encounter **"431 Request Header Fields Too Large"** error. This is caused by Clerk's handshake token in the URL exceeding Vite's 8KB limit. See [Issue #11](#issue-11-431-request-header-fields-too-large-vite-dev-mode) for solution.
**Solution:**
```json
// ✅ GOOD: Minimal claims
{
"user_id": "{{user.id}}",
"email": "{{user.primary_email_address}}",
"role": "{{user.public_metadata.role}}"
}
// ❌ BAD: Exceeds limit
{
"bio": "{{user.public_metadata.bio}}", // 6KB field
"all_metadata": "{{user.public_metadata}}" // Entire object
}
```
**Best Practice**: Store large data in database, include only identifiers/roles in JWT.
### Available Shortcodes Reference
| Category | Shortcodes | Example |
|----------|-----------|---------|
| **User ID & Name** | `{{user.id}}`, `{{user.first_name}}`, `{{user.last_name}}`, `{{user.full_name}}` | `"John Doe"` |
| **Contact** | `{{user.primary_email_address}}`, `{{user.primary_phone_address}}` | `"john@example.com"` |
| **Profile** | `{{user.image_url}}`, `{{user.username}}`, `{{user.created_at}}` | `"https://..."` |
| **Verification** | `{{user.email_verified}}`, `{{user.phone_number_verified}}` | `true` |
| **Metadata** | `{{user.public_metadata}}`, `{{user.public_metadata.FIELD}}` | `{"role": "admin"}` |
| **Organization** | `org_id`, `org_slug`, `org_role` (in sessionClaims) | `"org:admin"` |
**Advanced Features:**
- **String Interpolation**: `"{{user.last_name}} {{user.first_name}}"`
- **Conditional Fallbacks**: `"{{user.public_metadata.role || 'user'}}"`
- **Nested Metadata**: `"{{user.public_metadata.profile.interests}}"`
**Official Docs**: https://clerk.com/docs/guides/sessions/jwt-templates
---
## Testing with Clerk
### Test Credentials (Fixed OTP: 424242)
**Test Emails** (no emails sent, fixed OTP):
```
john+clerk_test@example.com
jane+clerk_test@gmail.com
```
**Test Phone Numbers** (no SMS sent, fixed OTP):
```
+12015550100
+19735550133
```
**Fixed OTP Code**: `424242` (works for all test credentials)
### Generate Session Tokens (60-second lifetime)
**Script** (`scripts/generate-session-token.js`):
```bash
# Generate token
CLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js
# Create new test user
CLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js --create-user
# Auto-refresh token every 50 seconds
CLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js --refresh
```
**Manual Flow**:
1. Create user: `POST /v1/users`
2. Create session: `POST /v1/sessions`
3. Generate token: `POST /v1/sessions/{session_id}/tokens`
4. Use in header: `Authorization: Bearer <token>`
### E2E Testing with Playwright
Install `@clerk/testing` for automatic Testing Token management:
```bash
npm install -D @clerk/testing
```
**Global Setup** (`global.setup.ts`):
```typescript
import { clerkSetup } from '@clerk/testing/playwright'
import { test as setup } from '@playwright/test'
setup('global setup', async ({}) => {
await clerkSetup()
})
```
**Test File** (`auth.spec.ts`):
```typescript
import { setupClerkTestingToken } from '@clerk/testing/playwright'
import { test } from '@playwright/test'
test('sign up', async ({ page }) => {
await setupClerkTestingToken({ page })
await page.goto('/sign-up')
await page.fill('input[name="emailAddress"]', 'test+clerk_test@example.com')
await page.fill('input[name="password"]', 'TestPassword123!')
await page.click('button[type="submit"]')
// Verify with fixed OTP
await page.fill('input[name="code"]', '424242')
await page.click('button[type="submit"]')
await expect(page).toHaveURL('/dashboard')
})
```
**Official Docs**: https://clerk.com/docs/guides/development/testing/overview
---
## Known Issues Prevention
This skill prevents **11 documented issues**:
### Issue #1: Missing Clerk Secret Key
**Error**: "Missing Clerk Secret Key or API Key"
**Source**: https://stackoverflow.com/questions/77620604
**Prevention**: Always set in `.env.local` or via `wrangler secret put`
### Issue #2: API Key → Secret Key Migration
**Error**: "apiKey is deprecated, use secretKey"
**Source**: https://clerk.com/docs/upgrade-guides/core-2/backend
**Prevention**: Replace `apiKey` with `secretKey` in all calls
### Issue #3: JWKS Cache Race Condition
**Error**: "No JWK available"
**Source**: https://github.com/clerk/javascript/blob/main/packages/backend/CHANGELOG.md
**Prevention**: Use @clerk/backend@2.17.2 or later (fixed)
### Issue #4: Missing authorizedParties (CSRF)
**Error**: No error, but CSRF vulnerability
**Source**: https://clerk.com/docs/reference/backend/verify-token
**Prevention**: Always set `authorizedParties: ['https://yourdomain.com']`
### Issue #5: Import Path Changes (Core 2)
**Error**: "Cannot find module"
**Source**: https://clerk.com/docs/upgrade-guides/core-2/backend
**Prevention**: Update import paths for Core 2
### Issue #6: JWT Size Limit Exceeded
**Error**: Token exceeds size limit
**Source**: https://clerk.com/docs/backend-requests/making/custom-session-token
**Prevention**: Keep custom claims under 1.2KB
### Issue #7: Deprecated API Version v1
**Error**: "API version v1 is deprecated"
**Source**: https://clerk.com/docs/upgrade-guides/core-2/backend
**Prevention**: Use latest SDK versions (API v2025-11-10)
### Issue #8: ClerkProvider JSX Component Error
**Error**: "cannot be used as a JSX component"
**Source**: https://stackoverflow.com/questions/79265537
**Prevention**: Ensure React 19 compatibility with @clerk/clerk-react@5.56.2+
### Issue #9: Async auth() Helper Confusion
**Error**: "auth() is not a function"
**Source**: https://clerk.com/changelog/2024-10-22-clerk-nextjs-v6
**Prevention**: Always await: `const { userId } = await auth()`
### Issue #10: Environment Variable Misconfiguration
**Error**: "Missing Publishable Key" or secret leaked
**Prevention**: Use correct prefixes (`NEXT_PUBLIC_`, `VITE_`), never commit secrets
### Issue #11: 431 Request Header Fields Too Large (Vite Dev Mode)
**Error**: "431 Request Header Fields Too Large" when signing in
**Source**: Common in Vite dev mode when testing custom JWT claims
**Cause**: Clerk's `__clerk_handshake` token in URL exceeds Vite's 8KB header limit
**Prevention**:
Add to `package.json`:
```json
{
"scripts": {
"dev": "NODE_OPTIONS='--max-http-header-size=32768' vite"
}
}
```
**Temporary Workaround**: Clear browser cache, sign out, sign back in
**Why**: Clerk dev tokens are larger than production; custom JWT claims increase handshake token size
**Note**: This is different from Issue #6 (session token size). Issue #6 is about cookies (1.2KB), this is about URL parameters in dev mode (8KB → 32KB).
---
## Official Documentation
- **Clerk Docs**: https://clerk.com/docs
- **Next.js Guide**: https://clerk.com/docs/references/nextjs/overview
- **React Guide**: https://clerk.com/docs/references/react/overview
- **Backend SDK**: https://clerk.com/docs/reference/backend/overview
- **JWT Templates**: https://clerk.com/docs/guides/sessions/jwt-templates
- **API Version 2025-11-10 Upgrade**: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/2025-11-10
- **Testing Guide**: https://clerk.com/docs/guides/development/testing/overview
- **Context7 Library ID**: `/clerk/clerk-docs`
---
## Package Versions
**Latest (Nov 22, 2025):**
```json
{
"dependencies": {
"@clerk/nextjs": "^6.35.4",
"@clerk/clerk-react": "^5.56.2",
"@clerk/backend": "^2.23.2",
"@clerk/testing": "^1.13.18"
}
}
```
---
**Token Efficiency**:
- **Without skill**: ~5,200 tokens (setup tutorials, JWT templates, testing setup)
- **With skill**: ~2,500 tokens (breaking changes + critical patterns + error prevention)
- **Savings**: ~52% (~2,700 tokens)
**Errors prevented**: 11 documented issues with exact solutions
**Key value**: API 2025-11-10 breaking changes, Next.js v6 async auth(), PKCE for custom OAuth, credential stuffing defense, JWT size limits, 431 header error workaround
---
**Last verified**: 2025-11-22 | **Skill version**: 2.0.0 | **Changes**: Added API version 2025-11-10 breaking changes (billing endpoints), PKCE support, Client Trust defense, Next.js 16 support. Removed tutorials (~480 lines). Updated SDK versions. Focused on breaking changes + error prevention + critical patterns.Related Skills
better-auth
Build authentication systems for TypeScript/Cloudflare Workers with social auth, 2FA, passkeys, organizations, and RBAC. Self-hosted alternative to Clerk/Auth.js. IMPORTANT: Requires Drizzle ORM or Kysely for D1 - no direct D1 adapter. v1.4.0 (Nov 2025) adds stateless sessions, ESM-only (breaking), JWT key rotation, SCIM provisioning. v1.3 adds SSO/SAML, multi-team support. Use when: self-hosting auth on Cloudflare D1, migrating from Clerk, implementing multi-tenant SaaS, or troubleshooting D1 adapter errors, session serialization, OAuth flows, TanStack Start cookie issues, nanostore session invalidation.
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.
zustand-state-management
Build type-safe global state in React applications with Zustand. Supports TypeScript, persist middleware, devtools, slices pattern, and Next.js SSR. Use when setting up React state, migrating from Redux/Context API, implementing localStorage persistence, or troubleshooting Next.js hydration errors, TypeScript inference issues, or infinite render loops.
zinc-database
Access ZINC (230M+ purchasable compounds). Search by ZINC ID/SMILES, similarity searches, 3D-ready structures for docking, analog discovery, for virtual screening and drug discovery.
zarr-python
Chunked N-D arrays for cloud storage. Compressed arrays, parallel I/O, S3/GCS integration, NumPy/Dask/Xarray compatible, for large-scale scientific computing pipelines.
youtube-transcript
Download YouTube video transcripts when user provides a YouTube URL or asks to download/get/fetch a transcript from YouTube. Also use when user wants to transcribe or get captions/subtitles from a YouTube video.
xlsx
Comprehensive spreadsheet creation, editing, and analysis with support for formulas, formatting, data analysis, and visualization. When Claude needs to work with spreadsheets (.xlsx, .xlsm, .csv, .tsv, etc) for: (1) Creating new spreadsheets with formulas and formatting, (2) Reading or analyzing data, (3) Modify existing spreadsheets while preserving formulas, (4) Data analysis and visualization in spreadsheets, or (5) Recalculating formulas
wordpress-plugin-core
Build secure WordPress plugins with core patterns for hooks, database interactions, Settings API, custom post types, REST API, and AJAX. Covers three architecture patterns (Simple, OOP, PSR-4) and the Security Trinity. Use when creating plugins, implementing nonces/sanitization/escaping, working with $wpdb prepared statements, or troubleshooting SQL injection, XSS, CSRF vulnerabilities, or plugin activation errors.
whisper
OpenAI's general-purpose speech recognition model. Supports 99 languages, transcription, translation to English, and language identification. Six model sizes from tiny (39M params) to large (1550M params). Use for speech-to-text, podcast transcription, or multilingual audio processing. Best for robust, multilingual ASR.
weights-and-biases
Track ML experiments with automatic logging, visualize training in real-time, optimize hyperparameters with sweeps, and manage model registry with W&B - collaborative MLOps platform
webapp-testing
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
serving-llms-vllm
Serves LLMs with high throughput using vLLM's PagedAttention and continuous batching. Use when deploying production LLM APIs, optimizing inference latency/throughput, or serving models with limited GPU memory. Supports OpenAI-compatible endpoints, quantization (GPTQ/AWQ/FP8), and tensor parallelism.