Skip to main content

Introduction

Inmobiliaria Web uses Better Auth for authentication, providing a secure, modern authentication system with support for:
  • Email and password authentication
  • Google OAuth integration
  • Session management with secure cookies
  • Password reset flows
  • Email verification
  • Admin role management

Authentication Client Setup

The authentication client is initialized with the API origin URL and includes the admin plugin:
import { createAuthClient } from "better-auth/react";
import { adminClient } from "better-auth/client/plugins";
import { API_ORIGIN } from "./api";

export const authClient = createAuthClient({
  baseURL: API_ORIGIN,
  plugins: [adminClient()],
});
The API_ORIGIN is automatically derived from API_BASE by removing the /api suffix. In production, this ensures authentication requests go to the correct domain.

Email & Password Authentication

Sign Up

Create a new user account with email verification:
import { authClient } from '@/lib/auth-client';

const handleSignUp = async (email: string, password: string, name: string) => {
  const response = await authClient.signUp.email({
    email,
    password,
    name,
    callbackURL: '/', // Redirect after email verification
  });

  if (response.error) {
    throw response.error;
  }

  // User created successfully
  // Email verification sent automatically
};
After sign up, users must verify their email before they can sign in. The verification email is sent automatically by Better Auth.

Sign In

Authenticate existing users:
import { authClient } from '@/lib/auth-client';

const handleSignIn = async (email: string, password: string) => {
  const response = await authClient.signIn.email({
    email,
    password,
  });

  if (response.error) {
    throw response.error;
  }

  // Session created successfully
  // Cookie set automatically
};

Sign Out

End the user session:
import { authClient } from '@/lib/auth-client';

const handleSignOut = async () => {
  await authClient.signOut();
  // Session cookie cleared automatically
  // Redirect to home or login page
};

OAuth Authentication

Google Sign In

Authenticate users via Google OAuth:
import { authClient } from '@/lib/auth-client';

const handleGoogleSignIn = async () => {
  await authClient.signIn.social({
    provider: 'google',
    callbackURL: '/dashboard',
  });
  
  // User will be redirected to Google for authentication
  // After approval, redirected back to callbackURL
};
Google OAuth requires proper configuration on the backend with valid OAuth client credentials. Contact your administrator to ensure Google authentication is properly configured.

Password Reset Flow

Request Password Reset

Send a password reset email to the user:
import { authClient } from '@/lib/auth-client';

const handleForgotPassword = async (email: string) => {
  const response = await authClient.forgetPassword({
    email,
    redirectTo: `${window.location.origin}/reset-password`,
  });

  if (response.error) {
    throw response.error;
  }

  // Reset email sent successfully
};

Reset Password

Complete the password reset with the token from the email:
import { authClient } from '@/lib/auth-client';

const handleResetPassword = async (token: string, newPassword: string) => {
  const { error } = await authClient.resetPassword({
    newPassword,
    token,
  });

  if (error) {
    throw error;
  }

  // Password reset successfully
  // User must sign in with new password
};
After a successful password reset, Better Auth does NOT create a session automatically. Users must sign in manually with their new password.

Session Management

Get Current Session

Retrieve the current user session:
import { authClient } from '@/lib/auth-client';

const getCurrentUser = async () => {
  const { data } = await authClient.getSession();

  if (data?.user) {
    return data.user;
  }

  return null;
};

Refresh Session

Manually refresh the session to get updated user data:
// From src/contexts/AuthContext.tsx
const refreshSession = async () => {
  try {
    const { data } = await authClient.getSession();

    if (data?.user) {
      const user = data.user as unknown as User;
      
      // Fetch user favorites
      try {
        const favoritesResponse = await api.users.getFavorites();
        const favoriteIds = favoritesResponse.data?.map(
          (property: Property) => property.id
        ) || [];

        setAuthState({
          user,
          loading: false,
          error: null,
          favoritePropertyIds: favoriteIds,
          refreshingSession: false,
        });
      } catch {
        setAuthState({
          user,
          loading: false,
          error: null,
          favoritePropertyIds: [],
          refreshingSession: false,
        });
      }

      return user;
    } else {
      setAuthState({
        user: null,
        loading: false,
        error: null,
        favoritePropertyIds: [],
        refreshingSession: false,
      });
      return null;
    }
  } catch {
    setAuthState({
      user: null,
      loading: false,
      error: null,
      favoritePropertyIds: [],
      refreshingSession: false,
    });
    return null;
  }
};

Authentication Context

The application provides a React Context for managing authentication state:
import { useAuth } from '@/contexts/AuthContext';

function MyComponent() {
  const {
    user,
    loading,
    error,
    signIn,
    signUp,
    signOut,
    refreshSession,
    requestPasswordReset,
    resetPassword,
  } = useAuth();

  if (loading) return <div>Loading...</div>;
  if (!user) return <div>Please sign in</div>;

  return <div>Welcome, {user.name}!</div>;
}

Session Cookies

Better Auth uses secure, HTTP-only cookies for session management:
  • Automatic inclusion: The API client includes credentials: "include" in all requests
  • Secure by default: Cookies are HTTP-only and secure in production
  • CORS support: Backend must be configured to accept credentials from your frontend domain
Ensure your API server is configured with proper CORS settings to accept credentials from your frontend domain. The Access-Control-Allow-Credentials header must be set to true.

User Roles

Users can have one of two roles:
  • user - Standard user with access to public endpoints and their own data
  • admin - Administrator with access to all endpoints including admin operations
import { useAuth } from '@/contexts/AuthContext';

function AdminPanel() {
  const { user } = useAuth();

  if (user?.role !== 'admin') {
    return <div>Access denied</div>;
  }

  return <div>Admin panel content</div>;
}

Error Handling

All authentication methods in the AuthContext include comprehensive error handling:
1

Error Translation

Errors are translated using the translateAuthError utility for user-friendly messages
2

State Updates

Error messages are stored in the auth state for display in the UI
3

Auto-Clear

Errors automatically clear after 5 seconds to prevent stale error messages
4

Error Propagation

Errors are re-thrown to allow components to handle them locally
import { useAuth } from '@/contexts/AuthContext';
import { useState } from 'react';

function LoginForm() {
  const { signIn, error: authError } = useAuth();
  const [localError, setLocalError] = useState<string | null>(null);

  const handleSubmit = async (email: string, password: string) => {
    try {
      await signIn(email, password);
      // Success - redirect or show success message
    } catch (error) {
      setLocalError(error.message);
    }
  };

  return (
    <form>
      {authError && <div className="error">{authError}</div>}
      {localError && <div className="error">{localError}</div>}
      {/* Form fields */}
    </form>
  );
}

Best Practices

Use the Context

Always use the AuthProvider and useAuth hook instead of calling authClient directly

Handle Loading States

Check the loading state before rendering protected content

Verify Email

Remind users to verify their email after sign up

Secure Redirects

Always use absolute URLs for callbackURL and redirectTo parameters

Next Steps

Properties API

Learn how to manage property listings

Users API

Manage user profiles and preferences

Admin API

Administrative operations for admins

API Overview

Learn about API structure and error handling

Build docs developers (and LLMs) love