Skip to content
v3.0.1 — MCP OAuth, organizations, passkeys, SSR adaptersChangelog
Convex Auth
Esc
↑↓navigate↵open⌘Jpreview
On this page

Security

Security controls in convex-auth: 2FA, CAPTCHA, breach checks, rate limits, sessions, and keys.

convex-auth gives you several security controls out of the box. Most are configured in convex/auth.ts; the rest are environment and deployment practices.

Passwords

Breach detection

emailAndPassword.checkBreach checks new passwords against Have I Been Pwned and rejects known-breached ones.

export const auth = convexAuth({
  component: components.convexAuth,
  emailAndPassword: {
    enabled: true,
    checkBreach: true,
    minPasswordLength: 8,
    maxPasswordLength: 128,
  },
});

Password reset

By default revokeSessionsOnPasswordReset is true. When a user resets their password, all active sessions are invalidated immediately.

Rate limiting

Configure sign-in attempt rate limits per email:

export const auth = convexAuth({
  component: components.convexAuth,
  emailAndPassword: {
    enabled: true,
    rateLimit: {
      windowMs: 15 * 60 * 1000,
      maxAttempts: 5,
    },
  },
});

CAPTCHA

Protect the sign-up and password-reset endpoints with a CAPTCHA provider:

export const auth = convexAuth({
  component: components.convexAuth,
  captcha: {
    provider: "cloudflare-turnstile",
    secretKey: process.env.TURNSTILE_SECRET_KEY!,
  },
});

Supported providers: cloudflare-turnstile, google-recaptcha, hcaptcha, and captchafox. The default endpoints are /api/auth/sign-up/email, /api/auth/sign-up, and /api/auth/request-password-reset.

Two-factor authentication

TOTP is native. When 2FA is enabled, signIn returns a twoFactorChallengeToken. The client must verify the TOTP code or a backup code before a session token is issued.

const { data } = await client.signIn.email({ email, password });
// data.twoFactorChallengeToken is set if 2FA is enabled
await client.twoFactor.verifyTotp({ code, trustDevice: true });

Set trustDevice to skip 2FA on the current device for the configured trust window.

JWT and JWKS

Sessions are RS256 JWTs.

  • JWT_PRIVATE_KEY — the private JWK used to sign tokens. Never commit it.
  • JWKS — the public JWKS used to verify tokens on every Convex request.
  • Use convex env set for both local and production.
  • Rotate keys by generating a new pair, updating JWKS, and then updating JWT_PRIVATE_KEY.

Trusted origins

All email links, OAuth callbacks, and verification redirects require an allowed origin. Configure the origins in the provider config:

export const auth = convexAuth({
  component: components.convexAuth,
  emailAndPassword: {
    trustedOrigins: ["https://yourdomain.com", "https://app.yourdomain.com"],
  },
  oauth: {
    trustedOrigins: ["https://yourdomain.com", "https://app.yourdomain.com"],
  },
});

Session and refresh tokens

  • Access tokens are short-lived (default 7 days).
  • Refresh tokens are long-lived (default 30 days).
  • Revoke sessions from the client with the session-list hooks.
  • Password reset revokes all sessions by default.
  • Revocation is enforced on every validation path — a revoked session’s token is rejected by session resolution, token verification, the bearer HTTP endpoints, OAuth account linking, and MCP authorization immediately, not just at expiry.
  • Session listings never expose raw tokens; listSessions returns isCurrent instead.
  • Revoking a passkey revokes every session and refresh token it created, including sessions minted after a two-factor challenge.

Security checklist

Use strong signing keys

Generate RS256 keys with jose and keep them in Convex env, not in the repo.

Enable breach checks

Set checkBreach: true for email/password.

Add CAPTCHA

Protect sign-up and password reset in production.

Rate-limit sign-in

Configure rateLimit for email/password and any custom actions.

Pin trusted origins

Set trustedOrigins for email, OAuth, and magic links.

Use 2FA for admin accounts

Require TOTP for accounts with elevated privileges.

Rotate keys on suspicion

Regenerate JWT_PRIVATE_KEY and JWKS if a key leaks.

Was this page helpful?