PluginBench
Skill
Pass
Audit score 90

convex-auth

get-convex/agent-skills

Add passkey/OAuth authentication to Convex apps with proper auth.config.ts wiring.

What is convex-auth?

Installs and configures @convex-dev/auth for a Convex app with passkeys (default), password, or OAuth providers. Includes server config, client hooks, sign-in UI, and headless JWT key generation to avoid the common auth.config.ts misconfiguration that silently breaks authentication.

  • Installs @convex-dev/auth with pinned build and wires it into convex.config.ts
  • Generates JWT_PRIVATE_KEY and JWKS deterministically using jose (avoids interactive wizard hangs)
  • Creates convex/auth.config.ts to prevent silent sign-out bugs
  • Sets up ConvexAuthProvider and sign-in UI components on the client
  • Supports passkeys (default), password, or OAuth (Google, etc.) providers
  • Installs required shadcn/ui primitives automatically

How to install convex-auth

npx skills add https://github.com/get-convex/agent-skills --skill convex-auth
Prerequisites
  • Existing Convex app with convex.config.ts
  • Node.js with jose package (auto-installed for pnpm; manual `pnpm add jose` if needed)
  • shadcn/ui installed in the project (primitives added on-demand)
Claude Code
Cursor
Windsurf
Cline

How to use convex-auth

  1. 1.Install @convex-dev/auth and add it to convex.config.ts
  2. 2.Add the auth provider (passkeys by default) in convex/auth.ts
  3. 3.Generate JWT_PRIVATE_KEY and JWKS headlessly using the provided jose command
  4. 4.Set JWT_PRIVATE_KEY, JWKS, and SITE_URL environment variables via MCP envSet or CLI
  5. 5.Write convex/auth.config.ts with correct configuration
  6. 6.Wire ConvexAuthProvider, sign-in component, and route guards on the client
  7. 7.Test a complete sign-in flow to verify it works end-to-end

Use cases

Good for
  • Adding user authentication to a new Convex app with passkeys as the primary method
  • Integrating OAuth sign-in (e.g., Google) into an existing Convex backend
  • Setting up authentication in CI/headless environments without interactive prompts
  • Migrating from manual auth to @convex-dev/auth with proper key generation
  • Adding password-based authentication as an alternative to passkeys
Who it's for
  • Full-stack developers building Convex apps
  • Teams setting up authentication in CI/deployment pipelines
  • Developers wanting to avoid common auth.config.ts misconfiguration pitfalls

convex-auth FAQ

Why not use the interactive `npx @convex-dev/auth` wizard?

The interactive wizard requires a login/TTY and hangs in non-interactive, anonymous, or CI environments. This skill generates keys headlessly with jose instead.

What happens if auth.config.ts is missing or wrong?

The app silently becomes always-signed-out with no error message. This skill ensures it's written correctly to prevent that footgun.

Which authentication provider should I use?

Passkeys are the default and recommended. Password or OAuth (Google, GitHub, etc.) are available on request.

Do I need to manually install shadcn/ui components?

No, the skill installs required primitives (button, input, label, etc.) automatically when they're imported.

How do I set environment variables without shell-quoting issues?

Use the MCP `envSet` tool (one call per variable) or the NAME=VALUE CLI form (`npx convex env set "JWT_PRIVATE_KEY=$JWT"`). Never use `env set JWT_PRIVATE_KEY "$JWT"` as the CLI will misparse the leading `-`.

Full instructions (SKILL.md)

Source of truth, from get-convex/agent-skills.


name: convex-auth description: "Add authentication (passkeys/OAuth) to the current Convex app, including the auth.config.ts wiring."

<!-- GENERATED from convex-agents content/capabilities/auth.json — do not edit by hand. -->

Add sign-in to the app

Install and wire @convex-dev/auth for the current app: a provider (passkeys by default, or OAuth/password), the server config, the client hooks, and a sign-in UI — correctly, including the auth.config.ts that's the #1 real-world auth footgun.

Workflow

  1. Install @convex-dev/auth (pinned build) and add it to convex.config.ts. With pnpm, also pnpm add jose (it won't hoist otherwise); you need it for step 3.
  2. Add the provider in convex/auth.ts (Passkey by default; Password or OAuth like Google on request).
  3. Generate the auth keys HEADLESSLY. Do NOT run the interactive npx @convex-dev/auth wizard: it needs a login/TTY and hangs in non-interactive, anonymous, or CI runs (the #1 auth time-sink). Generate JWT_PRIVATE_KEY + JWKS deterministically with jose: node -e 'import("jose").then(async({generateKeyPair,exportPKCS8,exportJWK})=>{const k=await generateKeyPair("RS256",{extractable:true});const priv=await exportPKCS8(k.privateKey);const pub=await exportJWK(k.publicKey);process.stdout.write(JSON.stringify({JWT_PRIVATE_KEY:priv.trimEnd().replace(/\n/g," "),JWKS:JSON.stringify({keys:[{use:"sig",...pub}]})}))})' > .auth-keys.json Then set JWT_PRIVATE_KEY and JWKS (from .auth-keys.json) plus SITE_URL on the deployment. Prefer the Convex MCP envSet tool, one call per var, to avoid shell-quoting the multi-line key. CLI fallback: use the NAME=VALUE form (npx convex env set "JWT_PRIVATE_KEY=$JWT"), NEVER env set JWT_PRIVATE_KEY "$JWT" (the value starts with -----BEGIN and the CLI parses the leading - as an unknown flag). SITE_URL is the dev URL (e.g. http://localhost:3000). Delete .auth-keys.json after.
  4. Write convex/auth.config.ts (the silently-always-signed-out bug lives here if it's wrong).
  5. Wire the client: ConvexAuthProvider, the sign-in component, and route guards. If you import shadcn/ui primitives (button, input, textarea, label, and so on), add them first with npx shadcn@latest add <name>; a missing @/components/ui/* is a hard build error.
  6. Verify a sign-in round-trips before declaring done.

Rules

  • Generate JWT_PRIVATE_KEY/JWKS with jose (extractable RS256; PKCS8 newlines to spaces; JWKS = {keys:[{use:"sig", ...publicJwk}]}). Do NOT run the interactive npx @convex-dev/auth wizard: it hangs headless/anonymous. Set the vars via the MCP envSet tool or the NAME=VALUE CLI form.
  • Always write auth.config.ts: a missing/incorrect one makes the app silently always-signed-out with no error.
  • Passkeys by default; only switch to password/OAuth on explicit request.
  • Install any shadcn/ui primitive you import up front (npx shadcn@latest add ...); a missing @/components/ui/* is a hard build failure.
  • Verify a real sign-in works before finishing.