Better Auth Foundation
Sigma Auth is built on top of Better Auth, a modern authentication framework that provides:
- Type-Safe: Full TypeScript support with type inference
- Framework Agnostic: Works with any web framework or platform
- Plugin Architecture: Extensible through custom plugins
- OAuth 2.0 Compatible: Standard OAuth flows with custom providers
Architecture Overview
Sigma Auth implements a custom Better Auth plugin called sigma that adds Bitcoin authentication support. The architecture consists of:
- Client plugin —
sigmaClient()from@sigma-auth/better-auth-plugin/client, handles OAuth flow initiation and callback handling - Server plugin (in the auth server) — manages Bitcoin signature verification
- OAuth bridge — standard OAuth 2.0 authorization code flow
Authentication Flow
Here's how the Bitcoin authentication flow works with Better Auth:
Client Configuration
Install the official Sigma Auth plugin for Better Auth:
bun add @sigma-auth/better-auth-plugin better-authConfigure the auth client:
import { createAuthClient } from 'better-auth/client';
import { sigmaClient } from '@sigma-auth/better-auth-plugin/client';
export const authClient = createAuthClient({
baseURL: 'https://auth.sigmaidentity.com',
plugins: [sigmaClient()],
});
// Export signIn and other utilities
export const { signIn } = authClient;Server-Side Token Exchange (Next.js)
Create a callback route to handle the OAuth code exchange:
import { createCallbackHandler } from "@sigma-auth/better-auth-plugin/next";
export const POST = createCallbackHandler();The callback handler:
- Exchanges the authorization code for tokens
- Signs the request with your member key
- Returns user profile with BAP identity data
Usage in Components
Sign In
'use client';
import { signIn } from '@/lib/auth-client';
const SIGMA_CLIENT_ID = process.env.NEXT_PUBLIC_SIGMA_CLIENT_ID ?? '';
export function SignInButton() {
const handleSignIn = () => {
signIn.sigma({ clientId: SIGMA_CLIENT_ID });
};
return (
<button type="button" onClick={handleSignIn}>
Sign In with Sigma
</button>
);
}The plugin handles PKCE automatically.
Session Management
import { useSession } from '@/lib/auth-client';
export function UserProfile() {
const { data: session, isPending } = useSession();
if (isPending) return <div>Loading...</div>;
if (!session) return <div>Not signed in</div>;
return (
<div>
<p>Welcome, {session.user.profile?.name || session.user.pubkey}</p>
<p>Bitcoin Address: {session.user.address}</p>
</div>
);
}OAuth Callback Page
The plugin's authClient.sigma.handleCallback takes the search params, verifies state, exchanges the code via your /api/auth/sigma/callback route, and returns the user and tokens. useSearchParams must be wrapped in <Suspense>.
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import { Suspense, useEffect, useState } from 'react';
import { authClient } from '@/lib/auth-client';
function CallbackContent() {
const router = useRouter();
const searchParams = useSearchParams();
const [error, setError] = useState('');
useEffect(() => {
authClient.sigma
.handleCallback(searchParams)
.then((result) => {
localStorage.setItem(
'auth_session',
JSON.stringify({ user: result.user, access_token: result.access_token })
);
router.push('/dashboard');
})
.catch((err: Error) => setError(err.message));
}, [searchParams, router]);
if (error) {
return <p>Error: {error}</p>;
}
return <p>Processing authentication...</p>;
}
export default function CallbackPage() {
return (
<Suspense fallback={<p>Loading...</p>}>
<CallbackContent />
</Suspense>
);
}Benefits of Better Auth
Type Safety
- Full TypeScript support with automatic type inference
- Type-safe plugin development
- No manual type definitions needed
Modern Architecture
- Plugin-based extensibility
- React Query integration
- Optimistic updates
Developer Experience
- Simple API with powerful features
- Excellent documentation
- Active community support
Environment Variables
# Required
NEXT_PUBLIC_SIGMA_CLIENT_ID=your-app
SIGMA_MEMBER_PRIVATE_KEY=your-member-wif
# Optional (defaults shown)
NEXT_PUBLIC_SIGMA_AUTH_URL=https://auth.sigmaidentity.comThe SIGMA_MEMBER_PRIVATE_KEY is used to sign token exchange requests. You receive this when you register your OAuth client at auth.sigmaidentity.com/account.
Learn More
For Bitcoin-specific features and implementation details, see our Bitcoin Authentication Guide.