3.1 KiB
3.1 KiB
title, impact, impactDescription, tags
| title | impact | impactDescription | tags |
|---|---|---|---|
| Use @request Context in API Rules | CRITICAL | Enables dynamic, user-aware access control | api-rules, security, request-context, authentication |
Use @request Context in API Rules
The @request object provides access to the current request context including authenticated user, request body, query parameters, and headers. Use it to build dynamic access rules.
Incorrect (hardcoded or missing auth checks):
// No authentication check
const collection = {
listRule: '', // Anyone can see everything
createRule: '' // Anyone can create
};
// Hardcoded user ID (never do this)
const collection = {
listRule: 'owner = "specific_user_id"' // Only one user can access
};
Correct (using @request context):
// Check if user is authenticated
createRule: '@request.auth.id != ""'
// Check ownership via auth record
listRule: 'owner = @request.auth.id'
viewRule: 'owner = @request.auth.id'
updateRule: 'owner = @request.auth.id'
deleteRule: 'owner = @request.auth.id'
// Access auth record fields
// IMPORTANT: If using custom role fields, ensure update rules prevent
// users from modifying their own role: @request.body.role:isset = false
listRule: '@request.auth.role = "admin"'
listRule: '@request.auth.verified = true'
// Validate request body on create/update
createRule: '@request.auth.id != "" && @request.body.owner = @request.auth.id'
// Prevent changing certain fields
updateRule: 'owner = @request.auth.id && @request.body.owner:isset = false'
// WARNING: Query parameters are user-controlled and should NOT be used
// for authorization decisions. Use them only for optional filtering behavior
// where the fallback is equally safe.
// listRule: '@request.query.publicOnly = "true" || owner = @request.auth.id'
// The above is UNSAFE - users can bypass ownership by adding ?publicOnly=true
// Instead, use separate endpoints or server-side logic for public vs. private views.
listRule: 'owner = @request.auth.id || public = true' // Use a record field, not query param
// Access nested auth relations
listRule: 'team.members ?= @request.auth.id'
Available @request fields:
| Field | Description |
|---|---|
@request.auth.id |
Authenticated user's ID (empty string if not authenticated) |
@request.auth.* |
Any field from auth record (role, verified, email, etc.) |
@request.body.* |
Request body fields (create/update only) |
@request.query.* |
URL query parameters |
@request.headers.* |
Request headers |
@request.method |
HTTP method (GET, POST, etc.) |
@request.context |
Request context: default, oauth2, otp, password, realtime, protectedFile |
Body field modifiers:
// Check if field is being set
updateRule: '@request.body.status:isset = false' // Can't change status
// Check if field changed from current value
updateRule: '@request.body.owner:changed = false' // Can't change owner
// Get length of array/string
createRule: '@request.body.tags:length <= 5' // Max 5 tags
Reference: PocketBase API Rules