> ## Documentation Index
> Fetch the complete documentation index at: https://twigz.arqqin.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Secure authentication with Clerk and Convex integration

## Overview

The Twigz API uses **Clerk** for authentication integrated with **Convex** for secure, scalable user management. This system supports multiple authentication methods and provides role-based access control for customers, store owners, and administrators.

## Authentication Flow

<Steps>
  <Step title="User Registration/Login">
    Users authenticate through Clerk using email, phone, or social providers
  </Step>

  <Step title="JWT Token Generation">
    Clerk generates a secure JWT token for the authenticated user
  </Step>

  <Step title="Convex Integration">
    Token is automatically validated by Convex for API access
  </Step>

  <Step title="Role-based Access">
    API functions check user roles and permissions automatically
  </Step>
</Steps>

## Setup Authentication

### Frontend Setup (React)

<CodeGroup>
  ```typescript Next.js App Router theme={null}
  // app/layout.tsx
  import { ClerkProvider } from '@clerk/nextjs'
  import { ConvexProviderWithClerk } from "convex/react-clerk";
  import { ConvexReactClient } from "convex/react";

  const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

  export default function RootLayout({
    children,
  }: {
    children: React.ReactNode
  }) {
    return (
      <ClerkProvider
        publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY!}
      >
        <ConvexProviderWithClerk client={convex}>
          <html lang="en">
            <body>{children}</body>
          </html>
        </ConvexProviderWithClerk>
      </ClerkProvider>
    )
  }
  ```

  ```typescript React Component theme={null}
  // components/AuthenticatedApp.tsx
  import { SignIn, SignUp, UserButton, useUser } from "@clerk/nextjs";
  import { Authenticated, Unauthenticated } from "convex/react";

  function AuthenticatedApp() {
    return (
      <>
        <Unauthenticated>
          <div className="flex items-center justify-center min-h-screen">
            <div className="max-w-md w-full">
              <h1 className="text-2xl font-bold text-center mb-6">
                Welcome to Twigz
              </h1>
              <SignIn 
                routing="hash"
                signUpUrl="#/sign-up"
              />
            </div>
          </div>
        </Unauthenticated>
        
        <Authenticated>
          <div className="min-h-screen bg-gray-50">
            {/* Navigation */}
            <nav className="bg-white shadow">
              <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
                <div className="flex justify-between h-16">
                  <div className="flex items-center">
                    <h1 className="text-xl font-bold">Twigz Dashboard</h1>
                  </div>
                  <div className="flex items-center">
                    <UserButton afterSignOutUrl="/" />
                  </div>
                </div>
              </div>
            </nav>
            
            {/* Main App Content */}
            <main className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
              <Dashboard />
            </main>
          </div>
        </Authenticated>
      </>
    );
  }

  export default AuthenticatedApp;
  ```

  ```typescript React Native theme={null}
  // App.tsx
  import { ClerkProvider, SignedIn, SignedOut } from '@clerk/clerk-expo';
  import { ConvexProviderWithClerk } from 'convex/react-clerk';
  import { ConvexReactClient } from 'convex/react';

  const convex = new ConvexReactClient(process.env.EXPO_PUBLIC_CONVEX_URL!);

  export default function App() {
    return (
      <ClerkProvider publishableKey={process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY!}>
        <ConvexProviderWithClerk client={convex}>
          <SignedOut>
            <LoginScreen />
          </SignedOut>
          <SignedIn>
            <MainApp />
          </SignedIn>
        </ConvexProviderWithClerk>
      </ClerkProvider>
    );
  }
  ```
</CodeGroup>

### Backend Setup (Convex)

<CodeGroup>
  ```typescript Convex Configuration theme={null}
  // convex/auth.config.ts
  export default {
    providers: [
      {
        domain: process.env.CLERK_JWT_ISSUER_DOMAIN!,
        applicationID: "convex",
      },
    ]
  };
  ```

  ```typescript Environment Variables theme={null}
  // .env.local
  NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
  CLERK_SECRET_KEY=sk_test_...
  NEXT_PUBLIC_CONVEX_URL=https://your-deployment.convex.cloud
  CLERK_JWT_ISSUER_DOMAIN=https://your-clerk-domain.clerk.accounts.dev
  ```
</CodeGroup>

## User Roles & Permissions

The system supports three main user roles:

<CardGroup cols={3}>
  <Card title="Customer" icon="user">
    **Permissions**: Place orders, manage cart, view own data\
    **Access**: Customer functions, public store data
  </Card>

  <Card title="Store Owner" icon="store">
    **Permissions**: Manage store, products, orders, settings\
    **Access**: Store functions, own store data, customer orders
  </Card>

  <Card title="Admin" icon="shield">
    **Permissions**: Platform management, store approval, analytics\
    **Access**: All functions, system-wide data
  </Card>
</CardGroup>

## Protected API Calls

<CodeGroup>
  ```typescript Authenticated Queries theme={null}
  import { useQuery, useMutation } from "convex/react";
  import { api } from "./convex/_generated/api";

  function CustomerProfile() {
    // Automatically authenticated - returns data for current user
    const profile = useQuery(api.customers.account.getCustomerProfile);
    
    if (profile === undefined) return <div>Loading...</div>;
    if (profile === null) return <div>Please complete your profile</div>;
    
    return <div>Welcome, {profile.name}!</div>;
  }

  function StoreOwnerDashboard() {
    // Only accessible to store owners
    const store = useQuery(api.stores.queries.getStoreByAuthenticatedOwner);
    const updateStore = useMutation(api.stores.operations.updateStore);
    
    const handleStoreUpdate = async (updates: any) => {
      try {
        await updateStore(updates);
      } catch (error) {
        if (error.message.includes('permission')) {
          console.error('Access denied: User is not a store owner');
        }
      }
    };
    
    return <div>{/* Store dashboard */}</div>;
  }
  ```

  ```typescript Server-side Authentication theme={null}
  // For server-side API calls
  import { ConvexHttpClient } from "convex/node";

  const convex = new ConvexHttpClient(process.env.CONVEX_URL!);

  // Get user token from Clerk
  const token = await getAuth(req).getToken({ template: "convex" });

  // Make authenticated API call
  const result = await convex.query(
    "customers.account.getCustomerProfile",
    {},
    { token }
  );
  ```
