Skip to main content
Villa Buena uses Auth0 for secure user authentication, providing a seamless login experience with automatic profile data integration.

Overview

User account features include:
  • Secure authentication via Auth0
  • Automatic profile data hydration
  • Persistent user preferences
  • Order history tracking
  • Shipping and payment information storage

Authentication with Auth0

Integration

The application uses the Auth0 React SDK for authentication:
import { useAuth0 } from "@auth0/auth0-react";

const { isAuthenticated, user, loginWithRedirect, logout } = useAuth0();
Auth0 handles all authentication flows, including login, signup, password reset, and social authentication.

User Store Architecture

The user store manages all user-related data with persistence:
src/store/useUserStore.js
import { create } from "zustand";
import { persist } from "zustand/middleware";

export const useUserStore = create(
  persist(
    (set) => ({
      shipping: {
        fullName: "",
        address: "",
        city: "",
      },

      payment: {
        cardNumber: "",
        expiryDate: "",
        cvc: "",
      },

      orders: [],

      setShipping: (data) =>
        set((state) => ({
          shipping: { ...state.shipping, ...data },
        })),

      setPayment: (data) =>
        set((state) => ({
          payment: { ...state.payment, ...data },
        })),

      hydrateFromAuth0: (user) =>
        set((state) => ({
          shipping: {
            ...state.shipping,
            fullName: state.shipping.fullName || user?.name || "",
          },
        })),

      addOrder: (order) =>
        set((state) => ({
          orders: [...state.orders, order],
        })),
    }),
    {
      name: "user-checkout-storage",
    },
  ),
);
All user data is stored in localStorage with the key user-checkout-storage, persisting across sessions.

Profile Data Hydration

Automatic Population

When a user logs in, their Auth0 profile data automatically populates relevant fields:
src/pages/checkoutShipping/CheckoutShipping.jsx
import { useAuth0 } from "@auth0/auth0-react";
import { useUserStore } from "../../store/useUserStore";

const { user } = useAuth0();
const hydrateFromAuth0 = useUserStore((state) => state.hydrateFromAuth0);

useEffect(() => {
  if (user) {
    hydrateFromAuth0(user);
  }
}, [user]);

Hydration Logic

1

Check Authentication

Verify user is authenticated via Auth0
2

Extract Profile Data

Get user name and other details from Auth0 user object
3

Populate Fields

Pre-fill shipping form with user’s name if not already set
4

Preserve Existing Data

Only hydrate empty fields - don’t overwrite user input
src/store/useUserStore.js
hydrateFromAuth0: (user) =>
  set((state) => ({
    shipping: {
      ...state.shipping,
      fullName: state.shipping.fullName || user?.name || "",
    },
  }))
The hydration logic uses a fallback pattern: existing value → Auth0 value → empty string, ensuring user input is never lost.

User Data Management

Shipping Information

Users’ shipping information is stored and managed through the store:

Full Name

Auto-populated from Auth0 profile

Address

Manually entered by user

City

Manually entered by user
src/store/useUserStore.js
shipping: {
  fullName: "",
  address: "",
  city: "",
},

setShipping: (data) =>
  set((state) => ({
    shipping: { ...state.shipping, ...data },
  }))

Payment Information

Payment information is stored in localStorage for user convenience during the session but should be cleared after order completion in a production environment.
src/store/useUserStore.js
payment: {
  cardNumber: "",
  expiryDate: "",
  cvc: "",
},

setPayment: (data) =>
  set((state) => ({
    payment: { ...state.payment, ...data },
  }))

Order History Management

Order Storage

Completed orders are added to the user’s order history:
src/store/useUserStore.js
orders: [],

addOrder: (order) =>
  set((state) => ({
    orders: [...state.orders, order],
  }))

Order Object Structure

Each order contains complete purchase information:
{
  id: "ABC12345",           // Unique 8-character order ID
  date: "2026-03-09T...",  // ISO timestamp
  items: [                  // Array of purchased products
    {
      id: 1,
      title: "Product Name",
      price: 29.99,
      thumbnail: "https://...",
      qty: 2
    }
  ],
  total: 59.98             // Total order amount
}

Adding Orders

Orders are created during checkout payment processing:
src/pages/checkoutpayment/CheckoutPayment.jsx
const orderId = Math.random().toString(36).substring(2, 10).toUpperCase();

addOrder({
  id: orderId,
  date: new Date().toISOString(),
  items: [...cart],
  total: cart.reduce((acc, item) => acc + item.price * item.qty, 0),
});
See Order History for details on viewing and displaying orders.

Authentication Flow

Login Process

1

User Clicks Login

User initiates login from navigation or protected page
2

Redirect to Auth0

Application redirects to Auth0 login page
3

Authenticate

User enters credentials or uses social login
4

Return to App

Auth0 redirects back with authentication token
5

Hydrate Profile

Application automatically populates user data

Protected Routes

Payment page requires authentication before access:
src/pages/checkoutpayment/CheckoutPayment.jsx
const { isAuthenticated, loginWithRedirect } = useAuth0();

const handlePayment = (e) => {
  e.preventDefault();

  if (!isAuthenticated) {
    loginWithRedirect({
      appState: { returnTo: "/checkout/payment" },
    });
    return;
  }

  // Process payment...
};
The returnTo parameter ensures users are redirected back to the payment page after logging in, maintaining their checkout flow.

Logout Process

Users can log out through the Auth0 SDK:
import { useAuth0 } from "@auth0/auth0-react";

const { logout } = useAuth0();

const handleLogout = () => {
  logout({ returnTo: window.location.origin });
};
Logging out clears Auth0 session but does NOT automatically clear localStorage data. Cart and order history persist across sessions.

User State Across Sessions

What Persists

Persisted Data

  • Shopping cart items
  • Order history
  • Shipping information
  • Payment form data

Session Only

  • Auth0 authentication token
  • Active login state
  • User profile from Auth0

Data Flow Diagram

Privacy and Security Considerations

Authentication

  • Auth0 handles all password security and encryption
  • OAuth tokens are managed by Auth0 SDK
  • No passwords are stored in application code

Data Storage

  • Shipping and order data persisted in localStorage
  • Payment information should be considered sensitive
  • Consider clearing payment data after order completion

Production Recommendations

  • Implement server-side order storage
  • Use tokenized payment methods
  • Encrypt sensitive data in localStorage
  • Add session timeouts for payment pages

Integration Points

Components Using User Data

Checkout Shipping

Uses shipping information and Auth0 profile

Checkout Payment

Requires authentication and uses payment data

Order History

Displays all user orders from store

Navigation

Shows login/logout based on auth state

Best Practices

Always check authentication state before accessing protected features, and provide clear login prompts when needed.

Development Guidelines

  1. State Management: Use the user store for all user-related data
  2. Hydration: Call hydrateFromAuth0 on every auth state change
  3. Validation: Validate all user input before storing
  4. Privacy: Be mindful of what data persists across sessions
  5. UX: Provide clear feedback for authentication state changes

Testing Authentication

const { isAuthenticated, isLoading, user } = useAuth0();

if (isLoading) {
  return <div>Loading...</div>;
}

if (!isAuthenticated) {
  return <div>Please log in</div>;
}

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

Build docs developers (and LLMs) love