Admin Plugin

User management, role-based access control, banning, and impersonation for administrators.

This guide is part of the Drizzle stack docs.

Manage users from an admin dashboard. The admin plugin provides role-based access control, user banning, session management, and impersonation for support and debugging.

This page is part of the Authentication documentation.

Overview

The admin plugin extends Better Auth with administrative capabilities:

  • Role-based access control (RBAC) - Define admin roles with specific permissions
  • User management - View, search, and manage all users
  • Banning - Temporarily or permanently ban users
  • Impersonation - Sign in as another user for support
  • Session control - Revoke user sessions

Configuration

The admin plugin is configured in packages/better-auth/src/plugins/admin.ts:

import { admin } from 'better-auth/plugins/admin';
import { userAc } from 'better-auth/plugins/admin/access';
import {
adminAc,
adminRoles,
getAdminRoleNames,
} from '@kit/rbac/admin';
import { DEFAULT_ROLE } from './admin-config';
const IMPERSONATION_SESSION_DURATION = 60 * 60; // 1 hour
const DEFAULT_BAN_EXPIRES_IN = undefined; // Permanent
function buildRolesConfig() {
const roles = { user: userAc };
for (const [roleName, role] of Object.entries(adminRoles)) {
roles[roleName] = role;
}
return roles;
}
export const adminPlugin = admin({
defaultRole: DEFAULT_ROLE,
adminRoles: getAdminRoleNames(),
impersonationSessionDuration: IMPERSONATION_SESSION_DURATION,
defaultBanExpiresIn: DEFAULT_BAN_EXPIRES_IN,
ac: adminAc,
roles: buildRolesConfig(),
});

RBAC Configuration

Admin roles are defined in packages/rbac/src/admin-rbac.config.ts. The kit includes:

RoleDescription
userRegular user (non-admin)
adminFull administrative access
super-adminElevated admin with all permissions

Customizing Admin Roles

Edit packages/rbac/src/admin-rbac.config.ts to add or modify roles:

export const adminRoles = {
admin: adminAc.newRole({
user: ['read', 'update', 'ban'],
session: ['read', 'revoke'],
}),
'super-admin': adminAc.newRole({
user: ['read', 'update', 'delete', 'ban', 'impersonate'],
session: ['read', 'revoke', 'revokeAll'],
}),
// Add custom roles
support: adminAc.newRole({
user: ['read', 'impersonate'],
session: ['read'],
}),
};

Admin Dashboard

The admin panel is available at /admin for users with admin roles. Features include:

  • User list - Paginated view of all users
  • User search - Find users by email or name
  • User details - View account information, sessions, organizations
  • User actions - Ban, unban, impersonate, revoke sessions

See the Admin Overview documentation for detailed admin panel usage.

User Management

Listing Users

import { authClient } from '@kit/better-auth/client';
const { data: users } = await authClient.admin.listUsers({
limit: 20,
offset: 0,
sortBy: 'createdAt',
sortOrder: 'desc',
});

Searching Users

const { data: results } = await authClient.admin.listUsers({
searchField: 'email',
searchValue: 'user@example.com',
});

Banning Users

Ban a User

import { authClient } from '@kit/better-auth/client';
// Permanent ban
await authClient.admin.banUser({
userId: 'user-id',
reason: 'Violation of terms of service',
});
// Temporary ban (7 days)
await authClient.admin.banUser({
userId: 'user-id',
reason: 'Suspicious activity',
expiresIn: 7 * 24 * 60 * 60, // seconds
});

Unban a User

await authClient.admin.unbanUser({
userId: 'user-id',
});

Ban Behavior

When banned:

  • User's active sessions are revoked
  • User cannot sign in
  • User sees a "banned" message on sign-in attempt
  • Temporary bans auto-expire

Impersonation

Impersonation allows admins to sign in as another user for support and debugging without knowing their password.

Start Impersonation

import { authClient } from '@kit/better-auth/client';
await authClient.admin.impersonateUser({
userId: 'user-id',
});
// Now signed in as that user
// Session duration: 1 hour (configurable)

Stop Impersonation

await authClient.admin.stopImpersonation();
// Returns to admin account

Impersonation Safety

  • Impersonation sessions expire after 1 hour
  • Actions during impersonation are logged
  • The impersonated session is clearly marked
  • Cannot impersonate other admins (configurable)

Session Management

View User Sessions

const { data: sessions } = await authClient.admin.listUserSessions({
userId: 'user-id',
});
// Returns: session ID, device info, IP, created at, last active

Revoke a Session

await authClient.admin.revokeSession({
sessionId: 'session-id',
});

Revoke All Sessions

await authClient.admin.revokeUserSessions({
userId: 'user-id',
});

Role Assignment

Set User Role

await authClient.admin.setRole({
userId: 'user-id',
role: 'admin',
});

Check User Role

import { isAdminRole } from '@kit/better-auth/admin-config';
const user = await authClient.getSession();
if (isAdminRole(user?.data?.user?.role)) {
// User has admin privileges
}

Client-Side Role Checks

The admin-config.ts exports utilities for role checking:

import {
ADMIN_ROLES,
isAdminRole,
roleHasPermission,
getRolePermissions,
} from '@kit/better-auth/admin-config';
// Check if role is an admin role
if (isAdminRole('super-admin')) {
// true
}
// Check specific permission
if (roleHasPermission('admin', 'user', 'ban')) {
// Admin can ban users
}
// Get all permissions for a role
const permissions = getRolePermissions('admin');

Security Considerations

  • Principle of least privilege - Assign minimal necessary permissions
  • Audit logging - Log all admin actions for accountability
  • Two admin rule - Consider requiring multiple admins for destructive actions
  • Impersonation limits - Restrict what actions can be taken while impersonating

Common Pitfalls

  • Missing role checks in UI - Always check permissions before showing admin features.
  • Impersonation without logging - Ensure impersonation actions are auditable.
  • Overly permissive roles - Start restrictive and add permissions as needed.
  • Forgetting client plugin - Add adminClient() to auth-client.ts for client-side admin methods.

Frequently Asked Questions

How do I create the first admin user?
Use the database directly to set a user's role to 'admin' or 'super-admin'. After that, existing admins can promote other users.
Can I customize what admins can impersonate?
Yes. Modify the RBAC configuration to control which roles can impersonate and which roles can be impersonated.
How do I audit admin actions?
Implement logging in your admin action handlers. The kit includes logging infrastructure you can extend.
Can I have multiple admin levels?
Yes. Define multiple roles in admin-rbac.config.ts with different permission sets. Common patterns include admin, super-admin, support.
What happens to a user's data when banned?
Banning only prevents sign-in. User data remains intact. For data deletion, use account deletion which triggers cleanup hooks.

For detailed admin panel documentation, see Admin Overview.