{
  "schemaVersion": "1.0",
  "item": {
    "slug": "clerk-auth",
    "name": "Clerk Auth",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/Veeramanikandanr48/clerk-auth",
    "canonicalUrl": "https://clawhub.ai/Veeramanikandanr48/clerk-auth",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/clerk-auth",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=clerk-auth",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      ".claude-plugin/plugin.json",
      "README.md",
      "SKILL.md",
      "agents/clerk-setup.md",
      "assets/example-template.txt",
      "commands/setup.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "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."
        },
        {
          "label": "Upgrade existing",
          "body": "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."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/clerk-auth"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/clerk-auth",
    "agentPageUrl": "https://openagent3.xyz/skills/clerk-auth/agent",
    "manifestUrl": "https://openagent3.xyz/skills/clerk-auth/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/clerk-auth/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "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."
      },
      {
        "label": "Upgrade existing",
        "body": "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."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Clerk Auth - Breaking Changes & Error Prevention Guide",
        "body": "Package Versions: @clerk/nextjs@6.36.7, @clerk/backend@2.29.2, @clerk/clerk-react@5.59.2, @clerk/testing@1.13.26\nBreaking Changes: Nov 2025 - API version 2025-11-10, Oct 2024 - Next.js v6 async auth()\nLast Updated: 2026-01-09"
      },
      {
        "title": "1. API Keys Beta (Dec 11, 2025) - NEW ✨",
        "body": "User-scoped and organization-scoped API keys for your application. Zero-code UI component.\n\n// 1. Add the component for self-service API key management\nimport { APIKeys } from '@clerk/nextjs'\n\nexport default function SettingsPage() {\n  return (\n    <div>\n      <h2>API Keys</h2>\n      <APIKeys />  {/* Full CRUD UI for user's API keys */}\n    </div>\n  )\n}\n\nBackend Verification:\n\nimport { verifyToken } from '@clerk/backend'\n\n// API keys are verified like session tokens\nconst { data, error } = await verifyToken(apiKey, {\n  secretKey: process.env.CLERK_SECRET_KEY,\n  authorizedParties: ['https://yourdomain.com'],\n})\n\n// Check token type\nif (data?.tokenType === 'api_key') {\n  // Handle API key auth\n}\n\nclerkMiddleware Token Types:\n\n// v6.36.0+: Middleware can distinguish token types\nclerkMiddleware((auth, req) => {\n  const { userId, tokenType } = auth()\n\n  if (tokenType === 'api_key') {\n    // API key auth - programmatic access\n  } else if (tokenType === 'session_token') {\n    // Regular session - web UI access\n  }\n})\n\nPricing (Beta = Free):\n\nCreation: $0.001/key\nVerification: $0.0001/verification"
      },
      {
        "title": "2. Next.js 16: proxy.ts Middleware Filename (Dec 2025)",
        "body": "⚠️ BREAKING: Next.js 16 changed middleware filename due to critical security vulnerability (CVE disclosed March 2025).\n\nBackground: 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).\n\nWhy 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.\n\nNext.js 15 and earlier: middleware.ts\nNext.js 16+:            proxy.ts\n\nCorrect Setup for Next.js 16:\n\n// src/proxy.ts (NOT middleware.ts!)\nimport { clerkMiddleware } from '@clerk/nextjs/server'\n\nexport default clerkMiddleware()\n\nexport const config = {\n  matcher: [\n    '/((?!_next|[^?]*\\\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',\n    '/(api|trpc)(.*)',\n  ],\n}\n\nMinimum Version: @clerk/nextjs@6.35.0+ required for Next.js 16 (fixes Turbopack build errors and cache invalidation on sign-out)."
      },
      {
        "title": "3. Force Password Reset (Dec 19, 2025)",
        "body": "Administrators can mark passwords as compromised and force reset:\n\nimport { clerkClient } from '@clerk/backend'\n\n// Force password reset for a user\nawait clerkClient.users.updateUser(userId, {\n  passwordDigest: 'compromised',  // Triggers reset on next sign-in\n})"
      },
      {
        "title": "4. Organization Reports & Filters (Dec 15-17, 2025)",
        "body": "Dashboard now includes org creation metrics and filtering by name/slug/date."
      },
      {
        "title": "1. API Version 2025-11-10 (Nov 10, 2025) - BREAKING CHANGES ⚠️",
        "body": "Affects: Applications using Clerk Billing/Commerce APIs\n\nCritical Changes:\n\nEndpoint URLs: /commerce/ → /billing/ (30+ endpoints)\nGET /v1/commerce/plans → GET /v1/billing/plans\nGET /v1/commerce/statements → GET /v1/billing/statements\nPOST /v1/me/commerce/checkouts → POST /v1/me/billing/checkouts\n\n\n\nField Terminology: payment_source → payment_method\n// OLD (deprecated)\n{ payment_source_id: \"...\", payment_source: {...} }\n\n// NEW (required)\n{ payment_method_id: \"...\", payment_method: {...} }\n\n\n\nRemoved Fields: Plans responses no longer include:\n\namount, amount_formatted (use fee.amount instead)\ncurrency, currency_symbol (use fee objects)\npayer_type (use for_payer_type)\nannual_monthly_amount, annual_amount\n\n\n\nRemoved Endpoints:\n\nInvoices endpoint (use statements)\nProducts endpoint\n\n\n\nNull Handling: Explicit rules - null means \"doesn't exist\", omitted means \"not asserting existence\"\n\nMigration: Update SDK to v6.35.0+ which includes support for API version 2025-11-10.\n\nOfficial Guide: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/2025-11-10"
      },
      {
        "title": "2. Next.js v6 Async auth() (Oct 2024) - BREAKING CHANGE ⚠️",
        "body": "Affects: All Next.js Server Components using auth()\n\n// ❌ OLD (v5 - synchronous)\nconst { userId } = auth()\n\n// ✅ NEW (v6 - asynchronous)\nconst { userId } = await auth()\n\nAlso affects: auth.protect() is now async in middleware\n\n// ❌ OLD (v5)\nauth.protect()\n\n// ✅ NEW (v6)\nawait auth.protect()\n\nCompatibility: Next.js 15, 16 supported. Static rendering by default."
      },
      {
        "title": "3. PKCE Support for Custom OAuth (Nov 12, 2025)",
        "body": "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.\n\nUse case: Mobile apps, native apps, public clients that can't securely store secrets."
      },
      {
        "title": "4. Client Trust: Credential Stuffing Defense (Nov 14, 2025)",
        "body": "Automatic secondary authentication when users sign in from unrecognized devices:\n\nActivates for users with valid passwords but no 2FA\nNo configuration required\nIncluded in all Clerk plans\n\nHow it works: Clerk automatically prompts for additional verification (email code, backup code) when detecting sign-in from new device."
      },
      {
        "title": "5. Next.js 16 Support (Nov 2025)",
        "body": "@clerk/nextjs v6.35.2+ includes cache invalidation improvements for Next.js 16 during sign-out."
      },
      {
        "title": "Next.js v6: Async auth() Helper",
        "body": "Pattern:\n\nimport { auth } from '@clerk/nextjs/server'\n\nexport default async function Page() {\n  const { userId } = await auth()  // ← Must await\n\n  if (!userId) {\n    return <div>Unauthorized</div>\n  }\n\n  return <div>User ID: {userId}</div>\n}"
      },
      {
        "title": "Cloudflare Workers: authorizedParties (CSRF Prevention)",
        "body": "CRITICAL: Always set authorizedParties to prevent CSRF attacks\n\nimport { verifyToken } from '@clerk/backend'\n\nconst { data, error } = await verifyToken(token, {\n  secretKey: c.env.CLERK_SECRET_KEY,\n  // REQUIRED: Prevent CSRF attacks\n  authorizedParties: ['https://yourdomain.com'],\n})\n\nWhy: Without authorizedParties, attackers can use valid tokens from other domains.\n\nSource: https://clerk.com/docs/reference/backend/verify-token"
      },
      {
        "title": "Route Protection Patterns",
        "body": "import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'\n\n// Define protected routes\nconst isProtectedRoute = createRouteMatcher([\n  '/dashboard(.*)',\n  '/api/private(.*)',\n])\n\nconst isAdminRoute = createRouteMatcher(['/admin(.*)'])\n\nexport default clerkMiddleware(async (auth, req) => {\n  // Protect routes\n  if (isProtectedRoute(req)) {\n    await auth.protect()  // Redirects unauthenticated users\n  }\n\n  // Require specific permissions\n  if (isAdminRoute(req)) {\n    await auth.protect({\n      role: 'org:admin',  // Requires organization admin role\n    })\n  }\n})"
      },
      {
        "title": "All Middleware Options",
        "body": "OptionTypeDescriptiondebugbooleanEnable debug loggingjwtKeystringJWKS public key for networkless verificationclockSkewInMsnumberToken time variance (default: 5000ms)organizationSyncOptionsobjectURL-based org activationsignInUrlstringCustom sign-in URLsignUpUrlstringCustom sign-up URL"
      },
      {
        "title": "Organization Sync (URL-based Org Activation)",
        "body": "⚠️ 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.\n\nSource: GitHub Issue #7178\n\nclerkMiddleware({\n  organizationSyncOptions: {\n    organizationPatterns: ['/orgs/:slug', '/orgs/:slug/(.*)'],\n    personalAccountPatterns: ['/personal', '/personal/(.*)'],\n  },\n})"
      },
      {
        "title": "Webhook Verification",
        "body": "import { Webhook } from 'svix'\n\nexport async function POST(req: Request) {\n  const payload = await req.text()\n  const headers = {\n    'svix-id': req.headers.get('svix-id')!,\n    'svix-timestamp': req.headers.get('svix-timestamp')!,\n    'svix-signature': req.headers.get('svix-signature')!,\n  }\n\n  const wh = new Webhook(process.env.CLERK_WEBHOOK_SIGNING_SECRET!)\n\n  try {\n    const event = wh.verify(payload, headers)\n    // Process event\n    return Response.json({ success: true })\n  } catch (err) {\n    return Response.json({ error: 'Invalid signature' }, { status: 400 })\n  }\n}"
      },
      {
        "title": "Common Event Types",
        "body": "EventTriggeruser.createdNew user signs upuser.updatedUser profile changesuser.deletedUser account deletedsession.createdNew sign-insession.endedSign-outorganization.createdNew org createdorganization.membership.createdUser joins org\n\n⚠️ Important: Webhook routes must be PUBLIC (no auth). Add to middleware exclude list:\n\nconst isPublicRoute = createRouteMatcher([\n  '/api/webhooks/clerk(.*)',  // Clerk webhooks are public\n])\n\nclerkMiddleware((auth, req) => {\n  if (!isPublicRoute(req)) {\n    auth.protect()\n  }\n})"
      },
      {
        "title": "UI Components Quick Reference",
        "body": "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)"
      },
      {
        "title": "React Hooks",
        "body": "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"
      },
      {
        "title": "JWT Size Limitation: 1.2KB for Custom Claims ⚠️",
        "body": "Problem: Browser cookies limited to 4KB. Clerk's default claims consume ~2.8KB, leaving 1.2KB for custom claims.\n\n⚠️ 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.\n\nSolution:\n\n// ✅ GOOD: Minimal claims\n{\n  \"user_id\": \"{{user.id}}\",\n  \"email\": \"{{user.primary_email_address}}\",\n  \"role\": \"{{user.public_metadata.role}}\"\n}\n\n// ❌ BAD: Exceeds limit\n{\n  \"bio\": \"{{user.public_metadata.bio}}\",  // 6KB field\n  \"all_metadata\": \"{{user.public_metadata}}\"  // Entire object\n}\n\nBest Practice: Store large data in database, include only identifiers/roles in JWT."
      },
      {
        "title": "Available Shortcodes Reference",
        "body": "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\"\n\nAdvanced Features:\n\nString Interpolation: \"{{user.last_name}} {{user.first_name}}\"\nConditional Fallbacks: \"{{user.public_metadata.role || 'user'}}\"\nNested Metadata: \"{{user.public_metadata.profile.interests}}\"\n\nOfficial Docs: https://clerk.com/docs/guides/sessions/jwt-templates"
      },
      {
        "title": "Test Credentials (Fixed OTP: 424242)",
        "body": "Test Emails (no emails sent, fixed OTP):\n\njohn+clerk_test@example.com\njane+clerk_test@gmail.com\n\nTest Phone Numbers (no SMS sent, fixed OTP):\n\n+12015550100\n+19735550133\n\nFixed OTP Code: 424242 (works for all test credentials)"
      },
      {
        "title": "Generate Session Tokens (60-second lifetime)",
        "body": "Script (scripts/generate-session-token.js):\n\n# Generate token\nCLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js\n\n# Create new test user\nCLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js --create-user\n\n# Auto-refresh token every 50 seconds\nCLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js --refresh\n\nManual Flow:\n\nCreate user: POST /v1/users\nCreate session: POST /v1/sessions\nGenerate token: POST /v1/sessions/{session_id}/tokens\nUse in header: Authorization: Bearer <token>"
      },
      {
        "title": "E2E Testing with Playwright",
        "body": "Install @clerk/testing for automatic Testing Token management:\n\nnpm install -D @clerk/testing\n\nGlobal Setup (global.setup.ts):\n\nimport { clerkSetup } from '@clerk/testing/playwright'\nimport { test as setup } from '@playwright/test'\n\nsetup('global setup', async ({}) => {\n  await clerkSetup()\n})\n\nTest File (auth.spec.ts):\n\nimport { setupClerkTestingToken } from '@clerk/testing/playwright'\nimport { test } from '@playwright/test'\n\ntest('sign up', async ({ page }) => {\n  await setupClerkTestingToken({ page })\n\n  await page.goto('/sign-up')\n  await page.fill('input[name=\"emailAddress\"]', 'test+clerk_test@example.com')\n  await page.fill('input[name=\"password\"]', 'TestPassword123!')\n  await page.click('button[type=\"submit\"]')\n\n  // Verify with fixed OTP\n  await page.fill('input[name=\"code\"]', '424242')\n  await page.click('button[type=\"submit\"]')\n\n  await expect(page).toHaveURL('/dashboard')\n})\n\nOfficial Docs: https://clerk.com/docs/guides/development/testing/overview"
      },
      {
        "title": "Known Issues Prevention",
        "body": "This skill prevents 15 documented issues:"
      },
      {
        "title": "Issue #1: Missing Clerk Secret Key",
        "body": "Error: \"Missing Clerk Secret Key or API Key\"\nSource: https://stackoverflow.com/questions/77620604\nPrevention: Always set in .env.local or via wrangler secret put"
      },
      {
        "title": "Issue #2: API Key → Secret Key Migration",
        "body": "Error: \"apiKey is deprecated, use secretKey\"\nSource: https://clerk.com/docs/upgrade-guides/core-2/backend\nPrevention: Replace apiKey with secretKey in all calls"
      },
      {
        "title": "Issue #3: JWKS Cache Race Condition",
        "body": "Error: \"No JWK available\"\nSource: https://github.com/clerk/javascript/blob/main/packages/backend/CHANGELOG.md\nPrevention: Use @clerk/backend@2.17.2 or later (fixed)"
      },
      {
        "title": "Issue #4: Missing authorizedParties (CSRF)",
        "body": "Error: No error, but CSRF vulnerability\nSource: https://clerk.com/docs/reference/backend/verify-token\nPrevention: Always set authorizedParties: ['https://yourdomain.com']"
      },
      {
        "title": "Issue #5: Import Path Changes (Core 2)",
        "body": "Error: \"Cannot find module\"\nSource: https://clerk.com/docs/upgrade-guides/core-2/backend\nPrevention: Update import paths for Core 2"
      },
      {
        "title": "Issue #6: JWT Size Limit Exceeded",
        "body": "Error: Token exceeds size limit\nSource: https://clerk.com/docs/backend-requests/making/custom-session-token\nPrevention: Keep custom claims under 1.2KB"
      },
      {
        "title": "Issue #7: Deprecated API Version v1",
        "body": "Error: \"API version v1 is deprecated\"\nSource: https://clerk.com/docs/upgrade-guides/core-2/backend\nPrevention: Use latest SDK versions (API v2025-11-10)"
      },
      {
        "title": "Issue #8: ClerkProvider JSX Component Error",
        "body": "Error: \"cannot be used as a JSX component\"\nSource: https://stackoverflow.com/questions/79265537\nPrevention: Ensure React 19 compatibility with @clerk/clerk-react@5.59.2+"
      },
      {
        "title": "Issue #9: Async auth() Helper Confusion",
        "body": "Error: \"auth() is not a function\"\nSource: https://clerk.com/changelog/2024-10-22-clerk-nextjs-v6\nPrevention: Always await: const { userId } = await auth()"
      },
      {
        "title": "Issue #10: Environment Variable Misconfiguration",
        "body": "Error: \"Missing Publishable Key\" or secret leaked\nPrevention: Use correct prefixes (NEXT_PUBLIC_, VITE_), never commit secrets"
      },
      {
        "title": "Issue #11: 431 Request Header Fields Too Large (Vite Dev Mode)",
        "body": "Error: \"431 Request Header Fields Too Large\" when signing in\nSource: Common in Vite dev mode when testing custom JWT claims\nCause: Clerk's __clerk_handshake token in URL exceeds Vite's 8KB header limit\nPrevention:\n\nAdd to package.json:\n\n{\n  \"scripts\": {\n    \"dev\": \"NODE_OPTIONS='--max-http-header-size=32768' vite\"\n  }\n}\n\nTemporary Workaround: Clear browser cache, sign out, sign back in\n\nWhy: Clerk dev tokens are larger than production; custom JWT claims increase handshake token size\n\nNote: 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)."
      },
      {
        "title": "Issue #12: User Type Mismatch (useUser vs currentUser)",
        "body": "Error: TypeScript errors when sharing user utilities across client/server\nSource: GitHub Issue #2176\nWhy 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.\nPrevention: Use shared properties only, or create separate utility functions for client vs server contexts.\n\n// ✅ CORRECT: Use properties that exist in both\nconst primaryEmailAddress = user.emailAddresses.find(\n  ({ id }) => id === user.primaryEmailAddressId\n)\n\n// ✅ CORRECT: Separate types\ntype ClientUser = ReturnType<typeof useUser>['user']\ntype ServerUser = Awaited<ReturnType<typeof currentUser>>"
      },
      {
        "title": "Issue #13: Multiple acceptsToken Types Causes token-type-mismatch",
        "body": "Error: \"token-type-mismatch\" when using authenticateRequest() with multiple token types\nSource: GitHub Issue #7520\nWhy It Happens: When using authenticateRequest() with multiple acceptsToken values (e.g., ['session_token', 'api_key']), Clerk incorrectly throws token-type-mismatch error.\nPrevention: Upgrade to @clerk/backend@2.29.2+ (fix available in snapshot, releasing soon).\n\n// This now works in @clerk/backend@2.29.2+\nconst result = await authenticateRequest(request, {\n  acceptsToken: ['session_token', 'api_key'],  // Fixed!\n})"
      },
      {
        "title": "Issue #14: deriveUrlFromHeaders Server Crash on Malformed URLs",
        "body": "Error: Server crashes with URL parsing error\nSource: GitHub Issue #7275\nWhy 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.\nPrevention: Upgrade to @clerk/backend@2.29.0+ (fixed)."
      },
      {
        "title": "Issue #15: treatPendingAsSignedOut Option for Pending Sessions",
        "body": "Error: None - optional parameter for edge case handling\nSource: Changelog @clerk/nextjs@6.32.0\nWhy 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).\nUsage: Set treatPendingAsSignedOut: false to treat pending as signed-in (available in @clerk/nextjs@6.32.0+).\n\n// Default: pending = signed out\nconst user = await currentUser()  // null if status is 'pending'\n\n// Treat pending as signed in\nconst user = await currentUser({ treatPendingAsSignedOut: false })  // defined if pending"
      },
      {
        "title": "Service Availability & Reliability",
        "body": "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.\n\nSource: Clerk Postmortem: June 26, 2025\n\nMitigation Strategies:\n\nMonitor Clerk Status for real-time updates\nImplement graceful degradation when Clerk API is unavailable\nCache auth tokens locally where possible\nFor existing sessions, use jwtKey option for networkless verification:\n\nclerkMiddleware({\n  jwtKey: process.env.CLERK_JWT_KEY,  // Allows offline token verification\n})\n\nNote: 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."
      },
      {
        "title": "Official Documentation",
        "body": "Clerk Docs: https://clerk.com/docs\nNext.js Guide: https://clerk.com/docs/references/nextjs/overview\nReact Guide: https://clerk.com/docs/references/react/overview\nBackend SDK: https://clerk.com/docs/reference/backend/overview\nJWT Templates: https://clerk.com/docs/guides/sessions/jwt-templates\nAPI Version 2025-11-10 Upgrade: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/2025-11-10\nTesting Guide: https://clerk.com/docs/guides/development/testing/overview\nContext7 Library ID: /clerk/clerk-docs"
      },
      {
        "title": "Package Versions",
        "body": "Latest (Nov 22, 2025):\n\n{\n  \"dependencies\": {\n    \"@clerk/nextjs\": \"^6.36.7\",\n    \"@clerk/clerk-react\": \"^5.59.2\",\n    \"@clerk/backend\": \"^2.29.2\",\n    \"@clerk/testing\": \"^1.13.26\"\n  }\n}\n\nToken Efficiency:\n\nWithout skill: ~6,500 tokens (setup tutorials, JWT templates, testing setup, webhooks, production considerations)\nWith skill: ~3,200 tokens (breaking changes + critical patterns + error prevention + production guidance)\nSavings: ~51% (~3,300 tokens)\n\nErrors prevented: 15 documented issues with exact solutions\nKey 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)\n\nLast 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+)."
      }
    ],
    "body": "Clerk Auth - Breaking Changes & Error Prevention Guide\n\nPackage 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\n\nWhat's New (Dec 2025 - Jan 2026)\n1. API Keys Beta (Dec 11, 2025) - NEW ✨\n\nUser-scoped and organization-scoped API keys for your application. Zero-code UI component.\n\n// 1. Add the component for self-service API key management\nimport { APIKeys } from '@clerk/nextjs'\n\nexport default function SettingsPage() {\n  return (\n    <div>\n      <h2>API Keys</h2>\n      <APIKeys />  {/* Full CRUD UI for user's API keys */}\n    </div>\n  )\n}\n\n\nBackend Verification:\n\nimport { verifyToken } from '@clerk/backend'\n\n// API keys are verified like session tokens\nconst { data, error } = await verifyToken(apiKey, {\n  secretKey: process.env.CLERK_SECRET_KEY,\n  authorizedParties: ['https://yourdomain.com'],\n})\n\n// Check token type\nif (data?.tokenType === 'api_key') {\n  // Handle API key auth\n}\n\n\nclerkMiddleware Token Types:\n\n// v6.36.0+: Middleware can distinguish token types\nclerkMiddleware((auth, req) => {\n  const { userId, tokenType } = auth()\n\n  if (tokenType === 'api_key') {\n    // API key auth - programmatic access\n  } else if (tokenType === 'session_token') {\n    // Regular session - web UI access\n  }\n})\n\n\nPricing (Beta = Free):\n\nCreation: $0.001/key\nVerification: $0.0001/verification\n2. Next.js 16: proxy.ts Middleware Filename (Dec 2025)\n\n⚠️ BREAKING: Next.js 16 changed middleware filename due to critical security vulnerability (CVE disclosed March 2025).\n\nBackground: 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).\n\nWhy 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.\n\nNext.js 15 and earlier: middleware.ts\nNext.js 16+:            proxy.ts\n\n\nCorrect Setup for Next.js 16:\n\n// src/proxy.ts (NOT middleware.ts!)\nimport { clerkMiddleware } from '@clerk/nextjs/server'\n\nexport default clerkMiddleware()\n\nexport const config = {\n  matcher: [\n    '/((?!_next|[^?]*\\\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',\n    '/(api|trpc)(.*)',\n  ],\n}\n\n\nMinimum Version: @clerk/nextjs@6.35.0+ required for Next.js 16 (fixes Turbopack build errors and cache invalidation on sign-out).\n\n3. Force Password Reset (Dec 19, 2025)\n\nAdministrators can mark passwords as compromised and force reset:\n\nimport { clerkClient } from '@clerk/backend'\n\n// Force password reset for a user\nawait clerkClient.users.updateUser(userId, {\n  passwordDigest: 'compromised',  // Triggers reset on next sign-in\n})\n\n4. Organization Reports & Filters (Dec 15-17, 2025)\n\nDashboard now includes org creation metrics and filtering by name/slug/date.\n\nAPI Version 2025-11-10 Breaking Changes\n1. API Version 2025-11-10 (Nov 10, 2025) - BREAKING CHANGES ⚠️\n\nAffects: Applications using Clerk Billing/Commerce APIs\n\nCritical Changes:\n\nEndpoint URLs: /commerce/ → /billing/ (30+ endpoints)\n\nGET /v1/commerce/plans → GET /v1/billing/plans\nGET /v1/commerce/statements → GET /v1/billing/statements\nPOST /v1/me/commerce/checkouts → POST /v1/me/billing/checkouts\n\n\nField Terminology: payment_source → payment_method\n\n// OLD (deprecated)\n{ payment_source_id: \"...\", payment_source: {...} }\n\n// NEW (required)\n{ payment_method_id: \"...\", payment_method: {...} }\n\n\nRemoved Fields: Plans responses no longer include:\n\namount, amount_formatted (use fee.amount instead)\ncurrency, currency_symbol (use fee objects)\npayer_type (use for_payer_type)\nannual_monthly_amount, annual_amount\n\nRemoved Endpoints:\n\nInvoices endpoint (use statements)\nProducts endpoint\n\nNull Handling: Explicit rules - null means \"doesn't exist\", omitted means \"not asserting existence\"\n\nMigration: Update SDK to v6.35.0+ which includes support for API version 2025-11-10.\n\nOfficial Guide: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/2025-11-10\n\n2. Next.js v6 Async auth() (Oct 2024) - BREAKING CHANGE ⚠️\n\nAffects: All Next.js Server Components using auth()\n\n// ❌ OLD (v5 - synchronous)\nconst { userId } = auth()\n\n// ✅ NEW (v6 - asynchronous)\nconst { userId } = await auth()\n\n\nAlso affects: auth.protect() is now async in middleware\n\n// ❌ OLD (v5)\nauth.protect()\n\n// ✅ NEW (v6)\nawait auth.protect()\n\n\nCompatibility: Next.js 15, 16 supported. Static rendering by default.\n\n3. PKCE Support for Custom OAuth (Nov 12, 2025)\n\nCustom 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.\n\nUse case: Mobile apps, native apps, public clients that can't securely store secrets.\n\n4. Client Trust: Credential Stuffing Defense (Nov 14, 2025)\n\nAutomatic secondary authentication when users sign in from unrecognized devices:\n\nActivates for users with valid passwords but no 2FA\nNo configuration required\nIncluded in all Clerk plans\n\nHow it works: Clerk automatically prompts for additional verification (email code, backup code) when detecting sign-in from new device.\n\n5. Next.js 16 Support (Nov 2025)\n\n@clerk/nextjs v6.35.2+ includes cache invalidation improvements for Next.js 16 during sign-out.\n\nCritical Patterns & Error Prevention\nNext.js v6: Async auth() Helper\n\nPattern:\n\nimport { auth } from '@clerk/nextjs/server'\n\nexport default async function Page() {\n  const { userId } = await auth()  // ← Must await\n\n  if (!userId) {\n    return <div>Unauthorized</div>\n  }\n\n  return <div>User ID: {userId}</div>\n}\n\nCloudflare Workers: authorizedParties (CSRF Prevention)\n\nCRITICAL: Always set authorizedParties to prevent CSRF attacks\n\nimport { verifyToken } from '@clerk/backend'\n\nconst { data, error } = await verifyToken(token, {\n  secretKey: c.env.CLERK_SECRET_KEY,\n  // REQUIRED: Prevent CSRF attacks\n  authorizedParties: ['https://yourdomain.com'],\n})\n\n\nWhy: Without authorizedParties, attackers can use valid tokens from other domains.\n\nSource: https://clerk.com/docs/reference/backend/verify-token\n\nclerkMiddleware() Configuration\nRoute Protection Patterns\nimport { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'\n\n// Define protected routes\nconst isProtectedRoute = createRouteMatcher([\n  '/dashboard(.*)',\n  '/api/private(.*)',\n])\n\nconst isAdminRoute = createRouteMatcher(['/admin(.*)'])\n\nexport default clerkMiddleware(async (auth, req) => {\n  // Protect routes\n  if (isProtectedRoute(req)) {\n    await auth.protect()  // Redirects unauthenticated users\n  }\n\n  // Require specific permissions\n  if (isAdminRoute(req)) {\n    await auth.protect({\n      role: 'org:admin',  // Requires organization admin role\n    })\n  }\n})\n\nAll Middleware Options\nOption\tType\tDescription\ndebug\tboolean\tEnable debug logging\njwtKey\tstring\tJWKS public key for networkless verification\nclockSkewInMs\tnumber\tToken time variance (default: 5000ms)\norganizationSyncOptions\tobject\tURL-based org activation\nsignInUrl\tstring\tCustom sign-in URL\nsignUpUrl\tstring\tCustom sign-up URL\nOrganization Sync (URL-based Org Activation)\n\n⚠️ 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.\n\nSource: GitHub Issue #7178\n\nclerkMiddleware({\n  organizationSyncOptions: {\n    organizationPatterns: ['/orgs/:slug', '/orgs/:slug/(.*)'],\n    personalAccountPatterns: ['/personal', '/personal/(.*)'],\n  },\n})\n\nWebhooks\nWebhook Verification\nimport { Webhook } from 'svix'\n\nexport async function POST(req: Request) {\n  const payload = await req.text()\n  const headers = {\n    'svix-id': req.headers.get('svix-id')!,\n    'svix-timestamp': req.headers.get('svix-timestamp')!,\n    'svix-signature': req.headers.get('svix-signature')!,\n  }\n\n  const wh = new Webhook(process.env.CLERK_WEBHOOK_SIGNING_SECRET!)\n\n  try {\n    const event = wh.verify(payload, headers)\n    // Process event\n    return Response.json({ success: true })\n  } catch (err) {\n    return Response.json({ error: 'Invalid signature' }, { status: 400 })\n  }\n}\n\nCommon Event Types\nEvent\tTrigger\nuser.created\tNew user signs up\nuser.updated\tUser profile changes\nuser.deleted\tUser account deleted\nsession.created\tNew sign-in\nsession.ended\tSign-out\norganization.created\tNew org created\norganization.membership.created\tUser joins org\n\n⚠️ Important: Webhook routes must be PUBLIC (no auth). Add to middleware exclude list:\n\nconst isPublicRoute = createRouteMatcher([\n  '/api/webhooks/clerk(.*)',  // Clerk webhooks are public\n])\n\nclerkMiddleware((auth, req) => {\n  if (!isPublicRoute(req)) {\n    auth.protect()\n  }\n})\n\nUI Components Quick Reference\nComponent\tPurpose\n<SignIn />\tFull sign-in flow\n<SignUp />\tFull sign-up flow\n<SignInButton />\tTrigger sign-in modal\n<SignUpButton />\tTrigger sign-up modal\n<SignedIn>\tRender only when authenticated\n<SignedOut>\tRender only when unauthenticated\n<UserButton />\tUser menu with sign-out\n<UserProfile />\tFull profile management\n<OrganizationSwitcher />\tSwitch between orgs\n<OrganizationProfile />\tOrg settings\n<CreateOrganization />\tCreate new org\n<APIKeys />\tAPI key management (NEW)\nReact Hooks\nHook\tReturns\nuseAuth()\t{ userId, sessionId, isLoaded, isSignedIn, getToken }\nuseUser()\t{ user, isLoaded, isSignedIn }\nuseClerk()\tClerk instance with methods\nuseSession()\tCurrent session object\nuseOrganization()\tCurrent org context\nuseOrganizationList()\tAll user's orgs\nJWT Templates - Size Limits & Shortcodes\nJWT Size Limitation: 1.2KB for Custom Claims ⚠️\n\nProblem: Browser cookies limited to 4KB. Clerk's default claims consume ~2.8KB, leaving 1.2KB for custom claims.\n\n⚠️ 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.\n\nSolution:\n\n// ✅ GOOD: Minimal claims\n{\n  \"user_id\": \"{{user.id}}\",\n  \"email\": \"{{user.primary_email_address}}\",\n  \"role\": \"{{user.public_metadata.role}}\"\n}\n\n// ❌ BAD: Exceeds limit\n{\n  \"bio\": \"{{user.public_metadata.bio}}\",  // 6KB field\n  \"all_metadata\": \"{{user.public_metadata}}\"  // Entire object\n}\n\n\nBest Practice: Store large data in database, include only identifiers/roles in JWT.\n\nAvailable Shortcodes Reference\nCategory\tShortcodes\tExample\nUser ID & Name\t{{user.id}}, {{user.first_name}}, {{user.last_name}}, {{user.full_name}}\t\"John Doe\"\nContact\t{{user.primary_email_address}}, {{user.primary_phone_address}}\t\"john@example.com\"\nProfile\t{{user.image_url}}, {{user.username}}, {{user.created_at}}\t\"https://...\"\nVerification\t{{user.email_verified}}, {{user.phone_number_verified}}\ttrue\nMetadata\t{{user.public_metadata}}, {{user.public_metadata.FIELD}}\t{\"role\": \"admin\"}\nOrganization\torg_id, org_slug, org_role (in sessionClaims)\t\"org:admin\"\n\nAdvanced Features:\n\nString Interpolation: \"{{user.last_name}} {{user.first_name}}\"\nConditional Fallbacks: \"{{user.public_metadata.role || 'user'}}\"\nNested Metadata: \"{{user.public_metadata.profile.interests}}\"\n\nOfficial Docs: https://clerk.com/docs/guides/sessions/jwt-templates\n\nTesting with Clerk\nTest Credentials (Fixed OTP: 424242)\n\nTest Emails (no emails sent, fixed OTP):\n\njohn+clerk_test@example.com\njane+clerk_test@gmail.com\n\n\nTest Phone Numbers (no SMS sent, fixed OTP):\n\n+12015550100\n+19735550133\n\n\nFixed OTP Code: 424242 (works for all test credentials)\n\nGenerate Session Tokens (60-second lifetime)\n\nScript (scripts/generate-session-token.js):\n\n# Generate token\nCLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js\n\n# Create new test user\nCLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js --create-user\n\n# Auto-refresh token every 50 seconds\nCLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js --refresh\n\n\nManual Flow:\n\nCreate user: POST /v1/users\nCreate session: POST /v1/sessions\nGenerate token: POST /v1/sessions/{session_id}/tokens\nUse in header: Authorization: Bearer <token>\nE2E Testing with Playwright\n\nInstall @clerk/testing for automatic Testing Token management:\n\nnpm install -D @clerk/testing\n\n\nGlobal Setup (global.setup.ts):\n\nimport { clerkSetup } from '@clerk/testing/playwright'\nimport { test as setup } from '@playwright/test'\n\nsetup('global setup', async ({}) => {\n  await clerkSetup()\n})\n\n\nTest File (auth.spec.ts):\n\nimport { setupClerkTestingToken } from '@clerk/testing/playwright'\nimport { test } from '@playwright/test'\n\ntest('sign up', async ({ page }) => {\n  await setupClerkTestingToken({ page })\n\n  await page.goto('/sign-up')\n  await page.fill('input[name=\"emailAddress\"]', 'test+clerk_test@example.com')\n  await page.fill('input[name=\"password\"]', 'TestPassword123!')\n  await page.click('button[type=\"submit\"]')\n\n  // Verify with fixed OTP\n  await page.fill('input[name=\"code\"]', '424242')\n  await page.click('button[type=\"submit\"]')\n\n  await expect(page).toHaveURL('/dashboard')\n})\n\n\nOfficial Docs: https://clerk.com/docs/guides/development/testing/overview\n\nKnown Issues Prevention\n\nThis skill prevents 15 documented issues:\n\nIssue #1: Missing Clerk Secret Key\n\nError: \"Missing Clerk Secret Key or API Key\" Source: https://stackoverflow.com/questions/77620604 Prevention: Always set in .env.local or via wrangler secret put\n\nIssue #2: API Key → Secret Key Migration\n\nError: \"apiKey is deprecated, use secretKey\" Source: https://clerk.com/docs/upgrade-guides/core-2/backend Prevention: Replace apiKey with secretKey in all calls\n\nIssue #3: JWKS Cache Race Condition\n\nError: \"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)\n\nIssue #4: Missing authorizedParties (CSRF)\n\nError: No error, but CSRF vulnerability Source: https://clerk.com/docs/reference/backend/verify-token Prevention: Always set authorizedParties: ['https://yourdomain.com']\n\nIssue #5: Import Path Changes (Core 2)\n\nError: \"Cannot find module\" Source: https://clerk.com/docs/upgrade-guides/core-2/backend Prevention: Update import paths for Core 2\n\nIssue #6: JWT Size Limit Exceeded\n\nError: Token exceeds size limit Source: https://clerk.com/docs/backend-requests/making/custom-session-token Prevention: Keep custom claims under 1.2KB\n\nIssue #7: Deprecated API Version v1\n\nError: \"API version v1 is deprecated\" Source: https://clerk.com/docs/upgrade-guides/core-2/backend Prevention: Use latest SDK versions (API v2025-11-10)\n\nIssue #8: ClerkProvider JSX Component Error\n\nError: \"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+\n\nIssue #9: Async auth() Helper Confusion\n\nError: \"auth() is not a function\" Source: https://clerk.com/changelog/2024-10-22-clerk-nextjs-v6 Prevention: Always await: const { userId } = await auth()\n\nIssue #10: Environment Variable Misconfiguration\n\nError: \"Missing Publishable Key\" or secret leaked Prevention: Use correct prefixes (NEXT_PUBLIC_, VITE_), never commit secrets\n\nIssue #11: 431 Request Header Fields Too Large (Vite Dev Mode)\n\nError: \"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:\n\nAdd to package.json:\n\n{\n  \"scripts\": {\n    \"dev\": \"NODE_OPTIONS='--max-http-header-size=32768' vite\"\n  }\n}\n\n\nTemporary Workaround: Clear browser cache, sign out, sign back in\n\nWhy: Clerk dev tokens are larger than production; custom JWT claims increase handshake token size\n\nNote: 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).\n\nIssue #12: User Type Mismatch (useUser vs currentUser)\n\nError: 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.\n\n// ✅ CORRECT: Use properties that exist in both\nconst primaryEmailAddress = user.emailAddresses.find(\n  ({ id }) => id === user.primaryEmailAddressId\n)\n\n// ✅ CORRECT: Separate types\ntype ClientUser = ReturnType<typeof useUser>['user']\ntype ServerUser = Awaited<ReturnType<typeof currentUser>>\n\nIssue #13: Multiple acceptsToken Types Causes token-type-mismatch\n\nError: \"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).\n\n// This now works in @clerk/backend@2.29.2+\nconst result = await authenticateRequest(request, {\n  acceptsToken: ['session_token', 'api_key'],  // Fixed!\n})\n\nIssue #14: deriveUrlFromHeaders Server Crash on Malformed URLs\n\nError: 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).\n\nIssue #15: treatPendingAsSignedOut Option for Pending Sessions\n\nError: 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+).\n\n// Default: pending = signed out\nconst user = await currentUser()  // null if status is 'pending'\n\n// Treat pending as signed in\nconst user = await currentUser({ treatPendingAsSignedOut: false })  // defined if pending\n\nProduction Considerations\nService Availability & Reliability\n\nContext: 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.\n\nSource: Clerk Postmortem: June 26, 2025\n\nMitigation Strategies:\n\nMonitor Clerk Status for real-time updates\nImplement graceful degradation when Clerk API is unavailable\nCache auth tokens locally where possible\nFor existing sessions, use jwtKey option for networkless verification:\nclerkMiddleware({\n  jwtKey: process.env.CLERK_JWT_KEY,  // Allows offline token verification\n})\n\n\nNote: 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.\n\nOfficial Documentation\nClerk Docs: https://clerk.com/docs\nNext.js Guide: https://clerk.com/docs/references/nextjs/overview\nReact Guide: https://clerk.com/docs/references/react/overview\nBackend SDK: https://clerk.com/docs/reference/backend/overview\nJWT Templates: https://clerk.com/docs/guides/sessions/jwt-templates\nAPI Version 2025-11-10 Upgrade: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/2025-11-10\nTesting Guide: https://clerk.com/docs/guides/development/testing/overview\nContext7 Library ID: /clerk/clerk-docs\nPackage Versions\n\nLatest (Nov 22, 2025):\n\n{\n  \"dependencies\": {\n    \"@clerk/nextjs\": \"^6.36.7\",\n    \"@clerk/clerk-react\": \"^5.59.2\",\n    \"@clerk/backend\": \"^2.29.2\",\n    \"@clerk/testing\": \"^1.13.26\"\n  }\n}\n\n\nToken Efficiency:\n\nWithout skill: ~6,500 tokens (setup tutorials, JWT templates, testing setup, webhooks, production considerations)\nWith skill: ~3,200 tokens (breaking changes + critical patterns + error prevention + production guidance)\nSavings: ~51% (~3,300 tokens)\n\nErrors 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)\n\nLast 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+)."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/Veeramanikandanr48/clerk-auth",
    "publisherUrl": "https://clawhub.ai/Veeramanikandanr48/clerk-auth",
    "owner": "Veeramanikandanr48",
    "version": "0.1.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/clerk-auth",
    "downloadUrl": "https://openagent3.xyz/downloads/clerk-auth",
    "agentUrl": "https://openagent3.xyz/skills/clerk-auth/agent",
    "manifestUrl": "https://openagent3.xyz/skills/clerk-auth/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/clerk-auth/agent.md"
  }
}