Skip to main content
The most common security bug in multi-user apps is IDOR — Insecure Direct Object Reference. User A passes a URL with user B’s resource ID; the server returns it without checking. Don’t let this happen.

The rule

Every query and mutation that returns or modifies data must verify the caller has access.

Patterns

Per-user

Per-workspace

Per-role

Common mistakes

“I only show the user their own tasks in the UI” — but the API endpoint returns everything. Anyone who sniffs the network can see all tasks.
/tasks/123 — server should verify the user has access to task 123, not just trust the URL.
Filtering by workspaceId is necessary but not sufficient. Verify the user is a member of that workspace too.

Tips

Write a “permission helper” once and reuse. A requireMembership(ctx, workspaceId) function called from every mutation prevents copy-paste drift.
Test by signing in as different users. Don’t trust that vly generated the right checks — verify by trying to access other users’ data.

Roles & permissions

Role model.

Multi-tenancy

Per-tenant patterns.

Auth integration

The ctx.auth API.
Last modified on April 18, 2026