| title |
aliases |
tags |
sources |
created |
updated |
| Payload CMS — Access Control Overview |
| payload-access-control |
| payload-cms-permissions |
|
| payload-cms |
| access-control |
| rbac |
| permissions |
| cms |
|
| raw/access-control__overview.md |
|
2026-05-15 |
2026-05-15 |
Payload CMS — Access Control Overview
Access Control in Payload determines what a user can do with any Document and what they see in the Admin Panel. Functions are scoped per operation and run before any changes are made.
Three Types
Default Access Control
Payload ships with a default that requires an authenticated user:
const defaultPayloadAccess = ({ req: { user } }) => Boolean(user)
- Local API skips access control by default — set
overrideAccess: false to opt back in.
Access Operation & Admin Panel Sync
- On login, Payload runs every access function at the top level (all Collections, Globals, Fields) to determine what the user can do.
- Admin Panel hides/shows UI elements dynamically based on this result.
- When called via the Access Operation,
id, data, siblingData, blockData, and doc are all undefined — always guard against this before using them.
const access = ({ req: { user }, id }) => {
if (!id) return Boolean(user) // Access Operation context
return user?.role === 'admin'
}
Locale-Specific Access Control
Use req.locale to restrict access per locale:
const access = ({ req }) => req.locale === 'en'
Common Patterns
- Public read: return
true from read
- Published only: return
{ status: { equals: 'published' } } (Query constraint)
- Owner only: return
{ createdBy: { equals: req.user.id } }
- Admin role:
return req.user?.role === 'admin'
- Org-scoped:
return { organization: { equals: req.user.orgId } }
Key Takeaways
- Access functions execute before operations — they are guards, not post-filters
- Return
true/false for full allow/deny; return a Where query for row-level security (Collections/Globals only — Fields are boolean-only)
- Local API bypasses access control unless
overrideAccess: false is set
- Admin Panel UI reflects access control automatically via the Access Operation
- Guard
id/data/doc for undefined inside access functions — they are absent when called by the Access Operation
- Locale-aware access is possible via
req.locale
Sources