removeUser method in admin plugin shouldn't allow to delete the current session user - myself/himself #1925

Closed
opened 2026-03-13 09:12:55 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @anmol-fzr on GitHub (Sep 14, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Setup a Better Auth
  2. Add admin Plugin on both client and server
  3. use remove-user endpoint via admin plugin's authClient.admin.removeUser and pass the currently logged in admin's usedId

Current vs. Expected behavior

Better Auth must restrict removing the session user via the admin/remove-user endpoint

What version of Better Auth are you using?

1.3.4

System info

{
  "system": {
    "platform": "linux",
    "arch": "x64",
    "version": "#1 SMP PREEMPT_DYNAMIC Sun, 06 Jul 2025 11:14:36 +0000",
    "release": "6.15.5-arch1-1",
    "cpuCount": 16,
    "cpuModel": "12th Gen Intel(R) Core(TM) i5-1240P",
    "totalMemory": "23.17 GB",
    "freeMemory": "18.53 GB"
  },
  "node": {
    "version": "v20.19.3",
    "env": "development"
  },
  "packageManager": {
    "name": "bun",
    "version": "1.2.21"
  },
  "frameworks": null,
  "databases": null,
  "betterAuth": {
    "version": "0.0.0",
    "config": {
      "appName": "safe-fin-api",
      "session": {
        "cookieCache": {
          "enabled": true,
          "maxAge": 216000
        }
      },
      "plugins": [
        {
          "name": "expo",
          "config": {
            "id": "expo",
            "hooks": {
              "after": [
                {}
              ]
            }
          }
        },
        {
          "name": "admin",
          "config": {
            "id": "admin",
            "hooks": {
              "after": [
                {}
              ]
            },
            "endpoints": {},
            "$ERROR_CODES": {
              "FAILED_TO_CREATE_USER": "Failed to create user",
              "USER_ALREADY_EXISTS": "User already exists",
              "YOU_CANNOT_BAN_YOURSELF": "You cannot ban yourself",
              "YOU_ARE_NOT_ALLOWED_TO_CHANGE_USERS_ROLE": "You are not allowed to change users role",
              "YOU_ARE_NOT_ALLOWED_TO_CREATE_USERS": "You are not allowed to create users",
              "YOU_ARE_NOT_ALLOWED_TO_LIST_USERS": "You are not allowed to list users",
              "YOU_ARE_NOT_ALLOWED_TO_LIST_USERS_SESSIONS": "You are not allowed to list users sessions",
              "YOU_ARE_NOT_ALLOWED_TO_BAN_USERS": "You are not allowed to ban users",
              "YOU_ARE_NOT_ALLOWED_TO_IMPERSONATE_USERS": "You are not allowed to impersonate users",
              "YOU_ARE_NOT_ALLOWED_TO_REVOKE_USERS_SESSIONS": "You are not allowed to revoke users sessions",
              "YOU_ARE_NOT_ALLOWED_TO_DELETE_USERS": "You are not allowed to delete users",
              "YOU_ARE_NOT_ALLOWED_TO_SET_USERS_PASSWORD": "[REDACTED]",
              "BANNED_USER": "You have been banned from this application",
              "NO_DATA_TO_UPDATE": "No data to update",
              "YOU_ARE_NOT_ALLOWED_TO_UPDATE_USERS": "You are not allowed to update users"
            },
            "schema": {
              "user": {
                "fields": {
                  "role": {
                    "type": "string",
                    "required": false,
                    "input": false
                  },
                  "banned": {
                    "type": "boolean",
                    "defaultValue": false,
                    "required": false,
                    "input": false
                  },
                  "banReason": {
                    "type": "string",
                    "required": false,
                    "input": false
                  },
                  "banExpires": {
                    "type": "date",
                    "required": false,
                    "input": false
                  }
                }
              },
              "session": {
                "fields": {
                  "impersonatedBy": {
                    "type": "string",
                    "required": false
                  }
                }
              }
            },
            "options": {
              "adminUserIds": [
                "F7EOrNtgbhOUA4FYvj0r7bN4eJykYGMb"
              ]
            }
          }
        },
        {
          "name": "open-api",
          "config": {
            "id": "open-api",
            "endpoints": {}
          }
        },
        {
          "name": "multi-session",
          "config": {
            "id": "multi-session",
            "endpoints": {},
            "hooks": {
              "after": [
                {},
                {}
              ]
            },
            "$ERROR_CODES": {
              "INVALID_SESSION_TOKEN": "[REDACTED]"
            }
          }
        },
        {
          "name": "phone-number",
          "config": {
            "id": "phone-number",
            "endpoints": {},
            "schema": {
              "user": {
                "fields": {
                  "phoneNumber": {
                    "type": "string",
                    "required": false,
                    "unique": true,
                    "sortable": true,
                    "returned": true
                  },
                  "phoneNumberVerified": {
                    "type": "boolean",
                    "required": false,
                    "returned": true,
                    "input": false
                  }
                }
              }
            },
            "rateLimit": [
              {
                "window": 60000,
                "max": 10
              }
            ],
            "$ERROR_CODES": {
              "INVALID_PHONE_NUMBER": "Invalid phone number",
              "PHONE_NUMBER_EXIST": "Phone number already exists",
              "INVALID_PHONE_NUMBER_OR_PASSWORD": "[REDACTED]",
              "UNEXPECTED_ERROR": "Unexpected error",
              "OTP_NOT_FOUND": "OTP not found",
              "OTP_EXPIRED": "OTP expired",
              "INVALID_OTP": "Invalid OTP",
              "PHONE_NUMBER_NOT_VERIFIED": "Phone number not verified"
            }
          }
        }
      ],
      "baseURL": "http://localhost:8787",
      "secret": "[REDACTED]",
      "trustedOrigins": [
        "http://localhost:5173",
        "http://192.168.29.57:5173"
      ]
    }
  }
}

Which area(s) are affected? (Select all that apply)

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
	plugins: [
		expo(),
		admin({
			adminUserIds: ["F7EOrNtgbhOUA4FYvj0r7bN4eJykYGMb"],
		}),
		
	],

});

