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

# Auth

> Learn how to set up Flowglad server client using your auth provider of choice

Flowglad provides flexible authentication integration that works with any auth provider. You have complete control over how you define your customers, whether you're building a B2C app with individual users or a B2B platform with organization customers.

<Info>
  **Using Better Auth?** Check out the [Flowglad Better Auth plugin](/sdks/better-auth) for automatic customer creation and simplified integration.
</Info>

## Scoped Server Pattern

The scoped server pattern gives you maximum flexibility for defining customers and works seamlessly with any authentication provider. This approach uses a factory function that creates a `FlowgladServer` instance scoped to a specific customer.

**Key benefits:**

* Works with any auth provider
* Full control over customer identity (user ID for B2C, organization ID for B2B)

### Server Setup

Create a Flowglad server factory function in a shared file (e.g., `lib/flowglad.ts`):

<CodeGroup>
  ```ts Better Auth theme={null}
  import { FlowgladServer } from '@flowglad/nextjs/server'
  import { auth } from '@/utils/auth'
  import { headers } from 'next/headers'

  export const flowglad = (customerExternalId: string) => {
    return new FlowgladServer({
      customerExternalId,
      getCustomerDetails: async (customerExternalId) => {
        const session = await auth.api.getSession({
          headers: await headers(),
        })
        if (!session?.user) {
          throw new Error('User not authenticated')
        }
        return {
          email: session.user.email || '',
          name: session.user.name || ''
        }
      },
    })
  }
  ```

  <Info>
    **Better Auth users:** Flowglad provides a [Better Auth plugin](/sdks/better-auth) that simplifies integration by automatically creating customers and providing a convenient `getExternalId` endpoint. The plugin handles customer creation on sign-up and supports both user and organization-based customers.
  </Info>

  ```ts Supabase Auth theme={null}
  import { FlowgladServer } from '@flowglad/nextjs/server'
  import { createClient } from '@/utils/supabase/server'

  export const flowglad = (customerExternalId: string) => {
    return new FlowgladServer({
      customerExternalId,
      getCustomerDetails: async (customerExternalId) => {
        const supabase = await createClient()
        const { data: { user } } = await supabase.auth.getUser()
        if (!user) {
          throw new Error('User not authenticated')
        }
        return {
          email: user.email || '',
          name: user.user_metadata.name || user.email || ''
        }
      },
    })
  }
  ```

  ```ts Custom theme={null}
  import { FlowgladServer } from '@flowglad/nextjs/server'

  export const flowglad = (customerExternalId: string) => {
    // customerExternalId is the ID from YOUR app's database, NOT Flowglad's customer ID
    return new FlowgladServer({
      customerExternalId,
      getCustomerDetails: async (customerExternalId) => {
        // Fetch customer details from YOUR database using YOUR app's ID
        const user = await db.users.findOne({ id: customerExternalId })
        if (!user) {
          throw new Error('Customer not found')
        }
        return {
          email: user.email,
          name: user.name,
        }
      },
    })
  }
  ```

  ```ts B2B (Organization-based) theme={null}
  import { FlowgladServer } from '@flowglad/nextjs/server'

  export const flowglad = (organizationId: string) => {
    // For B2B apps: organizationId is ID from YOUR app's database
    return new FlowgladServer({
      customerExternalId: organizationId,
      getCustomerDetails: async (customerExternalId) => {
        // Fetch organization details from YOUR database using YOUR org ID
        const org = await db.organizations.findOne({ id: customerExternalId })
        if (!org) {
          throw new Error('Organization not found')
        }
        return {
          email: org.billingEmail || org.ownerEmail,
          name: org.name,
        }
      },
    })
  }
  ```
</CodeGroup>

<Note>
  **Important:** `customerExternalId` is the ID from **your app's database** (e.g., `user.id` or `organization.id`), **not** Flowglad's customer ID.

  **B2C apps:** Pass `user.id` as `customerExternalId`\
  **B2B apps:** Pass `organization.id` or `team.id` as `customerExternalId`
</Note>

### Next Route Handler Setup

Set up your Flowglad API route at `/api/flowglad/[...path]` to handle requests from your frontend:

<CodeGroup>
  ```ts Better Auth theme={null}
  import { nextRouteHandler } from '@flowglad/nextjs/server'
  import { flowglad } from '@/utils/flowglad'
  import { auth } from '@/utils/auth'
  import { headers } from 'next/headers'

  export const { GET, POST } = nextRouteHandler({
    flowglad,
    getCustomerExternalId: async (req) => {
      const session = await auth.api.getSession({
        headers: await headers(),
      })
      const userId = session?.user?.id
      if (!userId) {
        throw new Error('User not found')
      }
      return userId
    },
  })
  ```

  <Info>
    **Better Auth users:** If you're using the [Flowglad Better Auth plugin](/sdks/better-auth), you can use `auth.api.getExternalId()` instead of manually extracting the user ID. The plugin automatically handles customer type configuration (user vs organization).
  </Info>

  ```ts Supabase Auth theme={null}
  import { nextRouteHandler } from '@flowglad/nextjs/server'
  import { flowglad } from '@/utils/flowglad'
  import { createClient } from '@/utils/supabase/server'

  export const { GET, POST } = nextRouteHandler({
    flowglad,
    getCustomerExternalId: async (req) => {
      const supabase = await createClient()
      const {
        data: { user }
      } = await supabase.auth.getUser()
      const userId = user?.id
      if (!userId) {
        throw new Error('User not found')
      }
      return userId
    },
  })
  ```

  ```ts Clerk theme={null}
  import { nextRouteHandler } from '@flowglad/nextjs/server'
  import { flowglad } from '@/utils/flowglad'
  import { currentUser } from '@clerk/nextjs/server'

  export const { GET, POST } = nextRouteHandler({
    flowglad,
    getCustomerExternalId: async (req) => {
      const user = await currentUser()
      const userId = user?.id
      if (!userId) {
        throw new Error('User not found')
      }
      return userId
    },
  })
  ```

  ```ts Next Auth theme={null}
  import { nextRouteHandler } from '@flowglad/nextjs/server'
  import { flowglad } from '@/utils/flowglad'
  import { auth } from '@/auth'

  export const { GET, POST } = nextRouteHandler({
    flowglad,
    getCustomerExternalId: async (req) => {
      const session = await auth()
      const userId = session?.user?.id
      if (!userId) {
        throw new Error('User not found')
      }
      return userId
    },
  })
  ```

  ```ts Custom Auth theme={null}
  import { nextRouteHandler } from '@flowglad/nextjs/server'
  import { flowglad } from '@/utils/flowglad'
  import { yourAuthFunction } from '@/utils/auth'

  export const { GET, POST } = nextRouteHandler({
    flowglad,
    getCustomerExternalId: async (req) => {
      // Extract user/customer ID from your auth system
      const userId = await yourAuthFunction(req)
      if (!userId) {
        throw new Error('User not found')
      }
      return userId
    },
  })
  ```
</CodeGroup>
