Skip to content

Guards

Guards protect procedures by checking authorization before the handler runs. If a guard fails, the request is rejected.

Requires a logged-in user:

import { authenticated } from '@veloxts/auth';
getProfile: procedure()
.guard(authenticated)
.query(({ ctx }) => ctx.user),

Requires a specific role:

import { hasRole } from '@veloxts/auth';
deleteUser: procedure()
.guard(authenticated)
.guard(hasRole('admin'))
.mutation(handler),

Requires a specific permission:

import { hasPermission } from '@veloxts/auth';
updateSettings: procedure()
.guard(authenticated)
.guard(hasPermission('settings:write'))
.mutation(handler),

Create guards with defineGuard:

import { defineGuard } from '@veloxts/auth';
const isVerified = defineGuard({
name: 'isVerified',
check: (ctx) => ctx.user?.emailVerified === true,
message: 'Email verification required',
statusCode: 403,
});
// Usage
updateEmail: procedure()
.guard(authenticated)
.guard(isVerified)
.mutation(handler),
import { allOf } from '@veloxts/auth';
const adminAndVerified = allOf(hasRole('admin'), isVerified);
sensitiveOperation: procedure()
.guard(authenticated)
.guard(adminAndVerified)
.mutation(handler),
import { anyOf } from '@veloxts/auth';
const adminOrModerator = anyOf(hasRole('admin'), hasRole('moderator'));
moderateContent: procedure()
.guard(authenticated)
.guard(adminOrModerator)
.mutation(handler),
import { not } from '@veloxts/auth';
const notBanned = not(defineGuard({
name: 'isBanned',
check: (ctx) => ctx.user?.banned === true,
message: 'Account is banned',
}));

Guards run in order. If any fails, subsequent guards don’t run:

getSecretData: procedure()
.guard(authenticated) // 1. Must be logged in
.guard(isVerified) // 2. Must have verified email
.guard(hasRole('admin')) // 3. Must be admin
.guard(notBanned) // 4. Must not be banned
.query(handler),

When a guard fails:

{
"error": {
"message": "Email verification required",
"code": "FORBIDDEN"
}
}

HTTP status code is set based on guard configuration (default: 403).

For per-resource authorization, use policies instead:

// Guard: "Is user an admin?" (role-based)
.guard(hasRole('admin'))
// Policy: "Can user edit THIS post?" (resource-based)
.guard(authorize('posts', 'edit'))

See Policies for resource-based authorization.

  • Policies - Resource-based authorization
  • JWT - Token authentication
  • Sessions - Cookie-based auth