YeetCode
Convex App

Authentication

How Clerk authentication integrates with the Convex backend.

YeetCode uses Clerk for authentication and Convex Auth to verify JWTs on the backend. Users authenticate through Clerk on the frontend, and their identity is verified server-side via JWT validation.

How It Works

  1. User signs in via Clerk on the frontend (Clerk components/hooks)
  2. Clerk issues a JWT that gets sent with every Convex request
  3. Convex validates the JWT using the Clerk issuer domain
  4. Backend functions use getAuthUserId() to identify the current user

Auth Configuration

The JWT provider is configured in apps/convex/auth.config.ts:

import { env } from "./env";

export default {
  providers: [
    {
      domain: env.CLERK_JWT_ISSUER_DOMAIN,
      applicationID: "convex",
    },
  ]
};
  • domain — Your Clerk JWT issuer domain (e.g., https://your-app.clerk.accounts.dev)
  • applicationID — Must match the audience claim in Clerk's JWT template. Set this to "convex" and create a matching JWT template in Clerk's dashboard.

Checking Authentication

The users model provides helpers for authentication checks:

import * as Users from "./models/users";

// In a query or mutation:
const user = await Users.getCurrentUserOrThrow(ctx);
// Throws if not authenticated or user not found

// Or just verify auth without returning the user:
await Users.ensureUserAuthenticated(ctx);

These use getAuthUserId() from @convex-dev/auth/server internally, which extracts the user ID from the validated JWT.

User Sync

Users are synced from Clerk to Convex via webhooks — not at login time. When Clerk fires a user.created webhook, the backend creates a corresponding users record. See Webhooks for the full flow.

Required Environment Variables

VariableDescription
CLERK_JWT_ISSUER_DOMAINYour Clerk issuer domain
CLERK_WEBHOOK_SECRETSvix signing secret for webhook verification

Both must be set in your Convex deployment's environment variables.

On this page