Email/Password

Traditional email and password authentication with verification

Email/password authentication is the primary method for user registration. It includes email verification via OTP and password reset functionality.

Registration Flow

User submits registration form

The form collects first name, last name, email, and password.

Backend validates and creates account

Input is validated, password is hashed, and a verification OTP is generated.

Verification email sent

A 6-digit code is sent to the user's email address.

User verifies email

User enters the OTP code to complete registration.

Profile created and tokens issued

User profile is created with an auto-generated username. JWT tokens are returned.

Password Requirements

RequirementDescription
LengthMinimum 8 characters
UppercaseAt least one uppercase letter (A-Z)
LowercaseAt least one lowercase letter (a-z)
NumberAt least one digit (0-9)
SpecialAt least one special character (!@#$%^&*)

For detailed API documentation including request/response examples, see the Auth Endpoints reference.

Frontend Implementation

Registration Form

import { useCreateAccount } from '@/hooks/auth/useAuthMutations';
import { useRouter } from 'next/navigation';

function RegistrationForm() {
  const router = useRouter();
  const createAccount = useCreateAccount();

  const handleSubmit = async (data: CreateAccountData) => {
    createAccount.mutate(data, {
      onSuccess: (response) => {
        // Store email for verification page
        sessionStorage.setItem('pendingEmail', data.email);
        router.push('/email-verification');
      },
    });
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* Form fields */}
    </form>
  );
}

Login Form

import { useLogin } from '@/hooks/auth/useAuthMutations';
import { useAuth } from '@/providers/auth-provider';

function LoginForm() {
  const { login: setAuth } = useAuth();
  const loginMutation = useLogin();

  const handleSubmit = async (data: LoginData) => {
    loginMutation.mutate(data, {
      onSuccess: (response) => {
        const { accessToken, refreshToken, session, user } = response.data;
        setAuth(accessToken, refreshToken, user, {
          sessionId: session.sessionId,
        });
        router.push('/dashboard');
      },
    });
  };
}

Password Reset

import { useForgotPassword, useResetPassword } from '@/hooks/auth/useAuthMutations';

function ForgotPasswordForm() {
  const forgotPassword = useForgotPassword();

  const handleSubmit = (email: string) => {
    forgotPassword.mutate({ email }, {
      onSuccess: () => {
        router.push(`/reset-password?email=${encodeURIComponent(email)}`);
      },
    });
  };
}

function ResetPasswordForm({ email }: { email: string }) {
  const resetPassword = useResetPassword();

  const handleSubmit = (data: ResetPasswordData) => {
    resetPassword.mutate({ ...data, email }, {
      onSuccess: () => {
        router.push('/log-in');
      },
    });
  };
}

Validation Schemas

The registration and login forms use Zod schemas for validation:

src/zod/authValidation.ts
import { z } from 'zod';

export const createAccountSchema = z.object({
  firstName: z.string().min(1).max(20),
  lastName: z.string().min(1).max(20),
  email: z.string().email(),
  password: z.string()
    .min(8)
    .regex(/[A-Z]/, 'Must contain uppercase letter')
    .regex(/[a-z]/, 'Must contain lowercase letter')
    .regex(/[0-9]/, 'Must contain number')
    .regex(/[!@#$%^&*]/, 'Must contain special character'),
  confirmPassword: z.string(),
}).refine((data) => data.password === data.confirmPassword, {
  message: 'Passwords do not match',
  path: ['confirmPassword'],
});

export const loginSchema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
});

On this page