Skip to Content
Delmare Digital

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.

By default the plugin registers Better Auth's endpoints, injects its admin login and logout components, and lets only users with the admin role into the admin. Each of those can be changed.

Role-based admin access

The admin login checks for the admin role by default. Change it with admin.login.requiredRole:

src/payload.config.ts
createBetterAuthPlugin({
  createAuth,
  admin: {
    login: {
      requiredRole: 'admin',                          // Single role
      // requiredRole: ['admin', 'editor', 'moderator'], // Any of these
      // requiredRole: null,                             // Disable checking
    },
  },
})

With an array, any matching role grants access. Set admin.login.requireAllRoles: true to require all of them.

The role is read from user.role unless you configure another property. See Naming the role field.

Disabling auto-injection

src/payload.config.ts
createBetterAuthPlugin({
  createAuth,
  autoRegisterEndpoints: false,
  autoInjectAdminComponents: false,
})

autoInjectAdminComponents only acts when your users collection sets auth.disableLocalStrategy. A collection with auth: true keeps Payload's own login.

To turn off individual pieces instead, use admin.disableLoginView, admin.disableLogoutButton and admin.disableBeforeLogin. The full list is in createBetterAuthPlugin.

Custom admin components

Point the plugin at your own components using Payload import-map paths:

src/payload.config.ts
createBetterAuthPlugin({
  createAuth,
  admin: {
    loginViewComponent: '@/components/admin/CustomLogin',
    logoutButtonComponent: '@/components/admin/CustomLogout',
    disableBeforeLogin: true,
  },
})

beforeLoginComponent replaces the BeforeLogin redirect the same way. The built-in components (LoginView, LogoutButton, BeforeLogin) are exported from @delmaredigital/payload-better-auth/components if you want to wrap rather than replace them.

Manual API route

With autoRegisterEndpoints: false, mount Better Auth's handler in a Next.js route yourself. All Better Auth customization (hooks, plugins, callbacks) still belongs in createAuth; the route is a passthrough.

src/app/api/auth/[...all]/route.ts
import type { NextRequest } from 'next/server'
import { getPayload } from 'payload'
import config from '@payload-config'
import type { PayloadWithAuth } from '@delmaredigital/payload-better-auth'

export async function GET(request: NextRequest) {
  const payload = (await getPayload({ config })) as PayloadWithAuth
  return payload.betterAuth.handler(request)
}

export async function POST(request: NextRequest) {
  const payload = (await getPayload({ config })) as PayloadWithAuth
  return payload.betterAuth.handler(request)
}

The Better Auth instance is created in Payload's onInit and attached to payload.betterAuth.

Edit this page on GitHub

On this page