Admin
Add static user management, session details, and impersonation to Solid and Zaidan.
The Admin plugin adds a static /admin/users page and a user-detail dialog.
It also adds a "Stop impersonating" action to the copied <UserButton />.
Setup
Enable the Better Auth admin plugin
import { betterAuth } from "better-auth"
import { admin } from "better-auth/plugins"
export const auth = betterAuth({
// ...
plugins: [
admin()
]
})Update your database schema after enabling the plugin. Better Auth adds admin
fields to users and an impersonatedBy field to sessions.
Add the matching Solid client plugin
import { createAuthClient } from "@better-auth-ui/solid"
import { adminClient } from "better-auth/client/plugins"
export const authClient = createAuthClient({
plugins: [adminClient()]
})Install the Solid and Zaidan integration
npx shadcn@latest add https://better-auth-ui.com/r/solid/admin.jsonThis copies:
src/lib/auth/admin-plugin.tssrc/components/auth/admin/admin.tsxsrc/components/auth/admin/admin-users.tsxsrc/components/auth/admin/stop-impersonating.tsx
Register the copied UI plugin
import { AuthProvider } from "@/components/auth/auth-provider"
import { adminPlugin } from "@/lib/auth/admin-plugin"
<AuthProvider
authClient={authClient}
plugins={[adminPlugin()]}
>
{children}
</AuthProvider>Add the users route
Create one static TanStack Start route:
import { createFileRoute } from "@tanstack/solid-router"
import { Admin } from "@/components/auth/admin/admin"
export const Route = createFileRoute("/admin/users")({
component: () => <Admin view="users" />
})Use <Admin path="users" /> when a parent route supplies the final static path
segment. The user-detail dialog keeps user IDs out of the route contract.
Applications can control the selected user through <AdminUsers />:
import { AdminUsers } from "@/components/auth/admin/admin-users"
<AdminUsers
selectedUserId={selectedUserId()}
onSelectedUserIdChange={setSelectedUserId}
/>Inspector tabs
The user inspector includes local Overview and Sessions tabs. Registered plugins can add more tabs without adding routes.
The Dash integration adds an Activity tab when both UI plugins are registered. Dash applies its own organization owner or admin access rules to this tab.
User actions
The users page can create users. The dialog can update a user's name and role, set a password, ban or unban the user, impersonate the user, delete the user, and revoke one or all of the user's sessions.
The UI checks the matching Admin client permission before it enables each action. Dangerous actions require confirmation. The UI also disables actions that would ban, delete, impersonate, or revoke sessions for the current user.
Permissions and privacy
The users page calls the Better Auth permission API before it requests the user list. Do not authorize the page from a role string alone.
The table searches either email or name in each request. Passwords stay in
local form state. The forms clear each password after the request or when the
user closes the form. Session IP addresses are hidden unless showIpAddress
is true.
adminPlugin({
allowMultipleRoles: false,
defaultRole: "member",
impersonationRedirectTo: "/",
pageSize: 25,
roles: ["member", "support", "admin"],
showIpAddress: false
})Set allowMultipleRoles to false to make the create and edit forms accept
one role. This option does not change adminRoles, which controls administrator
access.
The public Admin client does not provide account disconnection, global organization administration, or a Sentinel dashboard. These views are not part of this integration.
User button behavior
The copied adminPlugin() contributes <StopImpersonating /> through the
userMenuItems slot. <UserButton /> places it above sign out.
The action renders only when session.session.impersonatedBy is present.
Selecting it calls authClient.admin.stopImpersonating() and refreshes the
cached session before the pending state completes.
import { StopImpersonating } from "@/components/auth/admin/stop-impersonating"
<StopImpersonating />Prop
Type
Options
adminPlugin({
localization: {
stopImpersonating: "Return to admin"
}
})Prop
Type
Localization
Prop
Type
Mutation API
import { useStopImpersonating } from "@better-auth-ui/solid/plugins/admin"
const stopImpersonating = useStopImpersonating(authClient)Use the hook when you need the same behavior outside the copied user button. It restores the admin session and awaits invalidation of the shared session query.
See the Solid package reference for the shared query and mutation APIs.
Last updated on