Authorization
Learn how to protect routes based on user roles and permissions.
Authorization verifies that a user has the necessary permissions to access a resource.
Role-Based Access Control (RBAC)
Users have one of two roles:
| Role | Description |
|---|---|
Role.USER | Default role for all new users. |
Role.ADMIN | Full access to admin features. |
Protecting Server-Side Routes
Use the pre-configured procedure types in tRPC:
import { protectedProcedure, adminProcedure, router } from "../../trpc";
export const exampleRouter = router({
// Any authenticated user
getData: protectedProcedure.query(({ ctx }) => {
return service.getData(ctx.session.user.id);
}),
// Admin only
getAllUsers: adminProcedure.query(() => {
return service.getAllUsers();
}),
});Always derive the user ID from ctx.session.user.id — never trust client-supplied user IDs (IDOR prevention).
Protecting Client-Side Routes
You can check the user's role in client components:
"use client";
import { authClient } from "@package/auth/client";
import { Role } from "@package/utils";
export function AdminPanel() {
const { data: session } = authClient.useSession();
if (session?.user.role !== Role.ADMIN) {
return <p>Access denied.</p>;
}
return <div>Admin content here.</div>;
}Client-side protection is for UX only. Always enforce authorization on the server side through tRPC procedure types.