Auth & Permissions

Sessions

Reading the current session and scoping queries and inserts to the logged-in user.

After setting up authentication, you can read the current session to scope queries and inserts to the logged-in user.

Get the session and user ID

const session = useSession();
const sessionUserId = session?.user_id ?? null;
const session = useSession();
const sessionUserId = session?.user_id ?? null;
const session = getSession();
const sessionUserId = $derived(session?.user_id ?? null);
const session = db.getAuthState().session;
const sessionUserId = session?.user_id ?? null;

Read rows for the current user

Use the session's user ID with .where() to scope queries to the current user.

const ownedTodos =
  useAll(sessionUserId ? app.todos.where({ owner_id: sessionUserId }) : undefined) ?? [];
const ownedTodos = useAll(sessionUserId ? app.todos.where({ owner_id: sessionUserId }) : undefined);
const ownedTodos = new QuerySubscription(
  sessionUserId ? app.todos.where({ owner_id: sessionUserId }) : undefined,
);
const ownedTodos = sessionUserId
  ? await db.all(app.todos.where({ owner_id: sessionUserId }))
  : [];

Insert a user-owned row

Insert a row with the session's user ID to associate it with the current user.

function addOwnedTodo(title: string) {
  if (!sessionUserId) return;

  db.insert(app.todos, {
    title,
    done: false,
    owner_id: sessionUserId,
  });
}
function addOwnedTodo(title: string) {
  if (!sessionUserId) return;

  db.insert(app.todos, {
    title,
    done: false,
    owner_id: sessionUserId,
  });
}
function addOwnedTodo(title: string) {
  if (!sessionUserId) return;

  db.insert(app.todos, {
    title,
    done: false,
    owner_id: sessionUserId,
  });
}
function addOwnedTodo(title: string) {
  if (!sessionUserId) return;

  db.insert(app.todos, {
    title,
    done: false,
    owner_id: sessionUserId,
  });
}

Use whatever column fits your schema — owner_id, author_id, assignee_id, etc. — the column names have no special significance.

Session identity and authorship

Jazz also records authorship and edit times through the edit metadata magic columns $createdBy, $createdAt, $updatedBy, and $updatedAt.

See Queries for how to select and filter on these columns.

On clients, writes are automatically attributed to the current session user. On backends, await context.forRequest(...) and context.forSession(...) both run as that user for permissions and also stamp authorship as that user.

Attribution without impersonation

Sometimes backend code should keep backend-level permissions but still record a user's identity in edit metadata. Use the attribution helpers for this:

  • context.withAttribution(userId) — stamps writes as the given user ID
  • context.withAttributionForSession(session) — derives authorship from a resolved session
  • await context.withAttributionForRequest(req) — derives authorship from an authenticated request
export async function createAttributedHandles(req: Request) {
  const syntheticSession = {
    user_id: "user_123",
    authMode: "external" as const,
    claims: {},
  };

  return {
    backendDb: context.asBackend(schemaApp),
    attributedDb: context.withAttribution("user_123", schemaApp),
    attributedSessionDb: context.withAttributionForSession(syntheticSession, schemaApp),
    attributedRequestDb: await context.withAttributionForRequest(req, schemaApp),
  };
}

These differ from forRequest / forSession in one key way:

  • await context.forRequest(...) / context.forSession(...) change both permission evaluation and authorship
  • withAttribution* only changes authorship — permissions stay at the backend level
  • asBackend() and unscoped db() writes default to jazz:system

Client-side filters are useful for UX, but they don't enforce access control on their own. Use Permissions to define row-level policies that control which sessions can read or mutate a row.

Next steps

  • Permissions — define row-level access policies using session identity
  • Queries — subscribe to data and filter by user
  • Writing Data — insert, update, and delete rows

On this page