Auth Integration (2 Minutes)
Quick guide: Integrate Cortex with your existing authentication system.
The Simple Truth
Cortex works with whatever auth system you already use. No special integration, no proprietary protocol, no heavy lifting.
Your auth system → Extract userId → Pass to Cortex → Done.
3-Line Integration
1import { Cortex, createAuthContext } from "@cortexmemory/sdk";2 3// 1. Extract from YOUR existing auth (any system)4const auth = createAuthContext({5userId: yourUser.id, // Required6tenantId: yourUser.tenantId, // Optional (for SaaS)7});8 9// 2. Pass to Cortex10const cortex = new Cortex({11convexUrl: process.env.CONVEX_URL!,12auth,13});14 15// 3. Use normally - userId auto-injected16await cortex.memory.remember({17memorySpaceId: "user-space",18userMessage: "Hello",19agentResponse: "Hi!",20userName: yourUser.name,21// userId automatically set from auth22});No SDKs to install, no webhooks to configure, no middleware to debug.
Supported Auth Providers
Cortex is framework-agnostic — it works with any auth system that provides a user ID.
Clerk, Auth0, NextAuth, Supabase Auth, Firebase Auth, Okta, WorkOS, Custom JWT — any system that provides a user ID.
Provider Setup
Install Clerk SDK
$ npm install @clerk/nextjsConfigure Cortex with Clerk
import { Cortex, createAuthContext } from '@cortexmemory/sdk';
import { auth } from '@clerk/nextjs';
export async function getCortexClient() {
const { userId, orgId } = auth();
if (!userId) {
throw new Error('Not authenticated');
}
return new Cortex({
convexUrl: process.env.CONVEX_URL!,
auth: createAuthContext({
userId,
tenantId: orgId, // For multi-tenant apps
authProvider: 'clerk',
authMethod: 'oauth',
authenticatedAt: Date.now(),
}),
});
}
Get user from Auth0
import { getSession } from '@auth0/nextjs-auth0';
const session = await getSession();
const userId = session?.user?.sub;
Configure Cortex
const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
auth: createAuthContext({
userId: session.user.sub,
tenantId: session.user.org_id,
authProvider: 'auth0',
authMethod: 'oauth',
}),
});
Get session
import { getServerSession } from 'next-auth';
const session = await getServerSession();
Configure Cortex
const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
auth: createAuthContext({
userId: session.user.id,
authProvider: 'nextauth',
authMethod: 'oauth',
}),
});
Get user from Supabase
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(url, key);
const { data: { user } } = await supabase.auth.getUser();
Configure Cortex
const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
auth: createAuthContext({
userId: user.id,
authProvider: 'supabase',
authMethod: 'session',
}),
});
import jwt from 'jsonwebtoken';
// Verify your JWT
const decoded = jwt.verify(token, process.env.JWT_SECRET!);
const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
auth: createAuthContext({
userId: decoded.sub,
tenantId: decoded.org_id,
authProvider: 'custom',
authMethod: 'jwt',
sessionId: decoded.sid,
}),
});
The pattern is always the same — just map your auth data to Cortex's simple structure.
AuthContext Reference
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
userId | string | Yes | — | Unique user identifier from your auth system |
tenantId | string | No | — | Organization/tenant ID for multi-tenant apps |
sessionId | string | No | — | Current session identifier |
authMethod | string | No | — | Name of auth provider (for analytics) |
authenticatedAt | number | No | — | Timestamp of authentication (Unix ms) |
Multi-Tenancy Support
For multi-tenant SaaS apps, always include tenantId in your auth context. This ensures complete data isolation between customers.
const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
auth: createAuthContext({
userId: 'user-123',
tenantId: 'customer-acme', // Critical for SaaS!
authProvider: 'clerk',
authMethod: 'oauth',
}),
});
// All operations are now scoped to customer-acme
await cortex.memory.remember({...}); // tenantId auto-injected
See Isolation Boundaries for the complete multi-tenancy guide.
What Happens Behind the Scenes
Auto-Injection
userId and tenantId are automatically added to all operations:
// You write:
await cortex.memory.remember({ memorySpaceId: "space-1", ... });
// SDK automatically does:
await cortex.memory.remember({
memorySpaceId: "space-1",
userId: "user-123", // ← From auth
tenantId: "tenant-abc", // ← From auth
...
});
Auto-Filtering
All queries are automatically filtered by tenantId:
// You write:
const memories = await cortex.memory.search("space-1", "query");
// SDK automatically filters:
// WHERE memorySpaceId = "space-1" AND tenantId = "tenant-abc"
Enables Features
Auth context enables: GDPR cascade deletion by userId, multi-tenant data isolation, session tracking, and audit trails.
Security Best Practices
Always create the Cortex client on the server side. Never expose your Convex URL or auth context to the client.
Always get the user ID from your auth system's server-side session, never from client-submitted data.
Common Patterns
// app/api/cortex/route.ts
import { Cortex, createAuthContext } from '@cortexmemory/sdk';
import { auth } from '@clerk/nextjs';
export async function POST(req: Request) {
const { userId, orgId } = auth();
const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
auth: createAuthContext({ userId, tenantId: orgId }),
});
// Use cortex...
}
// pages/api/cortex.ts
import { Cortex, createAuthContext } from '@cortexmemory/sdk';
import { getAuth } from '@clerk/nextjs/server';
export default async function handler(req, res) {
const { userId, orgId } = getAuth(req);
const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
auth: createAuthContext({ userId, tenantId: orgId }),
});
// Use cortex...
}
// middleware/cortex.ts
import { Cortex, createAuthContext } from '@cortexmemory/sdk';
export function cortexMiddleware(req, res, next) {
req.cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
auth: createAuthContext({
userId: req.user.id,
tenantId: req.user.organizationId,
}),
});
next();
}
// Use in routes
app.post("/chat", async (req, res) => {
await req.cortex.memory.remember({...});
});
// Extract auth data (your code)
const userId = extractUserId(req);
const tenantId = extractTenantId(req);
// Create auth context
const auth = createAuthContext({ userId, tenantId });
// Use with Cortex
const cortex = new Cortex({ convexUrl, auth });
Without Auth (For Testing)
Cortex works without auth context for development and testing:
// No auth - for prototypes/testing
const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
// No auth
});
// Works, but you must set userId manually
await cortex.memory.remember({
memorySpaceId: "test-space",
userId: "test-user", // Manual
userMessage: "Hello",
agentResponse: "Hi!",
userName: "Test User",
});
Quick prototypes, development/testing, single-user apps, CLI tools.
Production APIs, multi-tenant SaaS, user-facing applications.
Common Questions
No! Cortex doesn't require any auth provider SDKs. Use whatever you already have.
Just update your extraction code. Cortex doesn't care where userId comes from.
No! Auth context is request-scoped. No async integrations needed.
Store in metadata field. Cortex provides data isolation, you handle authorization logic.
Yes! Use test values: createAuthContext({ userId: "test-user" })