Additional context

No response

Originally created by @anmol-fzr on GitHub (Sep 14, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Setup a Better Auth 2. Add admin Plugin on both client and server 3. use `remove-user` endpoint via admin plugin's `authClient.admin.removeUser` and pass the currently logged in admin's usedId ### Current vs. Expected behavior Better Auth must restrict removing the session user via the `admin/remove-user` endpoint ### What version of Better Auth are you using? 1.3.4 ### System info ```bash { "system": { "platform": "linux", "arch": "x64", "version": "#1 SMP PREEMPT_DYNAMIC Sun, 06 Jul 2025 11:14:36 +0000", "release": "6.15.5-arch1-1", "cpuCount": 16, "cpuModel": "12th Gen Intel(R) Core(TM) i5-1240P", "totalMemory": "23.17 GB", "freeMemory": "18.53 GB" }, "node": { "version": "v20.19.3", "env": "development" }, "packageManager": { "name": "bun", "version": "1.2.21" }, "frameworks": null, "databases": null, "betterAuth": { "version": "0.0.0", "config": { "appName": "safe-fin-api", "session": { "cookieCache": { "enabled": true, "maxAge": 216000 } }, "plugins": [ { "name": "expo", "config": { "id": "expo", "hooks": { "after": [ {} ] } } }, { "name": "admin", "config": { "id": "admin", "hooks": { "after": [ {} ] }, "endpoints": {}, "$ERROR_CODES": { "FAILED_TO_CREATE_USER": "Failed to create user", "USER_ALREADY_EXISTS": "User already exists", "YOU_CANNOT_BAN_YOURSELF": "You cannot ban yourself", "YOU_ARE_NOT_ALLOWED_TO_CHANGE_USERS_ROLE": "You are not allowed to change users role", "YOU_ARE_NOT_ALLOWED_TO_CREATE_USERS": "You are not allowed to create users", "YOU_ARE_NOT_ALLOWED_TO_LIST_USERS": "You are not allowed to list users", "YOU_ARE_NOT_ALLOWED_TO_LIST_USERS_SESSIONS": "You are not allowed to list users sessions", "YOU_ARE_NOT_ALLOWED_TO_BAN_USERS": "You are not allowed to ban users", "YOU_ARE_NOT_ALLOWED_TO_IMPERSONATE_USERS": "You are not allowed to impersonate users", "YOU_ARE_NOT_ALLOWED_TO_REVOKE_USERS_SESSIONS": "You are not allowed to revoke users sessions", "YOU_ARE_NOT_ALLOWED_TO_DELETE_USERS": "You are not allowed to delete users", "YOU_ARE_NOT_ALLOWED_TO_SET_USERS_PASSWORD": "[REDACTED]", "BANNED_USER": "You have been banned from this application", "NO_DATA_TO_UPDATE": "No data to update", "YOU_ARE_NOT_ALLOWED_TO_UPDATE_USERS": "You are not allowed to update users" }, "schema": { "user": { "fields": { "role": { "type": "string", "required": false, "input": false }, "banned": { "type": "boolean", "defaultValue": false, "required": false, "input": false }, "banReason": { "type": "string", "required": false, "input": false }, "banExpires": { "type": "date", "required": false, "input": false } } }, "session": { "fields": { "impersonatedBy": { "type": "string", "required": false } } } }, "options": { "adminUserIds": [ "F7EOrNtgbhOUA4FYvj0r7bN4eJykYGMb" ] } } }, { "name": "open-api", "config": { "id": "open-api", "endpoints": {} } }, { "name": "multi-session", "config": { "id": "multi-session", "endpoints": {}, "hooks": { "after": [ {}, {} ] }, "$ERROR_CODES": { "INVALID_SESSION_TOKEN": "[REDACTED]" } } }, { "name": "phone-number", "config": { "id": "phone-number", "endpoints": {}, "schema": { "user": { "fields": { "phoneNumber": { "type": "string", "required": false, "unique": true, "sortable": true, "returned": true }, "phoneNumberVerified": { "type": "boolean", "required": false, "returned": true, "input": false } } } }, "rateLimit": [ { "window": 60000, "max": 10 } ], "$ERROR_CODES": { "INVALID_PHONE_NUMBER": "Invalid phone number", "PHONE_NUMBER_EXIST": "Phone number already exists", "INVALID_PHONE_NUMBER_OR_PASSWORD": "[REDACTED]", "UNEXPECTED_ERROR": "Unexpected error", "OTP_NOT_FOUND": "OTP not found", "OTP_EXPIRED": "OTP expired", "INVALID_OTP": "Invalid OTP", "PHONE_NUMBER_NOT_VERIFIED": "Phone number not verified" } } } ], "baseURL": "http://localhost:8787", "secret": "[REDACTED]", "trustedOrigins": [ "http://localhost:5173", "http://192.168.29.57:5173" ] } } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, plugins: [ expo(), admin({ adminUserIds: ["F7EOrNtgbhOUA4FYvj0r7bN4eJykYGMb"], }), ], }); ``` ### Additional context _No response_
GiteaMirror added the plugin label 2026-03-13 09:12:55 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Sep 14, 2025):