</CodeGroup>

## Authentication Patterns

### Role-based Component Access

<CodeGroup>
  ```typescript Role Guard Component theme={null}
  import { useUser } from "@clerk/nextjs";

  interface RoleGuardProps {
    allowedRoles: ('customer' | 'store_owner' | 'admin')[];
    children: React.ReactNode;
    fallback?: React.ReactNode;
  }

  function RoleGuard({ allowedRoles, children, fallback }: RoleGuardProps) {
    const { user } = useUser();
    
    const userRole = user?.publicMetadata?.role as string;
    
    if (!userRole || !allowedRoles.includes(userRole as any)) {
      return fallback || <div>Access denied</div>;
    }
    
    return <>{children}</>;
  }

  // Usage
  <RoleGuard allowedRoles={['store_owner', 'admin']}>
    <StoreManagementPanel />
  </RoleGuard>

  <RoleGuard allowedRoles={['admin']}>
    <AdminDashboard />
  </RoleGuard>
  ```

  ```typescript Custom Hook theme={null}
  function useUserRole() {
    const { user } = useUser();
    
    const role = user?.publicMetadata?.role as string;
    
    return {
      role,
      isCustomer: role === 'customer',
      isStoreOwner: role === 'store_owner', 
      isAdmin: role === 'admin',
      hasAccess: (requiredRoles: string[]) => requiredRoles.includes(role)
    };
  }

  // Usage in component
  function MyComponent() {
    const { isStoreOwner, isAdmin, hasAccess } = useUserRole();
    
    return (
      <div>
        {isStoreOwner && <StoreControls />}
        {isAdmin && <AdminControls />}
        {hasAccess(['store_owner', 'admin']) && <ManagementPanel />}
      </div>
    );
  }
  ```
</CodeGroup>

## User Registration Flow

<CodeGroup>
  ```typescript Customer Registration theme={null}
  import { useUser } from "@clerk/nextjs";
  import { useMutation } from "convex/react";
  import { api } from "./convex/_generated/api";

  function CustomerOnboarding() {
    const { user } = useUser();
    const registerCustomer = useMutation(api.customers.account.registerCustomer);
    
    const handleRegistration = async () => {
      try {
        const customerId = await registerCustomer({
          preferredLanguage: "en"
        });
        
        console.log('Customer registered:', customerId);
        
        // Update Clerk user metadata
        await user?.update({
          publicMetadata: {
            role: 'customer',
            customerId: customerId
          }
        });
        
      } catch (error) {
        console.error('Registration failed:', error);
      }
    };
    
    return (
      <button onClick={handleRegistration}>
        Complete Registration
      </button>
    );
  }
  ```

  ```typescript Store Owner Registration theme={null}
  function StoreOwnerOnboarding() {
    const { user } = useUser();
    const registerStore = useMutation(api.stores.operations.registerStore);
    
    const handleStoreRegistration = async (storeData: any) => {
      try {
        const storeId = await registerStore(storeData);
        
        // Update user role to store owner
        await user?.update({
          publicMetadata: {
            role: 'store_owner',
            storeId: storeId
          }
        });
        
        console.log('Store registered:', storeId);
        
      } catch (error) {
        console.error('Store registration failed:', error);
      }
    };
    
    return <StoreRegistrationForm onSubmit={handleStoreRegistration} />;
  }
  ```
</CodeGroup>

## Error Handling

<AccordionGroup>
  <Accordion title="Unauthenticated">
    **Status Code**: `401`

    ```json theme={null}
    {
      "error": "Authentication required",
      "message": "Please sign in to access this resource"
    }
    ```
  </Accordion>

  <Accordion title="Insufficient permissions">
    **Status Code**: `403`

    ```json theme={null}
    {
      "error": "Insufficient permissions",
      "requiredRole": "store_owner",
      "userRole": "customer"
    }
    ```
  </Accordion>

  <Accordion title="Invalid token">
    **Status Code**: `401`

    ```json theme={null}
    {
      "error": "Invalid authentication token",
      "message": "Token has expired or is malformed"
    }
    ```
  </Accordion>

  <Accordion title="Account suspended">
    **Status Code**: `403`

    ```json theme={null}
    {
      "error": "Account suspended",
      "reason": "Violation of terms of service",
      "suspendedUntil": 1640995200000
    }
    ```
  </Accordion>
</AccordionGroup>

## Security Best Practices

<CardGroup cols={2}>
  <Card title="Token Security" icon="key">
    Never expose secret keys in client-side code. Use environment variables for all sensitive configuration.
  </Card>

  <Card title="Role Validation" icon="shield-check">
    Always validate user roles on both client and server side for security in depth.
  </Card>

  <Card title="Session Management" icon="clock">
    Implement proper session timeout and refresh mechanisms for long-running applications.
  </Card>

  <Card title="Audit Logging" icon="list-check">
    Log all authentication events and permission changes for security monitoring.
  </Card>
</CardGroup>

<Note>
  All API functions automatically validate authentication and permissions. You don't need to manually check authentication in most cases.
</Note>

<Tip>
  Use Clerk's built-in components for authentication UI to ensure security best practices and consistent user experience.
</Tip>
