obsidian/wiki/payloadcms/local-api-access-control.md
2026-05-15 16:14:29 +01:00

2.7 KiB

title aliases tags sources created updated
Local API — Access Control
local-api-access-control
payload-overrideAccess
payloadcms
local-api
access-control
security
server-side
raw/local-api__access-control.md
2026-05-15 2026-05-15

Overview

Local API operations skip access control by default. This is by design — server-side scripts and admin tasks often run without a user context. You must explicitly opt in to access control enforcement when it matters.

Default Behaviour: Access Control Skipped

// Access control is NOT checked — runs as a privileged operation
const doc = await payload.create({
  collection: 'users',
  data: { email: 'test@test.com', password: 'test' },
})

Useful for:

  • Seed scripts and migrations
  • Admin-only server jobs (cron tasks, background workers)
  • Internal service-to-service operations

Enforcing Access Control

Pass overrideAccess: false and the authenticated user object to make the operation respect collection-level access rules.

const doc = await payload.create({
  collection: 'users',
  overrideAccess: false, // enforce collection access control
  user,                  // authenticated user to check against
  data: { email: 'test@test.com', password: 'test' },
})
  • If user lacks permission → Payload throws a Forbidden error
  • Works on all CRUD operations: create, find, findByID, update, delete

When to Use Each Mode

Scenario overrideAccess Pass user?
Server scripts, cron jobs, seeds true (default) No
Server actions executing on behalf of a logged-in user false Yes — req.user
Webhooks / third-party integrations with trusted tokens true (default) No
Custom API endpoints that mirror REST behaviour false Yes

Key Takeaways

  • Local API bypasses access control by default — safe for trusted server code, dangerous if exposed to untrusted input.
  • To enforce permissions: set overrideAccess: false AND pass the user object.
  • Both conditions are required — overrideAccess: false without a user will treat the request as unauthenticated (all collection-access functions receive undefined as user).
  • In wiki/payloadcms/hooks-collections that run after user-triggered events, access control is already enforced by the REST/GraphQL layer; using the Local API inside hooks with overrideAccess: true lets you escalate privileges intentionally.
  • See wiki/payloadcms/access-control for collection/field-level access function signatures.

Sources