Email & Password
Traditional email and password authentication.
Note: This is mock/placeholder content for demonstration purposes.
Email and password authentication is the traditional way users sign up and sign in.
Overview
Email/password authentication provides:
- User registration with email verification
- Secure password storage
- Password reset functionality
- Session management
Sign Up Flow
User Registration
import { signUpFunction } from '~/lib/auth/functions';
const result = await signUpFunction({
email: 'user@example.com',
password: 'SecurePassword123!',
});
Server Function Implementation
import { createServerFn } from '@tanstack/react-start';
import * as z from 'zod';
import { errorMiddleware } from '@kit/function-middleware/server';
const SignUpSchema = z.object({
email: z.email(),
password: z.string().min(8),
});
export const signUpFunction = createServerFn({ method: 'POST' })
.middleware([errorMiddleware])
.validator(SignUpSchema)
.handler(async ({ data }) => {
// Sign up user with auth service
const authData = await signUp({
email: data.email,
password: data.password,
options: {
emailRedirectTo: `${process.env.VITE_SITE_URL}/auth/callback`,
},
});
return { success: true, data: authData };
});
Sign Up Component
'use client';
import { useForm } from '@tanstack/react-form';
import { useMutation } from '@tanstack/react-query';
import { Field, FieldError, FieldLabel } from '@kit/ui/field';
import { Input } from '@kit/ui/input';
import { toast } from '@kit/ui/sonner';
import { signUpFunction } from '../_lib/functions';
export function SignUpForm() {
const signUp = useMutation({ mutationFn: signUpFunction });
const form = useForm({
defaultValues: { email: '', password: '' },
validators: { onSubmit: SignUpSchema },
onSubmit: async ({ value }) => {
const result = await signUp.mutateAsync({ data: value });
if (result.success) {
toast.success('Check your email to confirm your account');
}
},
});
return (
<form
onSubmit={(e) => {
e.preventDefault();
void form.handleSubmit();
}}
>
<form.Field name="email">
{(field) => (
<Field>
<FieldLabel>Email</FieldLabel>
<Input
type="email"
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
<FieldError errors={field.state.meta.errors} />
</Field>
)}
</form.Field>
<form.Field name="password">
{(field) => (
<Field>
<FieldLabel>Password</FieldLabel>
<Input
type="password"
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
<FieldError errors={field.state.meta.errors} />
</Field>
)}
</form.Field>
<button type="submit">Sign Up</button>
</form>
);
}
Sign In Flow
User Login
export const signInFunction = createServerFn({ method: 'POST' })
.middleware([errorMiddleware])
.validator(SignInSchema)
.handler(async ({ data }) => {
await signIn({
email: data.email,
password: data.password,
});
throw redirect({ href: '/home' });
});
Sign In Component
'use client';
import { useForm } from '@tanstack/react-form';
import { Field } from '@kit/ui/field';
import { Input } from '@kit/ui/input';
import { toast } from '@kit/ui/sonner';
export function SignInForm() {
const form = useForm({
defaultValues: { email: '', password: '' },
onSubmit: async ({ value }) => {
try {
await signInFunction({ data: value });
} catch (error) {
toast.error('Invalid email or password');
}
},
});
return (
<form
onSubmit={(e) => {
e.preventDefault();
void form.handleSubmit();
}}
>
<form.Field name="email">
{(field) => (
<Field>
<Input
type="email"
placeholder="Email"
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
</Field>
)}
</form.Field>
<form.Field name="password">
{(field) => (
<Field>
<Input
type="password"
placeholder="Password"
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
</Field>
)}
</form.Field>
<button type="submit">Sign In</button>
</form>
);
}
Email Verification
Requiring Email Confirmation
Configure in auth config:
// config/auth.config.ts
export const authConfig = {
requireEmailConfirmation: true,
};
Handling Unconfirmed Emails
export const signInFunction = createServerFn({ method: 'POST' })
.middleware([errorMiddleware])
.validator(SignInSchema)
.handler(async ({ data }) => {
try {
await signIn({
email: data.email,
password: data.password,
});
} catch (error) {
if (error.message.includes('Email not confirmed')) {
return {
success: false,
error: 'Please confirm your email before signing in',
};
}
throw error;
}
throw redirect({ href: '/home' });
});
Password Reset
Request Password Reset
export const requestPasswordResetFunction = createServerFn({ method: 'POST' })
.middleware([errorMiddleware])
.validator(z.object({ email: z.email() }))
.handler(async ({ data }) => {
await requestPasswordReset({
email: data.email,
redirectTo: `${process.env.VITE_SITE_URL}/auth/reset-password`,
});
return {
success: true,
message: 'Check your email for reset instructions',
};
});
Reset Password Form
'use client';
import { useForm } from '@tanstack/react-form';
import { Field } from '@kit/ui/field';
import { Input } from '@kit/ui/input';
import { toast } from '@kit/ui/sonner';
export function PasswordResetRequestForm() {
const form = useForm({
defaultValues: { email: '' },
onSubmit: async ({ value }) => {
const result = await requestPasswordResetFunction({ data: value });
if (result.success) {
toast.success(result.message);
}
},
});
return (
<form
onSubmit={(e) => {
e.preventDefault();
void form.handleSubmit();
}}
>
<form.Field name="email">
{(field) => (
<Field>
<Input
type="email"
placeholder="Enter your email"
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
</Field>
)}
</form.Field>
<button type="submit">Send Reset Link</button>
</form>
);
}
Update Password
export const updatePasswordFunction = createServerFn({ method: 'POST' })
.middleware([errorMiddleware])
.validator(z.object({ newPassword: z.string().min(8) }))
.handler(async ({ data }) => {
await updatePassword({
password: data.newPassword,
});
throw redirect({ href: '/home' });
});
Password Requirements
Validation Schema
const PasswordSchema = z .string() .min(8, 'Password must be at least 8 characters') .regex(/[A-Z]/, 'Password must contain an uppercase letter') .regex(/[a-z]/, 'Password must contain a lowercase letter') .regex(/[0-9]/, 'Password must contain a number') .regex(/[^A-Za-z0-9]/, 'Password must contain a special character');
Password Strength Indicator
'use client';
import { useState } from 'react';
export function PasswordInput() {
const [password, setPassword] = useState('');
const strength = calculatePasswordStrength(password);
return (
<div>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<div className="flex gap-1">
{[1, 2, 3, 4].map((level) => (
<div
key={level}
className={cn(
'h-1 flex-1 rounded',
strength >= level ? 'bg-green-500' : 'bg-gray-200'
)}
/>
))}
</div>
<span className="text-sm">
{strength === 4 && 'Strong password'}
{strength === 3 && 'Good password'}
{strength === 2 && 'Fair password'}
{strength === 1 && 'Weak password'}
</span>
</div>
);
}
Session Management
Checking Authentication Status
import { getSession } from '@kit/auth/server';
export async function requireAuth() {
const session = await getSession();
if (!session) {
throw redirect({ href: '/auth/sign-in' });
}
return session.user;
}
Sign Out
export const signOutFunction = createServerFn({ method: 'POST' })
.middleware([errorMiddleware])
.handler(async () => {
await signOut();
throw redirect({ href: '/auth/sign-in' });
});
Security Best Practices
- Enforce strong passwords - Minimum 8 characters, mixed case, numbers, symbols
- Rate limit login attempts - Prevent brute force attacks
- Use HTTPS only - Encrypt data in transit
- Enable email verification - Confirm email ownership
- Implement account lockout - After failed attempts
- Log authentication events - Track sign-ins and failures
- Support 2FA - Add extra security layer