Skip to main content
Authorization belongs in your backend

AuthContext is SDK request metadata, not a verified Convex identity or an authorization policy. Tenant propagation varies by operation. Validate the authenticated identity and tenant on your trusted server, authorize every read and mutation there, and keep administrative APIs behind that boundary. Do not expose a privileged Convex deployment directly to untrusted clients or rely on IDs and client-side filters as access controls.

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

Supported operations use auth context as default request metadata:

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

Auth Context Fields​

ParameterTypeRequiredDefaultDescription
userIdstringYes—Identifies the authenticated user. Default user metadata for supported operations.
tenantIdstringNo—Multi-tenant SaaS isolation. Tenant metadata for supported operations; enforce authorization on the server.
sessionIdstringNo—Track user sessions across devices.
claimsobjectNo—Raw data from auth provider (email, iss, aud, etc.)
metadataobjectNo—Your 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​