@agentuity/auth
First-class authentication for Agentuity projects, powered by BetterAuth.
Features
- ✅ Zero Configuration: Works out of the box with just a database connection
- ✅ Native Integration:
ctx.auth available on AgentContext and Hono routes
- ✅ Organizations: Multi-tenancy with roles and permissions
- ✅ API Keys: Programmatic access with fine-grained permissions
- ✅ JWT Tokens: Stateless auth for API calls
- ✅ Drizzle Schema: Type-safe database schema with migrations
- ✅ React Hooks:
useAuth() for client-side auth state
Installation
bun add @agentuity/auth
Quick Start
1. Setup with CLI
agentuity project auth init
This will:
- Install required dependencies
- Generate
src/auth.ts with default configuration
- Set up environment variables
2. Configure Database
agentuity cloud database create --region use
agentuity project auth setup
3. Server Setup (Hono)
import { createAuth, createSessionMiddleware, mountAuthRoutes } from '@agentuity/auth';
export const auth = createAuth({
connectionString: process.env.DATABASE_URL,
});
export const authMiddleware = createSessionMiddleware(auth);
export const optionalAuthMiddleware = createSessionMiddleware(auth, { optional: true });
import { createRouter } from '@agentuity/runtime';
import { auth, authMiddleware } from '../auth';
import { mountAuthRoutes } from '@agentuity/auth';
const api = createRouter();
api.on(['GET', 'POST'], '/api/auth/*', mountAuthRoutes(auth));
api.use('/api/*', authMiddleware);
api.get('/api/me', async (c) => {
const user = await c.var.auth.getUser();
return c.json({ id: user.id, email: user.email });
});
export default api;
4. Client Setup (React)
import { createAuthClient } from '@agentuity/auth/react';
export const authClient = createAuthClient();
export const { signIn, signUp, signOut, useSession } = authClient;
import { AgentuityProvider } from '@agentuity/react';
import { createAuthClient, AuthProvider } from '@agentuity/auth/react';
import { App } from './App';
const authClient = createAuthClient();
<AgentuityProvider>
<AuthProvider authClient={authClient}>
<App />
</AuthProvider>
</AgentuityProvider>;
5. Environment Variables
# Database connection
DATABASE_URL=postgresql://user:pass@host:5432/dbname
# Auth secret (generate with: openssl rand -hex 32)
AGENTUITY_AUTH_SECRET=your-secret-here
Usage
Agent Access
Auth is native on AgentContext - no wrappers needed:
import { createAgent } from '@agentuity/runtime';
export default createAgent('my-agent', {
handler: async (ctx, input) => {
if (!ctx.auth) {
return { error: 'Please sign in' };
}
const user = await ctx.auth.getUser();
const org = await ctx.auth.getOrg();
if (org && (await ctx.auth.hasOrgRole('admin'))) {
}
return { userId: user.id, orgId: org?.id };
},
});
Hono Routes
import { createSessionMiddleware, createApiKeyMiddleware } from '@agentuity/auth';
api.get('/api/profile', authMiddleware, async (c) => {
const user = await c.var.auth.getUser();
return c.json({ email: user.email });
});
api.use('/api/v1/*', createApiKeyMiddleware(auth));
api.get('/api/v1/data', async (c) => {
if (!c.var.auth.hasPermission('data', 'read')) {
return c.json({ error: 'Forbidden' }, 403);
}
return c.json({ data: '...' });
});
React Components
import { useAuth } from '@agentuity/react';
import { useAuth } from '@agentuity/auth/react';
function Profile() {
const { isAuthenticated, authLoading } = useAuth();
const { user, isPending } = useAuth();
if (authLoading || isPending) return <div>Loading...</div>;
if (!isAuthenticated) return <div>Please sign in</div>;
return <div>Welcome, {user?.name}!</div>;
}
Database Configuration
Option A: Connection String (Simplest)
import { createAuth } from '@agentuity/auth';
export const auth = createAuth({
connectionString: process.env.DATABASE_URL,
});
Option B: Bring Your Own Drizzle
Merge auth schema with your app schema:
import { drizzle } from 'drizzle-orm/bun-sql';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import * as authSchema from '@agentuity/auth/schema';
import * as myAppSchema from './schema';
const schema = { ...authSchema, ...myAppSchema };
const db = drizzle(process.env.DATABASE_URL!, { schema });
export const auth = createAuth({
database: drizzleAdapter(db, { provider: 'pg', schema: authSchema }),
});
Option C: Other Adapters
Use any BetterAuth-compatible adapter:
import { prismaAdapter } from 'better-auth/adapters/prisma';
export const auth = createAuth({
database: prismaAdapter(new PrismaClient()),
});
API Reference
Server
createAuth(options)
Creates an auth instance with Agentuity defaults.
Options:
connectionString?: string - PostgreSQL connection URL (simplest path)
database?: Adapter - BetterAuth database adapter (for advanced use)
secret?: string - Auth secret (defaults to AGENTUITY_AUTH_SECRET env var)
basePath?: string - API path prefix (default: /api/auth)
emailAndPassword?: { enabled: boolean } - Email auth (default: { enabled: true })
skipDefaultPlugins?: boolean - Skip organization, JWT, bearer, API key plugins
apiKey?: ApiKeyPluginOptions | false - API key configuration
plugins?: Plugin[] - Additional BetterAuth plugins
createSessionMiddleware(auth, options?)
Hono middleware for session-based auth.
Options:
optional?: boolean - If true, don't 401 on missing auth
otelSpans?: { email?: boolean, orgName?: boolean } - Control PII in spans
createApiKeyMiddleware(auth, options?)
Hono middleware for API key auth.
Options:
optional?: boolean - If true, don't 401 on missing API key
otelSpans?: { email?: boolean } - Control PII in spans
mountAuthRoutes(auth, options?)
Handler for BetterAuth routes with cookie merging.
Options:
allowList?: string[] - Headers to forward from auth responses
Client
createAuthClient(options?)
Import from @agentuity/auth/react.
Options:
baseURL?: string - API base URL (default: window.location.origin)
basePath?: string - Auth path prefix (default: /api/auth)
skipDefaultPlugins?: boolean - Skip organization and API key plugins
plugins?: Plugin[] - Additional client plugins
Returns: BetterAuth client with signIn, signUp, signOut, useSession, etc.
AuthProvider
React provider that bridges auth state to Agentuity context.
import { AuthProvider } from '@agentuity/auth/react';
<AuthProvider authClient={authClient} refreshInterval={3600000}>
{children}
</AuthProvider>;
Props:
authClient - Auth client instance (required)
refreshInterval - Token refresh interval in milliseconds (default: 3600000 / 1 hour)
tokenEndpoint - Token endpoint path or false to disable (default: '/token')
<AuthProvider authClient={authClient} refreshInterval={30000}>
<AuthProvider authClient={authClient} refreshInterval={300000}>
// Default: refresh every hour
<AuthProvider authClient={authClient}>
See the refreshInterval JSDoc for detailed security recommendations.
useAuth()
Hook for full auth context. Import from @agentuity/auth/react.
Returns:
user: AuthUser | null
isPending: boolean
error: Error | null
isAuthenticated: boolean
authClient: AuthClient
Schema
Import from @agentuity/auth/schema:
import { user, session, organization, apikey, authSchema } from '@agentuity/auth/schema';
Tables:
user - User accounts
session - Active sessions
account - OAuth/credential accounts
verification - Email verification tokens
organization - Organizations
member - Organization memberships
invitation - Pending invitations
jwks - JWT signing keys
apikey - API keys
Combined:
authSchema - All tables and relations for easy spreading
Types
import type {
AuthUser,
AuthSession,
AuthContext,
AuthOrgContext,
AuthApiKeyContext,
AuthMethod,
AuthInterface,
} from '@agentuity/auth';
CLI Commands
agentuity project auth init
agentuity project auth setup
agentuity project auth generate
agentuity project auth secret
Security Best Practices
- Use HTTPS in production - Always use TLS for deployments
- Keep secrets secret - Never commit
.env files or expose AGENTUITY_AUTH_SECRET
- Rotate secrets periodically - Rotate
AGENTUITY_AUTH_SECRET on a regular schedule
- Control OTEL PII - Use
otelSpans: { email: false } to exclude sensitive data from telemetry
- Validate permissions - Always check
hasPermission() for API key routes
Templates
Get started quickly:
bunx agentuity create my-app --template agentuity-auth
Third-Party Providers
Agentuity Auth is the recommended solution. For Clerk, Auth0, or other providers, see:
License
MIT