GuidesAuthentication
Authentication
Better Auth in BetterCone - email/password, GitHub OAuth, 2FA, and API keys
BetterCone uses Better Auth integrated with Convex for authentication and session management.
What's Included
BetterCone's auth setup includes:
- Email & Password - Traditional authentication
- GitHub OAuth - Social login
- Two-Factor Auth - TOTP-based 2FA
- Username - Optional username support
- API Keys - For programmatic access
- Organizations - Team-based access control
Quick Start
Check Session
import { authClient } from "@/lib/auth-client";
function Profile() {
const { data: session } = authClient.useSession();
if (!session) return <p>Not logged in</p>;
return <p>Welcome, {session.user.email}!</p>;
}Sign Out
await authClient.signOut();Authentication Setup
Client Configuration
// apps/web/src/lib/auth-client.ts
import { createAuthClient } from "better-auth/react";
import { convexClient } from "@convex-dev/better-auth/client/plugins";
import { organizationClient, apiKeyClient } from "better-auth/client/plugins";
import { stripeClient } from "@better-auth/stripe/client";
export const authClient = createAuthClient({
baseURL: window.location.origin,
plugins: [
convexClient(),
organizationClient(),
apiKeyClient(),
stripeClient(),
],
});Server Configuration
// packages/convex/convex/auth.ts
import { betterAuth } from "better-auth";
import { organization, twoFactor, username, apiKey } from "better-auth/plugins";
import { stripe } from "@better-auth/stripe";
export const createAuth = (ctx) => {
return betterAuth({
baseURL: process.env.SITE_URL,
database: authComponent.adapter(ctx),
emailAndPassword: {
enabled: true,
requireEmailVerification: false,
},
socialProviders: {
github: {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
},
},
plugins: [
convex(),
organization({ /* ... */ }),
twoFactor({ issuer: process.env.SITE_URL }),
username(),
apiKey({
defaultPrefix: "ba_",
rateLimit: { enabled: true, maxRequests: 1000 },
}),
stripe({ /* ... */ }),
],
});
};Authentication Methods
UI Components
BetterCone uses @daveyplate/better-auth-ui:
import { AuthView, UserButton, SignedIn, SignedOut } from "@daveyplate/better-auth-ui";
// Sign in page
export default function SignInPage() {
return <AuthView view="SIGN_IN" />;
}
// User avatar + dropdown
<SignedIn>
<UserButton />
</SignedIn>
<SignedOut>
<Link href="/auth/sign-in">Sign In</Link>
</SignedOut>Available views:
SIGN_IN- Email/password + GitHub OAuthSIGN_UP- Create accountFORGOT_PASSWORD- Request reset link
GitHub OAuth
Setup in GitHub Settings:
- Create OAuth App
- Set callback URL:
https://yourdomain.com/api/auth/callback/github - Add to
.env:
GITHUB_CLIENT_ID=Ov23...
GITHUB_CLIENT_SECRET=abc123...Users can now click "Sign in with GitHub" in the UI.
Two-Factor Authentication
Enable 2FA for extra security:
// Enable 2FA
await authClient.twoFactor.enable({
password: userPassword,
});
// Returns QR code URI for authenticator app
// { qrCode: "otpauth://totp/...", secret: "..." }
// Verify with TOTP code
await authClient.twoFactor.verify({
code: "123456",
});API Keys
Generate API keys for programmatic access:
// Create API key
const { data: apiKey } = await authClient.apiKey.create({
name: "Production API",
expiresIn: 1000 * 60 * 60 * 24 * 365, // 1 year
});
// Returns: { key: "ba_xxx...", name: "Production API" }
// Use in requests
fetch("/api/data", {
headers: {
"Authorization": `Bearer ${apiKey.key}`,
},
});
// List keys
const { data: keys } = await authClient.apiKey.list();
// Revoke key
await authClient.apiKey.revoke({ id: keyId });API keys have rate limiting (1000 requests/min by default).
Custom User Fields
BetterCone extends the user model:
// packages/convex/convex/auth.ts
user: {
additionalFields: {
company: { type: "string", required: false },
phone: { type: "string", required: false },
bio: { type: "string", required: false },
},
}Access in session:
const { data: session } = authClient.useSession();
console.log(session?.user.company);Environment Variables
# Required
BETTER_AUTH_SECRET=... # openssl rand -base64 32
SITE_URL=http://localhost:3000
# OAuth (optional)
GITHUB_CLIENT_ID=Ov23...
GITHUB_CLIENT_SECRET=...
# Email (optional)
RESEND_API_KEY=re_...Security Features
BetterCone includes:
- Rate limiting - 1000 requests/min per API key
- CSRF protection - Built into Better Auth
- Secure sessions - HTTP-only cookies
- Password hashing - Bcrypt by default
- Email verification - Optional (disabled in dev)
Best Practices
- Use HTTPS in production
- Set strong secrets -
openssl rand -base64 32 - Enable email verification for production
- Require 2FA for admin users
- Rotate API keys regularly
- Monitor failed login attempts