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:
Sign Up Example
With Error Handling
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:
Sign In Example
From AuthContext
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:
Google OAuth
In React Component
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:
Request Reset
From AuthContext
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:
Reset Password
Complete Flow
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:
Get Session
useSession Hook (React)
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:
useAuth Hook
Available Methods
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:
Error Translation
Errors are translated using the translateAuthError utility for user-friendly messages
State Updates
Error messages are stored in the auth state for display in the UI
Auto-Clear
Errors automatically clear after 5 seconds to prevent stale error messages
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