--- title: "Email & Password" description: "Traditional email and password authentication." publishedAt: 2024-04-11 order: 2 status: "published" --- > **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 ```typescript import { signUpAction } from '~/lib/auth/actions'; const result = await signUpAction({ email: 'user@example.com', password: 'SecurePassword123!', }); ``` ### Server Action Implementation ```typescript 'use server'; import { enhanceAction } from '@kit/next/actions'; import * as z from 'zod'; const SignUpSchema = z.object({ email: z.string().email(), password: z.string().min(8), }); export const signUpAction = enhanceAction( async (data) => { const client = getSupabaseServerClient(); const { data: authData, error } = await client.auth.signUp({ email: data.email, password: data.password, options: { emailRedirectTo: `${process.env.NEXT_PUBLIC_SITE_URL}/auth/callback`, }, }); if (error) throw error; return { success: true, data: authData }; }, { schema: SignUpSchema } ); ``` ### Sign Up Component ```tsx 'use client'; import { useForm } from 'react-hook-form'; import { signUpAction } from '../_lib/actions'; export function SignUpForm() { const { register, handleSubmit, formState: { errors } } = useForm(); const onSubmit = async (data) => { const result = await signUpAction(data); if (result.success) { toast.success('Check your email to confirm your account'); } }; return (
{errors.email && Email is required}
{errors.password && Password must be 8+ characters}
); } ``` ## Sign In Flow ### User Login ```typescript export const signInAction = enhanceAction( async (data) => { const client = getSupabaseServerClient(); const { error } = await client.auth.signInWithPassword({ email: data.email, password: data.password, }); if (error) throw error; redirect('/home'); }, { schema: SignInSchema } ); ``` ### Sign In Component ```tsx 'use client'; export function SignInForm() { const { register, handleSubmit } = useForm(); const onSubmit = async (data) => { try { await signInAction(data); } catch (error) { toast.error('Invalid email or password'); } }; return (
); } ``` ## Email Verification ### Requiring Email Confirmation Configure in Supabase dashboard or config: ```typescript // config/auth.config.ts export const authConfig = { requireEmailConfirmation: true, }; ``` ### Handling Unconfirmed Emails ```typescript export const signInAction = enhanceAction( async (data) => { const client = getSupabaseServerClient(); const { data: authData, error } = await client.auth.signInWithPassword({ email: data.email, password: data.password, }); if (error) { if (error.message.includes('Email not confirmed')) { return { success: false, error: 'Please confirm your email before signing in', }; } throw error; } redirect('/home'); }, { schema: SignInSchema } ); ``` ## Password Reset ### Request Password Reset ```typescript export const requestPasswordResetAction = enhanceAction( async (data) => { const client = getSupabaseServerClient(); const { error } = await client.auth.resetPasswordForEmail(data.email, { redirectTo: `${process.env.NEXT_PUBLIC_SITE_URL}/auth/reset-password`, }); if (error) throw error; return { success: true, message: 'Check your email for reset instructions', }; }, { schema: z.object({ email: z.string().email(), }), } ); ``` ### Reset Password Form ```tsx 'use client'; export function PasswordResetRequestForm() { const { register, handleSubmit } = useForm(); const onSubmit = async (data) => { const result = await requestPasswordResetAction(data); if (result.success) { toast.success(result.message); } }; return (
); } ``` ### Update Password ```typescript export const updatePasswordAction = enhanceAction( async (data) => { const client = getSupabaseServerClient(); const { error } = await client.auth.updateUser({ password: data.newPassword, }); if (error) throw error; redirect('/home'); }, { schema: z.object({ newPassword: z.string().min(8), }), } ); ``` ## Password Requirements ### Validation Schema ```typescript 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 ```tsx 'use client'; import { useState } from 'react'; export function PasswordInput() { const [password, setPassword] = useState(''); const strength = calculatePasswordStrength(password); return (
setPassword(e.target.value)} />
{[1, 2, 3, 4].map((level) => (
= level ? 'bg-green-500' : 'bg-gray-200' )} /> ))}
{strength === 4 && 'Strong password'} {strength === 3 && 'Good password'} {strength === 2 && 'Fair password'} {strength === 1 && 'Weak password'}
); } ``` ## Session Management ### Checking Authentication Status ```typescript import { getSupabaseServerClient } from '@kit/supabase/server-client'; export async function requireAuth() { const client = getSupabaseServerClient(); const { data: { user } } = await client.auth.getUser(); if (!user) { redirect('/auth/sign-in'); } return user; } ``` ### Sign Out ```typescript export const signOutAction = enhanceAction( async () => { const client = getSupabaseServerClient(); await client.auth.signOut(); redirect('/auth/sign-in'); } ); ``` ## Security Best Practices 1. **Enforce strong passwords** - Minimum 8 characters, mixed case, numbers, symbols 2. **Rate limit login attempts** - Prevent brute force attacks 3. **Use HTTPS only** - Encrypt data in transit 4. **Enable email verification** - Confirm email ownership 5. **Implement account lockout** - After failed attempts 6. **Log authentication events** - Track sign-ins and failures 7. **Support 2FA** - Add extra security layer