Naming the role field
Store roles under a property other than role, such as a roles array, and have every role check in the plugin read it.
Role checks read user.role by default. To store roles under another property, such as a roles array, set roleField once on betterAuthCollections().
// Better Auth
user: { additionalFields: { roles: { type: 'string[]', input: false } } }
// Users collection
{ name: 'roles', type: 'json' }
// Payload config
betterAuthCollections({ betterAuthOptions, roleField: 'roles' })The plugin publishes the value on config.custom.betterAuth.roleField, and every role check reads it there:
- the first-user-admin guard
- the saveToJWT field list
- the access helpers (
isAdmin,isAdminField,isAdminOrSelf,canUpdateOwnFields,hasRole,hasRoleField,requireAllRoles) - the admin login role gate
- the API-key management gate
getRoleField(config) and DEFAULT_ROLE_FIELD ('role') are exported for your own checks.
Details
firstUserAdmin.roleFieldis the older spelling of the same setting and still works. Setting both to different values throws at startup.hasAnyRole(user, roles, 'roles')andhasAllRolestake the field as a third argument; they have no config to read, and default torolewhen it is omitted. The other access helpers read it from the request's Payload config and accept aroleFieldoption to override it.- Types:
WithRoleField<User, 'roles', string[]>moves the generatedroleproperty to the configured name. firstUserAdminHooks()runs inside Better Auth, outside the Payload config, so pass itroleFielddirectly if you use it.roleFieldis published bybetterAuthCollections(). Setups that skip it have no configured value and every gate falls back torole. To use another name there, setcustom: { betterAuth: { roleField: 'roles' } }on your Payload config yourself, or passroleFieldto each helper and theroleFieldprop to a standaloneLoginView.
Only the column name differs?
Better Auth's fieldName mapping (role: { type: 'string', fieldName: 'roles' }) renames where the value is stored, and the adapter handles it. In this plugin the stored name is also the Payload field name, so Payload-side checks see user.roles while Better Auth's session user keeps role. Set roleField to the stored name ('roles'); the admin login gate translates it to the session key on its own.
Use fieldName for a column rename under Better Auth's key. Use roleField when the property itself has another name.
Added in 0.13.2.
Customization
Gate the admin by role, turn off auto-injected endpoints and components, swap in your own admin components, or mount the auth route yourself.
Access control
Prebuilt Payload access functions for role checks, self-access and authenticated-only reads, plus the role utilities they are built on.