The restriction to prevent an admin from deleting their own account via the removeUser method was added in a recent update after v1.3.4. The current implementation checks if the userId to be deleted matches the session user's id and throws an error if so, blocking self-deletion (see implementation). This logic is not present in v1.3.4.

If you need this restriction in v1.3.4, you can add a check in your backend handler for removeUser like:

if (ctx.body.userId === ctx.context.session.user.id) {
  throw new APIError("BAD_REQUEST", {
    message: "You cannot remove yourself",
  });
}

Upgrading to a version after August 2025 will include this feature out of the box.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Sep 14, 2025): <!-- Answer --> The restriction to prevent an admin from deleting their own account via the `removeUser` method was added in a recent update after v1.3.4. The current implementation checks if the userId to be deleted matches the session user's id and throws an error if so, blocking self-deletion ([see implementation](https://github.com/better-auth/better-auth/pull/4008)). This logic is not present in v1.3.4. If you need this restriction in v1.3.4, you can add a check in your backend handler for `removeUser` like: ```typescript if (ctx.body.userId === ctx.context.session.user.id) { throw new APIError("BAD_REQUEST", { message: "You cannot remove yourself", }); } ``` Upgrading to a version after August 2025 will include this feature out of the box. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/7c5ed634-cd23-4847-94b6-6a6410819b15?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/7c5ed634-cd23-4847-94b6-6a6410819b15?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/7c5ed634-cd23-4847-94b6-6a6410819b15?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/7c5ed634-cd23-4847-94b6-6a6410819b15?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/7c5ed634-cd23-4847-94b6-6a6410819b15?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/7c5ed634-cd23-4847-94b6-6a6410819b15?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/7c5ed634-cd23-4847-94b6-6a6410819b15?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4652)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1925