Claude
Skills
Sign in
Back

clerk-auth

Included with Lifetime
$97 forever

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.

Web Devscriptsassets

What this skill does


# Clerk Auth - Breaking Changes & Error Prevention Guide

**Package Versions**: @clerk/[email protected], @clerk/[email protected], @clerk/[email protected], @clerk/[email protected]
**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}}` | `"[email protected]"` |
| **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):
```
[email protected]
[email protected]
```

**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"]', '[email protected]')
  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
Files: 26
Size: 107.8 KB
Complexity: 96/100
Category: Web Dev

Related in Web Dev