--- 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", }); ```