Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Clerk auth with API Keys beta (Dec 2025), Next.js 16 proxy.ts (March 2025 CVE context), API version 2025-11-10 breaking changes, clerkMiddleware() options, webhooks, production considerations (GCP outages), and component reference. Prevents 15 documented errors. Use when: API keys for users/orgs, Next.js 16 middleware filename, troubleshooting JWKS/CSRF/JWT/token-type-mismatch errors, webhook verification, user type inconsistencies, or testing with 424242 OTP.
Clerk auth with API Keys beta (Dec 2025), Next.js 16 proxy.ts (March 2025 CVE context), API version 2025-11-10 breaking changes, clerkMiddleware() options, webhooks, production considerations (GCP outages), and component reference. Prevents 15 documented errors. Use when: API keys for users/orgs, Next.js 16 middleware filename, troubleshooting JWKS/CSRF/JWT/token-type-mismatch errors, webhook verification, user type inconsistencies, or testing with 424242 OTP.
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.
Package Versions: @clerk/nextjs@6.36.7, @clerk/backend@2.29.2, @clerk/clerk-react@5.59.2, @clerk/testing@1.13.26 Breaking Changes: Nov 2025 - API version 2025-11-10, Oct 2024 - Next.js v6 async auth() Last Updated: 2026-01-09
User-scoped and organization-scoped API keys for your application. Zero-code UI component. // 1. Add the component for self-service API key management import { APIKeys } from '@clerk/nextjs' export default function SettingsPage() { return ( <div> <h2>API Keys</h2> <APIKeys /> {/* Full CRUD UI for user's API keys */} </div> ) } Backend Verification: import { verifyToken } from '@clerk/backend' // API keys are verified like session tokens const { data, error } = await verifyToken(apiKey, { secretKey: process.env.CLERK_SECRET_KEY, authorizedParties: ['https://yourdomain.com'], }) // Check token type if (data?.tokenType === 'api_key') { // Handle API key auth } clerkMiddleware Token Types: // v6.36.0+: Middleware can distinguish token types clerkMiddleware((auth, req) => { const { userId, tokenType } = auth() if (tokenType === 'api_key') { // API key auth - programmatic access } else if (tokenType === 'session_token') { // Regular session - web UI access } }) Pricing (Beta = Free): Creation: $0.001/key Verification: $0.0001/verification
โ ๏ธ BREAKING: Next.js 16 changed middleware filename due to critical security vulnerability (CVE disclosed March 2025). Background: The March 2025 vulnerability (affecting Next.js 11.1.4-15.2.2) allowed attackers to completely bypass middleware-based authorization by adding a single HTTP header: x-middleware-subrequest: true. This affected all auth libraries (NextAuth, Clerk, custom solutions). Why the Rename: The middleware.ts โ proxy.ts change isn't just cosmetic - it's Next.js signaling that middleware-first security patterns are dangerous. Future auth implementations should not rely solely on middleware for authorization. Next.js 15 and earlier: middleware.ts Next.js 16+: proxy.ts Correct Setup for Next.js 16: // src/proxy.ts (NOT middleware.ts!) import { clerkMiddleware } from '@clerk/nextjs/server' export default clerkMiddleware() export const config = { matcher: [ '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)', '/(api|trpc)(.*)', ], } Minimum Version: @clerk/nextjs@6.35.0+ required for Next.js 16 (fixes Turbopack build errors and cache invalidation on sign-out).
Administrators can mark passwords as compromised and force reset: import { clerkClient } from '@clerk/backend' // Force password reset for a user await clerkClient.users.updateUser(userId, { passwordDigest: 'compromised', // Triggers reset on next sign-in })
Dashboard now includes org creation metrics and filtering by name/slug/date.
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 // 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
Affects: All Next.js Server Components using auth() // โ OLD (v5 - synchronous) const { userId } = auth() // โ NEW (v6 - asynchronous) const { userId } = await auth() Also affects: auth.protect() is now async in middleware // โ OLD (v5) auth.protect() // โ NEW (v6) await auth.protect() Compatibility: Next.js 15, 16 supported. Static rendering by default.
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.
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.
@clerk/nextjs v6.35.2+ includes cache invalidation improvements for Next.js 16 during sign-out.
Pattern: 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> }
CRITICAL: Always set authorizedParties to prevent CSRF attacks 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
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server' // Define protected routes const isProtectedRoute = createRouteMatcher([ '/dashboard(.*)', '/api/private(.*)', ]) const isAdminRoute = createRouteMatcher(['/admin(.*)']) export default clerkMiddleware(async (auth, req) => { // Protect routes if (isProtectedRoute(req)) { await auth.protect() // Redirects unauthenticated users } // Require specific permissions if (isAdminRoute(req)) { await auth.protect({ role: 'org:admin', // Requires organization admin role }) } })
OptionTypeDescriptiondebugbooleanEnable debug loggingjwtKeystringJWKS public key for networkless verificationclockSkewInMsnumberToken time variance (default: 5000ms)organizationSyncOptionsobjectURL-based org activationsignInUrlstringCustom sign-in URLsignUpUrlstringCustom sign-up URL
โ ๏ธ Next.js Only: This feature currently only works with clerkMiddleware() in Next.js. It does NOT work with authenticateRequest() in other runtimes (Cloudflare Workers, Express, etc.) due to Sec-Fetch-Dest header checks. Source: GitHub Issue #7178 clerkMiddleware({ organizationSyncOptions: { organizationPatterns: ['/orgs/:slug', '/orgs/:slug/(.*)'], personalAccountPatterns: ['/personal', '/personal/(.*)'], }, })
import { Webhook } from 'svix' export async function POST(req: Request) { const payload = await req.text() const headers = { 'svix-id': req.headers.get('svix-id')!, 'svix-timestamp': req.headers.get('svix-timestamp')!, 'svix-signature': req.headers.get('svix-signature')!, } const wh = new Webhook(process.env.CLERK_WEBHOOK_SIGNING_SECRET!) try { const event = wh.verify(payload, headers) // Process event return Response.json({ success: true }) } catch (err) { return Response.json({ error: 'Invalid signature' }, { status: 400 }) } }
EventTriggeruser.createdNew user signs upuser.updatedUser profile changesuser.deletedUser account deletedsession.createdNew sign-insession.endedSign-outorganization.createdNew org createdorganization.membership.createdUser joins org โ ๏ธ Important: Webhook routes must be PUBLIC (no auth). Add to middleware exclude list: const isPublicRoute = createRouteMatcher([ '/api/webhooks/clerk(.*)', // Clerk webhooks are public ]) clerkMiddleware((auth, req) => { if (!isPublicRoute(req)) { auth.protect() } })
ComponentPurpose<SignIn />Full sign-in flow<SignUp />Full sign-up flow<SignInButton />Trigger sign-in modal<SignUpButton />Trigger sign-up modal<SignedIn>Render only when authenticated<SignedOut>Render only when unauthenticated<UserButton />User menu with sign-out<UserProfile />Full profile management<OrganizationSwitcher />Switch between orgs<OrganizationProfile />Org settings<CreateOrganization />Create new org<APIKeys />API key management (NEW)
HookReturnsuseAuth(){ userId, sessionId, isLoaded, isSignedIn, getToken }useUser(){ user, isLoaded, isSignedIn }useClerk()Clerk instance with methodsuseSession()Current session objectuseOrganization()Current org contextuseOrganizationList()All user's orgs
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 for solution. Solution: // โ 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.
CategoryShortcodesExampleUser 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}}trueMetadata{{user.public_metadata}}, {{user.public_metadata.FIELD}}{"role": "admin"}Organizationorg_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
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)
Script (scripts/generate-session-token.js): # 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: Create user: POST /v1/users Create session: POST /v1/sessions Generate token: POST /v1/sessions/{session_id}/tokens Use in header: Authorization: Bearer <token>
Install @clerk/testing for automatic Testing Token management: npm install -D @clerk/testing Global Setup (global.setup.ts): import { clerkSetup } from '@clerk/testing/playwright' import { test as setup } from '@playwright/test' setup('global setup', async ({}) => { await clerkSetup() }) Test File (auth.spec.ts): 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
This skill prevents 15 documented issues:
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
Error: "apiKey is deprecated, use secretKey" Source: https://clerk.com/docs/upgrade-guides/core-2/backend Prevention: Replace apiKey with secretKey in all calls
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)
Error: No error, but CSRF vulnerability Source: https://clerk.com/docs/reference/backend/verify-token Prevention: Always set authorizedParties: ['https://yourdomain.com']
Error: "Cannot find module" Source: https://clerk.com/docs/upgrade-guides/core-2/backend Prevention: Update import paths for Core 2
Error: Token exceeds size limit Source: https://clerk.com/docs/backend-requests/making/custom-session-token Prevention: Keep custom claims under 1.2KB
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)
Error: "cannot be used as a JSX component" Source: https://stackoverflow.com/questions/79265537 Prevention: Ensure React 19 compatibility with @clerk/clerk-react@5.59.2+
Error: "auth() is not a function" Source: https://clerk.com/changelog/2024-10-22-clerk-nextjs-v6 Prevention: Always await: const { userId } = await auth()
Error: "Missing Publishable Key" or secret leaked Prevention: Use correct prefixes (NEXT_PUBLIC_, VITE_), never commit secrets
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: { "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).
Error: TypeScript errors when sharing user utilities across client/server Source: GitHub Issue #2176 Why It Happens: useUser() returns UserResource (client-side) with different properties than currentUser() returns User (server-side). Client has fullName, primaryEmailAddress object; server has primaryEmailAddressId and privateMetadata instead. Prevention: Use shared properties only, or create separate utility functions for client vs server contexts. // โ CORRECT: Use properties that exist in both const primaryEmailAddress = user.emailAddresses.find( ({ id }) => id === user.primaryEmailAddressId ) // โ CORRECT: Separate types type ClientUser = ReturnType<typeof useUser>['user'] type ServerUser = Awaited<ReturnType<typeof currentUser>>
Error: "token-type-mismatch" when using authenticateRequest() with multiple token types Source: GitHub Issue #7520 Why It Happens: When using authenticateRequest() with multiple acceptsToken values (e.g., ['session_token', 'api_key']), Clerk incorrectly throws token-type-mismatch error. Prevention: Upgrade to @clerk/backend@2.29.2+ (fix available in snapshot, releasing soon). // This now works in @clerk/backend@2.29.2+ const result = await authenticateRequest(request, { acceptsToken: ['session_token', 'api_key'], // Fixed! })
Error: Server crashes with URL parsing error Source: GitHub Issue #7275 Why It Happens: Internal deriveUrlFromHeaders() function performs unsafe URL parsing and crashes the entire server when receiving malformed URLs in headers (e.g., x-forwarded-host: 'example.com[invalid]'). This is a denial-of-service vulnerability. Prevention: Upgrade to @clerk/backend@2.29.0+ (fixed).
Error: None - optional parameter for edge case handling Source: Changelog @clerk/nextjs@6.32.0 Why It Exists: Sessions can have a pending status during certain flows (e.g., credential stuffing defense secondary auth). By default, pending sessions are treated as signed-out (user is null). Usage: Set treatPendingAsSignedOut: false to treat pending as signed-in (available in @clerk/nextjs@6.32.0+). // Default: pending = signed out const user = await currentUser() // null if status is 'pending' // Treat pending as signed in const user = await currentUser({ treatPendingAsSignedOut: false }) // defined if pending
Context: Clerk experienced 3 major service disruptions in May-June 2025 attributed to Google Cloud Platform (GCP) outages. The June 26, 2025 outage lasted 45 minutes (6:16-7:01 UTC) and affected all Clerk customers. Source: Clerk Postmortem: June 26, 2025 Mitigation Strategies: Monitor Clerk Status for real-time updates Implement graceful degradation when Clerk API is unavailable Cache auth tokens locally where possible For existing sessions, use jwtKey option for networkless verification: clerkMiddleware({ jwtKey: process.env.CLERK_JWT_KEY, // Allows offline token verification }) Note: During total outage, no new sessions can be created (auth requires Clerk API). However, existing sessions can continue working if you verify JWTs locally with jwtKey. Clerk committed to exploring multi-cloud redundancy to reduce single-vendor dependency risk.
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
Latest (Nov 22, 2025): { "dependencies": { "@clerk/nextjs": "^6.36.7", "@clerk/clerk-react": "^5.59.2", "@clerk/backend": "^2.29.2", "@clerk/testing": "^1.13.26" } } Token Efficiency: Without skill: ~6,500 tokens (setup tutorials, JWT templates, testing setup, webhooks, production considerations) With skill: ~3,200 tokens (breaking changes + critical patterns + error prevention + production guidance) Savings: ~51% (~3,300 tokens) Errors prevented: 15 documented issues with exact solutions Key value: API Keys beta, Next.js 16 proxy.ts (with March 2025 CVE context), clerkMiddleware() options, webhooks, component reference, API 2025-11-10 breaking changes, JWT size limits, user type mismatches, production considerations (GCP outages, jwtKey offline verification) Last verified: 2026-01-20 | Skill version: 3.1.0 | Changes: Added 4 new Known Issues (#12-15: user type mismatch, acceptsToken type mismatch, deriveUrlFromHeaders crash, treatPendingAsSignedOut option), expanded proxy.ts section with March 2025 CVE security context, added Production Considerations section (GCP outages + mitigation), added organizationSyncOptions Next.js-only limitation note, updated minimum version requirements for Next.js 16 (6.35.0+).
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.