Admin Overview

Overview of the admin panel features including user management, organization oversight, and platform analytics.

The Admin Panel provides system administrators with tools to manage users, organizations, and monitor platform activity. Access it at /admin when signed in with an admin account.

This documentation covers the admin system built on Better Auth's admin plugin with MakerKit's RBAC layer.

Getting Started

Creating Your First Admin

After running pnpm seed, use these test credentials:

  • Email: admin1@makerkit.dev
  • Password: testingpassword

To promote an existing user to admin:

  1. Run Drizzle Studio: pnpm --filter "@kit/database" run drizzle:studio
  2. Open the users table
  3. Set the role column to admin for your user
  4. Sign out and back in to refresh the session

Alternatively, use the Better Auth CLI or API to update roles programmatically.

Admin Role Verification

When a user accesses /admin/* routes, the system verifies admin status through multiple layers:

  1. Middleware (proxy.ts) checks if the user has an admin role
  2. Server Components use requireAdmin() to validate and redirect if unauthorized
  3. Server Actions use adminActionClient which verifies the user's role before executing

Dashboard Metrics

The admin dashboard at /admin displays four key metrics:

MetricDescription
Total UsersAll registered user accounts
Active SessionsSessions created in the last 24 hours
Banned UsersAccounts with restricted access
New This WeekSign-ups from the past 7 days

These metrics are loaded server-side using React's cache() function to prevent duplicate queries within the same request.

Architecture

The admin system is organized across several packages:

packages/admin/ # Admin UI components and logic
├── src/
│ ├── dashboard/ # Dashboard page and metrics
│ │ ├── lib/
│ │ │ ├── actions/ # Server actions
│ │ │ ├── loaders/ # Data loaders
│ │ │ ├── schemas/ # Zod schemas
│ │ │ └── services/ # Business logic
│ │ └── page.tsx # Dashboard component
│ ├── users/ # User management
│ ├── organizations/ # Organization management
│ └── hooks/ # Client-side hooks
packages/rbac/ # Role-based access control
├── src/
│ ├── admin/ # Admin RBAC utilities
│ │ ├── factory.ts # Config factory
│ │ ├── defaults.ts # Default resources/actions
│ │ └── client.ts # Permission checking
│ └── admin-rbac.config.ts # Your customization file
packages/auth/ # Authentication utilities
├── src/utils/
│ ├── require-admin.ts # Server-side admin check
│ └── is-admin-role.ts # Role validation
packages/action-middleware/ # Server action utilities
├── src/
│ ├── require-admin-action-middleware.ts # Admin action client
│ └── require-admin-permission-middleware.ts # Permission middleware

Core Features

User Management

The Users section (/admin/users) provides full control over user accounts:

  • Search: Find users by name or email
  • Filter: By role (user/admin) and status (active/banned)
  • Sort: By name, email, creation date, role, or status
  • Paginated results: 25 users per page

Available actions per user:

ActionDescription
View DetailsFull user profile with sessions and subscriptions
Change RolePromote to admin or demote to user
ImpersonateSign in as the user for debugging (restrictions apply)
Ban/UnbanRestrict or restore account access
RemovePermanently delete the account
View SessionsSee all active sessions
Revoke SessionsEnd specific or all sessions
Admin Users Table

See User Management for detailed documentation.

Organization Management

The Organizations section (/admin/organizations) lets you oversee all teams:

  • Search: Find organizations by name
  • View Details: See organization info, members, and subscriptions
  • Member Access: Click through to any member's user details
Admin Organizations Table

See Organization Management for detailed documentation.

Role-Based Access Control

Admin permissions are configured via RBAC in packages/rbac/src/admin-rbac.config.ts. The default configuration provides a single admin role with full permissions. You can add custom roles with restricted access:

import { defineAdminRBACConfig } from './admin/factory';
export default defineAdminRBACConfig({
// Add custom roles with limited permissions
roles: {
support: 50, // Can help users but not delete
moderator: 30, // Can ban but limited access
},
permissions: {
support: {
user: ['list', 'get', 'ban'],
session: ['list', 'revoke'],
organizations: ['list', 'view'],
dashboard: ['view'],
},
},
});

See RBAC Permissions for detailed documentation on customizing admin roles.

The admin sidebar includes:

  • Dashboard (/admin) - Overview and statistics
  • Users (/admin/users) - User management
  • Organizations (/admin/organizations) - Organization oversight

Click "Back to Dashboard" in the sidebar header to return to your regular account.

Security Layers

The admin panel includes multiple security layers:

1. Route Protection (Middleware)

The middleware in apps/web/proxy.ts blocks non-admin access to /admin/* routes:

// Simplified from apps/web/proxy.ts
if (pathname.startsWith('/admin')) {
const isAdmin = await isUserAdmin();
if (!isAdmin) {
return NextResponse.redirect(new URL('/auth/sign-in', request.url));
}
}

2. Server-Side Checks

requireAdmin() verifies admin status in server components and redirects to a 403 page if unauthorized:

import { requireAdmin } from '@kit/auth/require-admin';
export default async function AdminPage() {
await requireAdmin(); // Redirects if not admin
// ... render admin content
}

3. Action Protection

adminActionClient protects all server actions:

import { adminActionClient } from '@kit/action-middleware';
export const myAdminAction = adminActionClient
.inputSchema(schema)
.action(async ({ ctx }) => {
// ctx.user is guaranteed to be admin
});

4. Permission Checks

withAdminPermission() enforces granular RBAC permissions:

import { adminActionClient, withAdminPermission } from '@kit/action-middleware';
export const banUserAction = adminActionClient
.use(withAdminPermission({ user: ['ban'] }))
.inputSchema(schema)
.action(async ({ ctx }) => {
// Only admins with 'user:ban' permission reach here
});

5. Impersonation Safeguards

The impersonation feature includes restrictions:

  • Cannot impersonate admin users
  • Cannot impersonate banned accounts
  • A banner appears during impersonation showing the original admin

Key Imports

ImportPackagePurpose
requireAdmin@kit/auth/require-adminServer-side admin check with redirect
isUserAdmin@kit/auth/require-adminServer-side check without redirect
isAdminRole@kit/auth/is-admin-roleClient-safe role validation
adminActionClient@kit/action-middlewareProtected action client
withAdminPermission@kit/action-middlewarePermission middleware
useAdminPermissions@kit/admin/hooks/use-admin-permissionsClient permission hook

For implementation details on adding custom features, see Extending Admin.

Frequently Asked Questions

How do I create my first admin user?
Run pnpm seed to create test admin credentials, or manually set the role column to 'admin' in the users table using Drizzle Studio. Sign out and back in to refresh the session after changing roles.
What's the difference between requireAdmin and adminActionClient?
requireAdmin() is for server components and data loaders - it redirects unauthorized users to a 403 page. adminActionClient is for server actions - it returns an error response instead of redirecting, which is appropriate for API-style calls.
Can I have multiple admin roles with different permissions?
Yes. Configure custom roles in packages/rbac/src/admin-rbac.config.ts using defineAdminRBACConfig(). Each role gets a hierarchy level (number) and explicit permissions. The built-in 'admin' role always has full permissions.
How do I protect a custom admin page?
Three layers: 1) Routes under /admin/* are automatically protected by middleware, 2) Call requireAdmin() in your server component, 3) Use adminActionClient for any server actions. See Extending Admin for complete examples.
Can admins impersonate other admin users?
No. The impersonation feature has built-in safeguards that prevent impersonating admin users or banned accounts. This is enforced at the Better Auth level.

This admin panel is part of the Next.js Drizzle SaaS Kit.


Next: User Management