
Security News
Feross on TBPN: Socket's Series C and the State of Software Supply Chain Security
Feross Aboukhadijeh joins TBPN to discuss Socket's $60M Series C, 500%+ ARR growth, AI's impact on open source, and the rise in supply chain attacks.
@agentuity/auth
Advanced tools
First-class authentication for Agentuity projects, powered by BetterAuth.
ctx.auth available on AgentContext and Hono routesuseAuth() for client-side auth statebun add @agentuity/auth
bun add @agentuity/auth better-auth drizzle-orm
bun add -D drizzle-kit
agentuity cloud db create --name my-app-auth --region usc
agentuity cloud db get my-app-auth --json
Use the database URL in .env, then generate an auth secret:
openssl rand -hex 32
// src/auth.ts
import { createAuth, createSessionMiddleware, mountAuthRoutes } from '@agentuity/auth';
export const auth = createAuth({
connectionString: process.env.DATABASE_URL,
trustedOrigins: [
process.env.BETTER_AUTH_URL,
'http://localhost:3500',
'http://127.0.0.1:3500',
],
// Uses AGENTUITY_AUTH_SECRET env var by default
});
export const authMiddleware = createSessionMiddleware(auth);
export const optionalAuthMiddleware = createSessionMiddleware(auth, { optional: true });
// src/api/index.ts
import { createRouter } from '@agentuity/runtime';
import { auth, authMiddleware } from '../auth';
import { mountAuthRoutes } from '@agentuity/auth';
const api = createRouter();
// Mount auth routes (sign-in, sign-up, sign-out, session, etc.)
api.on(['GET', 'POST'], '/auth/*', mountAuthRoutes(auth));
// Protect API routes
api.use('/*', authMiddleware);
api.get('/me', async (c) => {
const user = await c.var.auth.getUser();
return c.json({ id: user.id, email: user.email });
});
export default api;
// src/web/auth-client.ts
import { createAuthClient } from '@agentuity/auth/react';
export const authClient = createAuthClient();
export const { signIn, signUp, signOut, useSession } = authClient;
// src/web/frontend.tsx
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>;
# Database connection
DATABASE_URL=postgresql://user:pass@host:5432/dbname
# Auth secret (generate with: openssl rand -hex 32)
AGENTUITY_AUTH_SECRET=your-secret-here
For local browser auth, put the callback URL in .env.local:
BETTER_AUTH_URL=http://127.0.0.1:3500
// src/schema.ts
export * from '@agentuity/auth/schema';
// drizzle.config.ts
import { defineConfig } from 'drizzle-kit';
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) throw new Error('DATABASE_URL is required');
export default defineConfig({
dialect: 'postgresql',
schema: './src/schema.ts',
dbCredentials: { url: databaseUrl },
});
bunx drizzle-kit push
Auth is native on AgentContext - no wrappers needed:
import { createAgent } from '@agentuity/runtime';
export default createAgent('my-agent', {
handler: async (ctx, input) => {
// ctx.auth is available when using auth middleware
if (!ctx.auth) {
return { error: 'Please sign in' };
}
const user = await ctx.auth.getUser();
const org = await ctx.auth.getOrg();
// Check organization roles
if (org && (await ctx.auth.hasOrgRole('admin'))) {
// Admin-only logic
}
return { userId: user.id, orgId: org?.id };
},
});
import { createSessionMiddleware, createApiKeyMiddleware } from '@agentuity/auth';
// Session-based auth
api.get('/api/profile', authMiddleware, async (c) => {
const user = await c.var.auth.getUser();
return c.json({ email: user.email });
});
// API key auth
api.use('/api/v1/*', createApiKeyMiddleware(auth));
api.get('/api/v1/data', async (c) => {
// Check API key permissions
if (!c.var.auth.hasPermission('data', 'read')) {
return c.json({ error: 'Forbidden' }, 403);
}
return c.json({ data: '...' });
});
import { useAuth } from '@agentuity/react';
import { useAuth } from '@agentuity/auth/react';
function Profile() {
// Basic auth state from @agentuity/react
const { isAuthenticated, authLoading } = useAuth();
// Full auth context from @agentuity/auth
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>;
}
import { createAuth } from '@agentuity/auth';
export const auth = createAuth({
connectionString: process.env.DATABASE_URL,
});
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 }),
});
Use any BetterAuth-compatible adapter:
import { prismaAdapter } from 'better-auth/adapters/prisma';
export const auth = createAuth({
database: prismaAdapter(new PrismaClient()),
});
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 pluginsapiKey?: ApiKeyPluginOptions | false - API key configurationplugins?: Plugin[] - Additional BetterAuth pluginscreateSessionMiddleware(auth, options?)Hono middleware for session-based auth.
Options:
optional?: boolean - If true, don't 401 on missing authotelSpans?: { email?: boolean, orgName?: boolean } - Control PII in spanscreateApiKeyMiddleware(auth, options?)Hono middleware for API key auth.
Options:
optional?: boolean - If true, don't 401 on missing API keyotelSpans?: { email?: boolean } - Control PII in spansmountAuthRoutes(auth, options?)Handler for BetterAuth routes with cookie merging.
Options:
allowList?: string[] - Headers to forward from auth responsescreateAuthClient(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 pluginsplugins?: Plugin[] - Additional client pluginsReturns: BetterAuth client with signIn, signUp, signOut, useSession, etc.
AuthProviderReact 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')// High-security: refresh every 30 seconds
<AuthProvider authClient={authClient} refreshInterval={30000}>
// Sensitive features: refresh every 5 minutes
<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 | nullisPending: booleanerror: Error | nullisAuthenticated: booleanauthClient: AuthClientImport from @agentuity/auth/schema:
import { user, session, organization, apikey, authSchema } from '@agentuity/auth/schema';
Tables:
user - User accountssession - Active sessionsaccount - OAuth/credential accountsverification - Email verification tokensorganization - Organizationsmember - Organization membershipsinvitation - Pending invitationsjwks - JWT signing keysapikey - API keysCombined:
authSchema - All tables and relations for easy spreadingimport type {
AuthUser,
AuthSession,
AuthContext,
AuthOrgContext,
AuthApiKeyContext,
AuthMethod,
AuthInterface,
} from '@agentuity/auth';
@agentuity/auth exports the Drizzle schema used by the default plugins. Re-export it from your app and apply it with Drizzle Kit:
export * from '@agentuity/auth/schema';
import { defineConfig } from 'drizzle-kit';
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) throw new Error('DATABASE_URL is required');
export default defineConfig({
dialect: 'postgresql',
schema: './src/schema.ts',
dbCredentials: { url: databaseUrl },
});
bunx drizzle-kit push
.env files or expose AGENTUITY_AUTH_SECRETAGENTUITY_AUTH_SECRET on a regular scheduleotelSpans: { email: false } to exclude sensitive data from telemetryhasPermission() for API key routesAgentuity Auth is the recommended solution. For Clerk, Auth0, or other providers, see:
MIT
FAQs
Authentication for Agentuity projects using Agentuity Auth
The npm package @agentuity/auth receives a total of 1,089 weekly downloads. As such, @agentuity/auth popularity was classified as popular.
We found that @agentuity/auth demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Feross Aboukhadijeh joins TBPN to discuss Socket's $60M Series C, 500%+ ARR growth, AI's impact on open source, and the rise in supply chain attacks.

Security News
OSV withdrew 157 OSV malware reports after automated false positives incorrectly flagged trusted npm and PyPI packages, sending bad records into tools that rely on OSV data.

Research
/Security News
TrapDoor crypto stealer hits 36 malicious packages across npm, PyPI, and Crates.io, targeting crypto, DeFi, AI, and security developers.