BunshipBunship
Integrations

Authentication

Choose Better Auth or Clerk for Bunship authentication.

Bunship supports two auth providers:

  • Better Auth (default, fully integrated auth + MFA + passkeys + API keys)
  • Clerk (managed auth UI + user sync via webhook)

Choose the provider by setting NEXT_PUBLIC_AUTH_PROVIDER in your environment. If not set, Bunship defaults to better-auth.

Setup

Follow the section that matches your provider.

1. Choose provider (default: Better Auth)

# Better Auth (default)
NEXT_PUBLIC_AUTH_PROVIDER=better-auth

# Clerk
NEXT_PUBLIC_AUTH_PROVIDER=clerk

2. Better Auth setup

Generate Better Auth Secret

BETTER_AUTH_SECRET is used for session and token signing.

openssl rand -base64 32

Add to .env:

BETTER_AUTH_SECRET="YOUR-BETTER-AUTH-SECRET"
BETTER_AUTH_URL="http://localhost:3001"

Configure GitHub OAuth

Create a GitHub OAuth App and set callback URLs:

  • Local: http://localhost:3001/api/v1/auth/callback/github
  • Production: https://YOUR_DOMAIN/api/v1/auth/callback/github

Add to .env:

OAUTH_GITHUB_CLIENT_ID="YOUR-GITHUB-CLIENT-ID"
OAUTH_GITHUB_CLIENT_SECRET="YOUR-GITHUB-CLIENT-SECRET"

Use separate OAuth apps for development and production environments.

Configure Google OAuth

Create a Google OAuth client and set callback URLs:

  • Local: http://localhost:3001/api/v1/auth/callback/google
  • Production: https://YOUR_DOMAIN/api/v1/auth/callback/google

Add to .env:

OAUTH_GOOGLE_CLIENT_ID="YOUR-GOOGLE-CLIENT-ID"
OAUTH_GOOGLE_CLIENT_SECRET="YOUR-GOOGLE-CLIENT-SECRET"
NEXT_PUBLIC_OAUTH_GOOGLE_CLIENT_ID="YOUR-GOOGLE-CLIENT-ID"

Enable credential login

Email/password login requires email delivery to be configured first.

3. Clerk setup

  1. Create a Clerk application.
  2. Add the following environment variables:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="YOUR-CLERK-PUBLISHABLE-KEY"
CLERK_SECRET_KEY="YOUR-CLERK-SECRET-KEY"
CLERK_WEBHOOK_SECRET="YOUR-CLERK-WEBHOOK-SECRET"
  1. Configure Clerk webhooks to sync users into the Bunship database:
  • Endpoint: https://YOUR_DOMAIN/api/v1/webhook/clerk
  • Events: user.created, user.updated, user.deleted

Core Features

  • Email auth and verification flow
  • Google and GitHub social login
  • Account linking across auth methods
  • Invitation attribution for email and OAuth signup
  • Automatic wallet initialization for new users

Better Auth only:

  • MFA and passkey support
  • API key management

Client-Side Usage

Access session

'use client';

import { authClient } from '@/lib/auth-client';

export function ProfileButton() {
  const { data: session, isPending } = authClient.useSession();

  if (isPending) return <div>Loading...</div>;
  if (!session?.user) return <button>Sign in</button>;

  return <button>{session.user.name}</button>;
}

Auth operations

authClient.signIn.* APIs are Better Auth only. In Clerk mode, use Clerk UI components like SignIn / SignUp.

import { authClient } from '@/lib/auth-client';

await authClient.signIn.email({
  email: 'user@example.com',
  password: 'password123',
});

await authClient.signIn.social({
  provider: 'google',
  callbackURL: '/',
});

await authClient.signOut();

Server-Side Usage

Route protection

import { getSession } from '@/lib/session';
import { redirect } from 'next/navigation';

export default async function ProtectedPage() {
  const session = await getSession();

  if (!session?.user) {
    redirect('/signin');
  }

  return <div>Protected content</div>;
}

Admin-only guard

import { getSession } from '@/lib/session';
import { redirect } from 'next/navigation';

export default async function AdminPage() {
  const session = await getSession();

  if (!session?.user || session.user.role !== 'admin') {
    redirect('/signin');
  }

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

Best Practices

  1. Keep OAuth apps and secrets separate by environment.
  2. Keep callback URLs aligned with deployment domains.
  3. Enforce role checks server-side for sensitive routes.
  4. Debug auth failures from callback URL + cookie policy + env consistency.
  5. For Clerk, ensure webhook events are delivered and idempotent.

Next Steps