Agent Skill
2/7/2026

auth-protection

Add authentication and authorization to Convex functions and routes. Use this skill when protecting resources with user auth or role-based access control (RBAC).

J
joealmond
0GitHub Stars
1Views
npx skills add joealmond/convex-tanstack-better-auth-cloudfare-terraform

SKILL.md

Nameauth-protection
DescriptionAdd authentication and authorization to Convex functions and routes. Use this skill when protecting resources with user auth or role-based access control (RBAC).

name: auth-protection description: Add authentication and authorization to Convex functions and routes. Use this skill when protecting resources with user auth or role-based access control (RBAC).

Add Authentication Protection

Implement authentication and authorization patterns for this stack.

Goal

Secure resources with:

  • User authentication (logged in)
  • Ownership verification (user's own data)
  • Role-based access control (admin, user, etc.)

Instructions

1. Convex Function Authentication

Add to any protected query/mutation:

import { getAuthUserId } from "@convex-dev/auth/server";

export const myFunction = query({
  handler: async (ctx) => {
    const userId = await getAuthUserId(ctx);
    if (!userId) throw new Error("Unauthorized");
    
    // Now userId is available for scoping
  },
});

2. Ownership Verification

Ensure users can only access their own resources:

const item = await ctx.db.get(itemId);
if (!item) throw new Error("Not found");
if (item.userId !== userId) throw new Error("Forbidden");

3. Role-Based Access (RBAC)

For admin-only functions:

const user = await ctx.db
  .query("users")
  .filter((q) => q.eq(q.field("_id"), userId))
  .first();

if (user?.role !== "admin") {
  throw new Error("Forbidden: Admin access required");
}

4. Protected Routes (Frontend)

Place route files in _authed/ directory:

src/routes/
├── index.tsx          # Public
├── about.tsx          # Public
└── _authed/           # All routes here require auth
    ├── dashboard.tsx
    └── settings.tsx

The _authed layout checks session and redirects to login.

5. Client-Side Auth Check

import { useSession } from "@/lib/auth-client";

function ProfileButton() {
  const { data: session, isPending } = useSession();
  
  if (isPending) return <Skeleton />;
  if (!session) return <LoginButton />;
  
  return <UserMenu user={session.user} />;
}

Authorization Patterns

PatternUse CaseImplementation
AuthenticatedAny logged-in usergetAuthUserId(ctx)
OwnerUser's own dataCompare userId fields
Role-basedAdmin actionsCheck user.role
Resource-basedItem permissionsCheck item.permissions array

Constraints

  • DO NOT skip auth checks on mutations
  • DO NOT trust client-side role checks alone
  • DO NOT expose user IDs in error messages
  • DO use generic error messages for security

Examples

See examples/ directory for:

  • protected-query.ts - Query with user scoping
  • rbac-check.ts - Role-based admin access
Skills Info
Original Name:auth-protectionAuthor:joealmond