---
title: Admin
description: Admin plugin for Better Auth
---
The Admin plugin provides a set of administrative functions for user management in your application. It allows administrators to perform various operations such as creating users, managing user roles, banning/unbanning users, impersonating users, and more.
## Installation
### Add the plugin to your auth config
To use the Admin plugin, add it to your auth config.
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { admin } from "better-auth/plugins" // [!code highlight]
export const auth = betterAuth({
// ... other config options
plugins: [
admin() // [!code highlight]
]
})
```
### Migrate the database
Run the migration or generate the schema to add the necessary fields and tables to the database.
```bash
npx @better-auth/cli migrate
```
```bash
npx @better-auth/cli generate
```
See the [Schema](#schema) section to add the fields manually.
### Add the client plugin
Next, include the admin client plugin in your authentication client instance.
```ts title="auth-client.ts"
import { createAuthClient } from "better-auth/client"
import { adminClient } from "better-auth/client/plugins"
const authClient = createAuthClient({
plugins: [
adminClient()
]
})
```
## Usage
Before performing any admin operations, the user must be authenticated with an admin account. An admin is any user assigned the `admin` role or any user whose ID is included in the `adminUserIds` option.
### Create User
Allows an admin to create a new user.
```ts title="admin.ts"
const newUser = await authClient.admin.createUser({
name: "Test User",
email: "test@example.com",
password: "password123",
role: "user",
data: {
// any additional on the user table including plugin fields and custom fields
customField: "customValue",
},
});
```
### List Users
Allows an admin to list all users in the database.
```ts title="admin.ts"
const users = await authClient.admin.listUsers({
query: {
limit: 10,
},
});
```
By default, 100 users are returned. You can adjust the limit and offset using the following query parameters:
- `search`: The search query to apply to the users. It can be an object with the following properties:
- `field`: The field to search on, which can be `email` or `name`.
- `operator`: The operator to use for the search. It can be `contains`, `starts_with`, or `ends_with`.
- `value`: The value to search for.
- `limit`: The number of users to return.
- `offset`: The number of users to skip.
- `sortBy`: The field to sort the users by.
- `sortDirection`: The direction to sort the users by. Defaults to `asc`.
- `filter`: The filter to apply to the users. It can be an array of objects.
```ts title="admin.ts"
const users = await authClient.admin.listUsers({
query: {
searchField: "email",
searchOperator: "contains",
searchValue: "@example.com",
limit: 10,
offset: 0,
sortBy: "createdAt",
sortDirection: "desc"
filterField: "role",
filterOperator: "eq",
filterValue: "admin"
}
});
```
#### Pagination
The `listUsers` function supports pagination by returning metadata alongside the user list. The response includes the following fields:
```ts
{
users: User[], // Array of returned users
total: number, // Total number of users after filters and search queries
limit: number | undefined, // The limit provided in the query
offset: number | undefined // The offset provided in the query
}
```
##### How to Implement Pagination
To paginate results, use the `total`, `limit`, and `offset` values to calculate:
- **Total pages:** `Math.ceil(total / limit)`
- **Current page:** `(offset / limit) + 1`
- **Next page offset:** `Math.min(offset + limit, (total - 1))` – The value to use as `offset` for the next page, ensuring it does not exceed the total number of pages.
- **Previous page offset:** `Math.max(0, offset - limit)` – The value to use as `offset` for the previous page (ensuring it doesn’t go below zero).
##### Example Usage
Fetching the second page with 10 users per page:
```ts title="admin.ts"
const pageSize = 10;
const currentPage = 2;
const users = await authClient.admin.listUsers({
query: {
limit: pageSize,
offset: (currentPage - 1) * pageSize
}
});
const totalUsers = users.total;
const totalPages = Math.ceil(totalUsers / limit)
```
### Set User Role
Changes the role of a user.
```ts title="admin.ts"
const updatedUser = await authClient.admin.setRole({
userId: "user_id_here",
role: "admin",
});
```
### Ban User
Bans a user, preventing them from signing in and revokes all of their existing sessions.
```ts title="admin.ts"
const bannedUser = await authClient.admin.banUser({
userId: "user_id_here",
banReason: "Spamming", // Optional (if not provided, the default ban reason will be used - No reason)
banExpiresIn: 60 * 60 * 24 * 7, // Optional (if not provided, the ban will never expire)
});
```
### Unban User
Removes the ban from a user, allowing them to sign in again.
```ts title="admin.ts"
const unbannedUser = await authClient.admin.unbanUser({
userId: "user_id_here",
});
```
### List User Sessions
Lists all sessions for a user.
```ts title="admin.ts"
const sessions = await authClient.admin.listUserSessions({
userId: "user_id_here",
});
```
### Revoke User Session
Revokes a specific session for a user.
```ts title="admin.ts"
const revokedSession = await authClient.admin.revokeUserSession({
sessionToken: "session_token_here",
});
```
### Revoke All Sessions for a User
Revokes all sessions for a user.
```ts title="admin.ts"
const revokedSessions = await authClient.admin.revokeUserSessions({
userId: "user_id_here",
});
```
### Impersonate User
This feature allows an admin to create a session that mimics the specified user. The session will remain active until either the browser session ends or it reaches 1 hour. You can change this duration by setting the `impersonationSessionDuration` option.
```ts title="admin.ts"
const impersonatedSession = await authClient.admin.impersonateUser({
userId: "user_id_here",
});
```
### Stop Impersonating User
To stop impersonating a user and continue with the admin account, you can use `stopImpersonating`
```ts title="admin.ts"
await authClient.admin.stopImpersonating();
```
### Remove User
Hard deletes a user from the database.
```ts title="admin.ts"
const deletedUser = await authClient.admin.removeUser({
userId: "user_id_here",
});
```
## Access Control
The admin plugin offers a highly flexible access control system, allowing you to manage user permissions based on their role. You can define custom permission sets to fit your needs.
### Roles
By default, there are two roles:
`admin`: Users with the admin role have full control over other users.
`user`: Users with the user role have no control over other users.
### Permissions
By default, there are two resources with up to six permissions.
**user**:
`create` `list` `set-role` `ban` `impersonate` `delete` `set-password`
**session**:
`list` `revoke` `delete`
The admin have full control over all the resources and actions. The user have no control over any of those actions.
### Custom Permissions
the plugin providers easy way to define your own set of permission for each role.
#### Create Access Control
You first need to create access controller by calling `createAccessControl` function and passing the statement object. The statement object should have the resource name as the key and the array of actions as the value.
```ts title="permissions.ts"
import { createAccessControl } from "better-auth/plugins/access";
/**
* make sure to use `as const` so typescript can infer the type correctly
*/
const statement = { // [!code highlight]
project: ["create", "share", "update", "delete"], // [!code highlight]
} as const; // [!code highlight]
const ac = createAccessControl(statement); // [!code highlight]
```
#### Create Roles
Once you have created the access controller you can create roles with the permissions you have defined.
```ts title="permissions.ts"
import { createAccessControl } from "better-auth/plugins/access";
const statement = {
project: ["create", "share", "update", "delete"],
} as const;
const ac = createAccessControl(statement);
const user = ac.newRole({ // [!code highlight]
project: ["create"], // [!code highlight]
}); // [!code highlight]
const admin = ac.newRole({ // [!code highlight]
project: ["create", "update"], // [!code highlight]
}); // [!code highlight]
const myCustomRole = ac.newRole({ // [!code highlight]
project: ["create", "update", "delete"], // [!code highlight]
user: ["ban"], // [!code highlight]
}); // [!code highlight]
```
When you create custom roles for existing roles, the predefined permissions for those roles will be overridden. To add the existing permissions to the custom role, you need to import `defaultStatements` and merge it with your new statement, plus merge the roles' permissions set with the default roles.
```ts title="permissions.ts"
import { createAccessControl } from "better-auth/plugins/access";
import { defaultStatements, adminAc } from "better-auth/plugins/admin/access";
const statement = {
...defaultStatements, // [!code highlight]
project: ["create", "share", "update", "delete"],
} as const;
const ac = createAccessControl(statement);
const admin = ac.newRole({
project: ["create", "update"],
...adminAc.statements, // [!code highlight]
});
```
#### Pass Roles to the Plugin
Once you have created the roles you can pass them to the organization plugin both on the client and the server.
```ts title="auth.ts"
import { ac, admin, user } from "@/auth/permissions"
import { betterAuth } from "better-auth"
import { admin } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
admin({
ac: ac,
roles: {
admin,
user,
myCustomRole
}
}),
],
});
```
You also need to pass the access controller and the roles to the client plugin.
```ts title="auth-client.ts"
import { createAuthClient } from "better-auth/client"
import { adminClient } from "better-auth/client/plugins"
import { ac, admin, user, myCustomRole } from "@/auth/permissions"
export const client = createAuthClient({
plugins: [
adminClient({
ac: ac,
roles: {
admin,
user,
myCustomRole
}
})
]
})
```
### Access Control Usage
**Has Permission**:
To check the permission of the user, you can use the `hasPermission` function provided by the client.
```ts title="auth-client.ts"
const canCreateProject = await authClient.admin.hasPermission({
permission: {
project: ["create"],
},
});
```
If you want to use the server instead to check if a user has a permission, you can use `adminHasPermission` action provided by the `api` to check the permission of the user.
```ts title="api.ts"
import { auth } from "@/auth";
auth.api.adminHasPermission({
body: {
userId: 'id', //the user id
permission: {
project: ["create"], // This must match the structure in your access control
},
},
});
//you can also just pass the role directly
auth.api.adminHasPermission({
body: {
role: "admin",
permission: {
project: ["create"], // This must match the structure in your access control
},
},
});
```
**Check Role Permission**:
Once you have defined the roles and permissions to avoid checking the permission from the server you can use the `checkRolePermission` function provided by the client.
```ts title="auth-client.ts"
const canCreateProject = client.admin.checkRolePermission({
permission: {
user: ["delete"],
},
role: "admin",
});
```
## Schema
This plugin adds the following fields to the `user` table:
And adds one field in the `session` table:
## Options
### Default Role
The default role for a user. Defaults to `user`.
```ts title="auth.ts"
admin({
defaultRole: "regular",
});
```
### Admin Roles
The roles that are considered admin roles. Defaults to `["admin"]`.
```ts title="auth.ts"
admin({
adminRoles: ["admin", "superadmin"],
});
```
Any role that isn't in the `adminRoles` list, even if they have the permission,
will not be considered an admin.
### Admin userIds
You can pass an array of userIds that should be considered as admin. Default to `[]`
```ts title="auth.ts"
admin({
adminUserIds: ["user_id_1", "user_id_2"]
})
```
If a user is in the `adminUserIds` list, they will be able to perform any admin operation.
### impersonationSessionDuration
The duration of the impersonation session in seconds. Defaults to 1 hour.
```ts title="auth.ts"
admin({
impersonationSessionDuration: 60 * 60 * 24, // 1 day
});
```
### Default Ban Reason
The default ban reason for a user created by the admin. Defaults to `No reason`.
```ts title="auth.ts"
admin({
defaultBanReason: "Spamming",
});
```
### Default Ban Expires In
The default ban expires in for a user created by the admin in seconds. Defaults to `undefined` (meaning the ban never expires).
```ts title="auth.ts"
admin({
defaultBanExpiresIn: 60 * 60 * 24, // 1 day
});
```
### bannedUserMessage
The message to show when a banned user tries to sign in. Defaults to "You have been banned from this application. Please contact support if you believe this is an error."
```ts title="auth.ts"
admin({
bannedUserMessage: "Custom banned user message",
});
```