Skip to main content
Complete password-based authentication flow for React applications. Includes login and sign-up forms with built-in validation, error handling, and full Convex backend integration.

Installation

npx shadcn@latest add https://convex-ui.vercel.app/r/password-based-auth-react
This installs:
  • Login and sign-up form components
  • Convex auth configuration
  • User management functions
  • Convex client setup files

What’s Included

Login Form

Email/password login with forgot password link support

Sign-Up Form

User registration with password confirmation and validation

Backend Functions

Complete Convex auth setup with user management

Type Safety

Full TypeScript support with validated schemas

Setup

1
Start Convex Dev Server
2
Run the Convex development server to initialize your backend:
3
npx convex dev
4
This deploys your auth functions and schema to Convex.
5
Set Environment Variables
6
Add your Convex URL to .env:
7
VITE_CONVEX_URL=https://your-deployment.convex.cloud
CONVEX_DEPLOYMENT=your-deployment-name
8
Configure Email Provider (Optional)
9
For email verification and password reset, set up Resend in the Convex dashboard:
10
AUTH_RESEND_KEY=re_...
AUTH_EMAIL_FROM=[email protected]
11
Wrap Your App
12
The ConvexClientProvider is automatically included. Wrap your app in main.tsx:
13
import { ConvexClientProvider } from './lib/convex/provider'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <ConvexClientProvider>
    <App />
  </ConvexClientProvider>
)

Components

LoginForm

Email and password login form with error handling.
import { LoginForm } from "@/components/login-form";

function LoginPage() {
  return (
    <div className="flex items-center justify-center min-h-screen">
      <LoginForm 
        onSignUpClick={() => navigate('/signup')}
        onForgotPasswordClick={() => navigate('/forgot-password')}
      />
    </div>
  );
}

Props

onSignUpClick
() => void
Callback when user clicks “Sign up” link. Use for navigation to sign-up page.
onForgotPasswordClick
() => void
Callback when user clicks “Forgot password?” link. Use for navigation to password reset.

SignUpForm

User registration form with password strength validation.
import { SignUpForm } from "@/components/sign-up-form";

function SignUpPage() {
  return (
    <div className="flex items-center justify-center min-h-screen">
      <SignUpForm 
        onLoginClick={() => navigate('/login')}
        onSuccess={() => navigate('/welcome')}
      />
    </div>
  );
}

Props

onLoginClick
() => void
Callback when user clicks “Sign in” link. Use for navigation to login page.
onSuccess
() => void
Callback after successful registration. Use for navigation or showing success message.

Usage Example

import { useState } from 'react';
import { LoginForm } from '@/components/login-form';
import { SignUpForm } from '@/components/sign-up-form';

function AuthPage() {
  const [view, setView] = useState<'login' | 'signup'>('login');
  
  return (
    <div className="min-h-screen flex items-center justify-center bg-gray-50">
      {view === 'login' ? (
        <LoginForm onSignUpClick={() => setView('signup')} />
      ) : (
        <SignUpForm onLoginClick={() => setView('login')} />
      )}
    </div>
  );
}

export default AuthPage;

Backend Functions

The component includes a complete Convex backend setup.

Auth Configuration

convex/auth.config.ts configures Convex Auth with password authentication:
import { AuthConfig } from "convex/server";

export default {
  providers: [
    {
      domain: process.env.CONVEX_SITE_URL!,
      applicationID: "convex",
    },
  ],
} satisfies AuthConfig;

User Queries

Get current user:
api.users.current
// Returns: { _id, name, email, image } | null
Get user by ID:
api.users.get({ userId: "j97..." })
// Returns: { _id, name, image } | null (public fields only)

User Mutations

Update profile:
api.users.updateProfile({ 
  name: "Jane Doe",
  image: "https://..." 
})

Authentication Hooks

Use the useAuthActions hook from Convex Auth:
import { useAuthActions } from "@convex-dev/auth/react";
import { useQuery } from "convex/react";
import { api } from "@/convex/_generated/api";

function UserProfile() {
  const { signOut } = useAuthActions();
  const user = useQuery(api.users.current);
  
  return (
    <div>
      <p>Logged in as {user?.email}</p>
      <button onClick={() => signOut()}>Sign Out</button>
    </div>
  );
}

Available Actions

signIn
(provider: string, formData: FormData) => Promise<void>
Sign in with email/password. Provider should be "password".
signOut
() => Promise<void>
Sign out the current user.

Validation

Both forms include built-in validation:

Login Form

  • Email format validation
  • Required fields
  • Error messages from backend

Sign-Up Form

  • Password must be at least 8 characters
  • Password confirmation must match
  • Name and email required
  • Sanitized input (trimmed whitespace)

Environment Variables

VITE_CONVEX_URL
string
required
Your Convex deployment URL from npx convex dev
CONVEX_DEPLOYMENT
string
required
Your Convex deployment name

Optional (Convex Dashboard)

AUTH_RESEND_KEY
string
Resend API key for email verification and password reset
AUTH_EMAIL_FROM
string
Sender email address (defaults to [email protected])

Customization

The forms use shadcn/ui components and can be fully customized:
import { LoginForm } from "@/components/login-form";

// Wrap in custom container
<div className="max-w-md mx-auto p-8 bg-gradient-to-b from-blue-50 to-white rounded-xl">
  <LoginForm />
</div>

// Or modify the component directly in your components folder

Security Features

Input Sanitization

All user inputs are trimmed and validated before processing

Password Validation

Minimum length requirements and confirmation matching

Secure Sessions

JWT-based authentication managed by Convex Auth

Public Data Only

User lookup functions never expose email or sensitive data

Next Steps

Social Auth

Add GitHub and Google sign-in

Current User Avatar

Display the logged-in user’s avatar

Realtime Chat

Build authenticated chat rooms

Build docs developers (and LLMs) love