# Cursor Plugin Convex Rule Authentication Checks

> Implement authentication checks in all public functions

- Skill: `kunanonj/cursor-plugin-convex-rule-authentication-checks` (Agent Skill)
- Install (CLI): `npx skillmds@latest add kunanonj/cursor-plugin-convex-rule-authentication-checks`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kunanonj/cursor-plugin-convex-rule-authentication-checks/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: KunanonJ (https://skillmd.com/u/kunanonj)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/kunanonj/cursor-plugin-convex-rule-authentication-checks

---


# Authentication & Authorization

Every public function that accesses user data MUST verify authentication using `ctx.auth.getUserIdentity()`.

## Pattern

```typescript
export const getMyTasks = query({
  args: {},
  handler: async (ctx) => {
    const identity = await ctx.auth.getUserIdentity();
    if (!identity) {
      throw new Error("Not authenticated");
    }

    const user = await getUserByIdentity(ctx, identity);
    return await ctx.db
      .query("tasks")
      .withIndex("by_user", q => q.eq("userId", user._id))
      .collect();
  },
});
```

## Access Control Best Practices

1. **Use unguessable IDs**: Always use Convex IDs or UUIDs for access checks, never spoofable data like email addresses
2. **Check ownership**: Verify the authenticated user owns or has permission to access the resource
3. **Never trust client**: Client can send any ID—always verify server-side

## Example: Secure Update

```typescript
export const updateTask = mutation({
  args: { taskId: v.id("tasks"), text: v.string() },
  handler: async (ctx, args) => {
    const identity = await ctx.auth.getUserIdentity();
    if (!identity) throw new Error("Not authenticated");

    const task = await ctx.db.get(args.taskId);
    if (!task) throw new Error("Task not found");

    const user = await getUserByIdentity(ctx, identity);
    if (task.userId !== user._id) {
      throw new Error("Unauthorized");
    }

    await ctx.db.patch(args.taskId, { text: args.text });
  },
});
```

