Skip to main content

Authentication

Understanding authentication context in Cortex for user tracking, multi-tenancy, and session management.

Overview

Key Concept

Auth context is just data — not a protocol or SDK. Extract it from your auth system (whatever that is) and pass it to Cortex.

Authentication Flow
Your Auth System

Auth0 • Clerk • JWT • NextAuth • Custom

Extract & Create Context

userId • tenantId • sessionId • metadata

Cortex SDK

Auto-injects auth to ALL operations

Your auth system → Cortex SDK → Auto-injected to all operations

Why Authentication Matters

User Tracking

Link all data to users for personalization and context

Multi-Tenancy

Complete data separation for SaaS platforms

GDPR Compliance

Enable cascade deletion across all layers

Session Management

Track user activity across devices


Quick Start

1

Extract Auth Information

From your auth system (JWT, session, OAuth token):

import jwt from "jsonwebtoken";

function extractAuth(token: string) {
const decoded = jwt.verify(token, process.env.JWT_SECRET!) as {
sub: string;
tenant_id?: string;
session_id?: string;
};

return {
userId: decoded.sub,
tenantId: decoded.tenant_id,
sessionId: decoded.session_id,
};
}
2

Create Auth Context

import { createAuthContext } from "@cortexmemory/sdk";

const auth = createAuthContext({
userId: extracted.userId,
tenantId: extracted.tenantId,
sessionId: extracted.sessionId,
});
3

Initialize Cortex

import { Cortex } from "@cortexmemory/sdk";

const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
auth,
});
4

Use Cortex

All operations automatically include auth context:

await cortex.memory.remember({
memorySpaceId: "user-space",
userMessage: "Hello",
agentResponse: "Hi!",
userName: "User",
// userId, tenantId auto-injected
});

Auth Context Fields

ParameterTypeRequiredDefaultDescription
userIdstringYesIdentifies the authenticated user. Auto-injected to all entities.
tenantIdstringNoMulti-tenant SaaS isolation. Auto-filters ALL queries by tenant.
sessionIdstringNoTrack user sessions across devices.
claimsobjectNoRaw data from auth provider (email, iss, aud, etc.)
metadataobjectNoYour application data (role, plan, features, etc.)

Example with All Fields

const auth = createAuthContext({
userId: "user-123", // Required
tenantId: "customer-acme", // Multi-tenant isolation
sessionId: "session-xyz", // Session tracking
claims: {
email: "user@example.com",
iss: "https://auth.myapp.com",
},
metadata: {
role: "admin",
plan: "enterprise",
},
});

Common Patterns

// Middleware extracts auth
app.use((req, res, next) => {
const token = req.headers.authorization?.replace("Bearer ", "");
if (!token) return res.status(401).send("Unauthorized");

try {
const decoded = jwt.verify(token, process.env.JWT_SECRET!);
req.auth = createAuthContext({
userId: decoded.sub,
tenantId: decoded.tenant_id,
sessionId: decoded.session_id,
});
next();
} catch (err) {
res.status(401).send("Invalid token");
}
});

// Route uses auth
app.post("/chat", (req, res) => {
const cortex = new Cortex({ convexUrl, auth: req.auth });
// Use cortex...
});

Security Best Practices

Always Extract tenantId from Secure Token
// GOOD: From signed JWT
const decoded = jwt.verify(token, secret);
const auth = createAuthContext({
userId: decoded.sub,
tenantId: decoded.tenant_id, // From secure source
});

// BAD: From client input — user could change this!
const auth = createAuthContext({
userId: decoded.sub,
tenantId: req.body.tenantId, // NEVER do this
});
Validate Auth Context
async function validateAuth(auth: AuthContext) {
const user = await cortex.users.get(auth.userId);
if (!user) throw new Error("User not found");
return true;
}
Rotate Sessions
// Expire old sessions periodically
await cortex.sessions.expireIdle({
idleTimeout: 30 * 60 * 1000, // 30 minutes
});

Next Steps