admin plugin can't read cookie? #2752

Closed
opened 2026-03-13 10:18:00 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @wszgrcy on GitHub (Jan 22, 2026).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

 let list = await db.select().from(user).where(eq(user.name, 'admin'));
  if (list.length) {
    return;
  }

  let result0 = await auth.api.signUpEmail({
    body: {
      name: 'admin',
      email: 'admin@admin.com',
      password: '12345678',
    },
  });

  await db
    .update(user)
    .set({ role: 'admin' })
    .where(eq(user.id, result0.user.id));
  let result2 = await auth.api.signInEmail({
    body: {
      email: 'admin@admin.com',
      password: '12345678',
    },
    returnHeaders: true,
  });

  const result = await auth.api.listUsers({
    query: {
      searchValue: 'admin',
      searchField: 'name',
      limit: 0,
    },
    headers: [['cookie', result2.headers.get('set-cookie')!]],
  });

Current vs. Expected behavior

must set headers with [['cookie', result2.headers.get('set-cookie')!]],

What version of Better Auth are you using?

1.4.17

System info

{
  "system": {
    "platform": "win32",
    "arch": "x64",
    "version": "Windows 10 Pro",
    "release": "10.0.19045",
    "cpuCount": 24,
    "cpuModel": "AMD Ryzen 9 5900X 12-Core Processor            ",
    "totalMemory": "63.93 GB",
    "freeMemory": "41.79 GB"
  },
  "node": {
    "version": "v22.17.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "10.9.2"
  },
  "frameworks": [
    {
      "name": "fastify",
      "version": "^5.7.1"
    }
  ],
  "databases": [
    {
      "name": "better-sqlite3",
      "version": "^12.6.2"
    },
    {
      "name": "drizzle",
      "version": "0.45.1"
    }
  ],
  "betterAuth": {
    "version": "1.4.17",
    "config": null
  }
}

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

Backend

Auth config (if applicable)

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: 'sqlite',
    schema: BetterAuthSchemaGroup,
  }),
  emailAndPassword: {
    enabled: true,
  },
  trustedOrigins: ['http://localhost:4200'],
  plugins: [
  admin({
    ac,
    roles: {
      admin: adminRole,
      user: userRole,
    },
  }),
],
});

Additional context

When initializing the admin plugin on the backend, I found that using the header returned by signInEmail and passing it to auth.api.listUsers results in a 401 error. After debugging, it seems the request only works if I replace the set-cookie header with cookie. However, this issue isn’t mentioned in the documentation—is this a bug, or am I missing something?

Originally created by @wszgrcy on GitHub (Jan 22, 2026). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce ```ts let list = await db.select().from(user).where(eq(user.name, 'admin')); if (list.length) { return; } let result0 = await auth.api.signUpEmail({ body: { name: 'admin', email: 'admin@admin.com', password: '12345678', }, }); await db .update(user) .set({ role: 'admin' }) .where(eq(user.id, result0.user.id)); let result2 = await auth.api.signInEmail({ body: { email: 'admin@admin.com', password: '12345678', }, returnHeaders: true, }); const result = await auth.api.listUsers({ query: { searchValue: 'admin', searchField: 'name', limit: 0, }, headers: [['cookie', result2.headers.get('set-cookie')!]], }); ``` ### Current vs. Expected behavior must set headers with ` [['cookie', result2.headers.get('set-cookie')!]],` ### What version of Better Auth are you using? 1.4.17 ### System info ```bash { "system": { "platform": "win32", "arch": "x64", "version": "Windows 10 Pro", "release": "10.0.19045", "cpuCount": 24, "cpuModel": "AMD Ryzen 9 5900X 12-Core Processor ", "totalMemory": "63.93 GB", "freeMemory": "41.79 GB" }, "node": { "version": "v22.17.0", "env": "development" }, "packageManager": { "name": "npm", "version": "10.9.2" }, "frameworks": [ { "name": "fastify", "version": "^5.7.1" } ], "databases": [ { "name": "better-sqlite3", "version": "^12.6.2" }, { "name": "drizzle", "version": "0.45.1" } ], "betterAuth": { "version": "1.4.17", "config": null } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript export const auth = betterAuth({ database: drizzleAdapter(db, { provider: 'sqlite', schema: BetterAuthSchemaGroup, }), emailAndPassword: { enabled: true, }, trustedOrigins: ['http://localhost:4200'], plugins: [ admin({ ac, roles: { admin: adminRole, user: userRole, }, }), ], }); ``` ### Additional context When initializing the admin plugin on the backend, I found that using the header returned by `signInEmail` and passing it to `auth.api.listUsers` results in a 401 error. After debugging, it seems the request only works if I replace the `set-cookie` header with `cookie`. However, this issue isn’t mentioned in the documentation—is this a bug, or am I missing something?
GiteaMirror added the bug label 2026-03-13 10:18:00 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Jan 22, 2026):

It seems that you're facing an issue with the admin plugin in Better Auth not reading the cookie correctly, resulting in a 401 error when trying to use the auth.api.listUsers method with the set-cookie returned from signInEmail. You correctly noted that changing the header from set-cookie to cookie resolves the issue, but the documentation does not acknowledge this.

This does appear to be a valid concern, as it suggests a potential issue with how cookies are being handled in the Admin plugin. There is an open issue regarding the admin plugin returning a 401 error, which might be related to your situation. You might want to refer to that and see if there are any updates or solutions proposed [1].

For your next steps, consider filing a detailed bug report if you haven't done so already, as your findings might help the Better Auth team address this potential issue more efficiently. Remember to test if the behavior persists across different environments, as configurations can sometimes lead to inconsistent behavior.

Would you like to explore further debugging options, or do you have any other questions about Better Auth?

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

@better-auth-agent[bot] commented on GitHub (Jan 22, 2026): It seems that you're facing an issue with the admin plugin in Better Auth not reading the cookie correctly, resulting in a 401 error when trying to use the `auth.api.listUsers` method with the `set-cookie` returned from `signInEmail`. You correctly noted that changing the header from `set-cookie` to `cookie` resolves the issue, but the documentation does not acknowledge this. This does appear to be a valid concern, as it suggests a potential issue with how cookies are being handled in the Admin plugin. There is an open issue regarding the admin plugin returning a 401 error, which might be related to your situation. You might want to refer to that and see if there are any updates or solutions proposed [[1]](https://github.com/better-auth/better-auth/issues/5047). For your next steps, consider filing a detailed bug report if you haven't done so already, as your findings might help the Better Auth team address this potential issue more efficiently. Remember to test if the behavior persists across different environments, as configurations can sometimes lead to inconsistent behavior. Would you like to explore further debugging options, or do you have any other questions about Better Auth? _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) • [Discord](https://discord.gg/better-auth) • [GitHub](https://github.com/better-auth/better-auth) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/better-auth) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/better-auth/better-auth)
Author
Owner

@dosubot[bot] commented on GitHub (Jan 22, 2026):

This isn't a bug—it's an expected integration detail with Better Auth and how HTTP cookies work. The set-cookie header is sent by the server in a response to tell the client to store a cookie; the cookie header is what the client (or your backend code) must send on subsequent requests to authenticate. Better Auth's admin plugin expects the session cookie in the cookie header for authentication, but it doesn't automatically convert set-cookie responses into cookie requests for you in backend/server-to-server flows. That's why you need to extract the cookie value from set-cookie and send it as a cookie header in your next API call—otherwise, you'll get a 401 error. This pattern is common in server-side integrations and is confirmed as expected behavior by maintainers and in the codebase (example, admin plugin code).

This behavior isn't clearly documented, which has led to confusion for others as well (discussion). For backend-to-backend API calls, you must manually manage the cookie header. There isn't a built-in helper for this in Better Auth as of v1.4.17.

If you want a more ergonomic or secure approach for backend automation, consider using the API Key or Bearer token plugins for admin endpoints, which avoid cookie juggling altogether (reference). But for session-based flows, manual cookie header propagation is required.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Jan 22, 2026): <!-- Answer --> This isn't a bug—it's an expected integration detail with Better Auth and how HTTP cookies work. The `set-cookie` header is sent by the server in a response to tell the client to store a cookie; the `cookie` header is what the client (or your backend code) must send on subsequent requests to authenticate. Better Auth's admin plugin expects the session cookie in the `cookie` header for authentication, but it doesn't automatically convert `set-cookie` responses into `cookie` requests for you in backend/server-to-server flows. That's why you need to extract the cookie value from `set-cookie` and send it as a `cookie` header in your next API call—otherwise, you'll get a 401 error. This pattern is common in server-side integrations and is confirmed as expected behavior by maintainers and in the codebase ([example](https://github.com/better-auth/better-auth/issues/4945), [admin plugin code](https://github.com/better-auth/better-auth/blob/d1602ef0ae9822e462a5a42497072a0a1756e804/packages/better-auth/src/plugins/admin/routes.ts#L11-L695)). This behavior isn't clearly documented, which has led to confusion for others as well ([discussion](https://github.com/better-auth/better-auth/issues/6530)). For backend-to-backend API calls, you must manually manage the cookie header. There isn't a built-in helper for this in Better Auth as of v1.4.17. If you want a more ergonomic or secure approach for backend automation, consider using the API Key or Bearer token plugins for admin endpoints, which avoid cookie juggling altogether ([reference](https://github.com/better-auth/better-auth/discussions/5659)). But for session-based flows, manual cookie header propagation is required. <!-- 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/7b6e2af6-f3e9-4d46-91fe-eadcd9321ce5?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/7b6e2af6-f3e9-4d46-91fe-eadcd9321ce5?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/7b6e2af6-f3e9-4d46-91fe-eadcd9321ce5?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/7b6e2af6-f3e9-4d46-91fe-eadcd9321ce5?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/7b6e2af6-f3e9-4d46-91fe-eadcd9321ce5?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/7b6e2af6-f3e9-4d46-91fe-eadcd9321ce5?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/7b6e2af6-f3e9-4d46-91fe-eadcd9321ce5?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20isn%27t%20a%20bug%E2%80%94it%27s%20an%20expected%20integration%20detail%20with%20Better%20Auth%20and%20how%20HTTP%20cookies%20work.%20The%20%60set-cookie%60%20header%20is%20sent%20by%20the%20server%20in%20a%20response%20to%20tell%20the%20client%20to%20store%20a%20cookie%3B%20the%20%60cookie%60%20header%20is%20what%20the%20client%20%28or%20your%20backend%20code%29%20must%20send%20on%20subsequent%20requests%20to%20authenticate.%20Better%20Auth%27s%20admin%20plugin%20expects%20the%20session%20cookie%20in%20the%20%60cookie%60%20header%20for%20authentication%2C%20but%20it%20doesn%27t%20automatically%20convert%20%60set-cookie%60%20responses%20into%20%60cookie%60%20requests%20for%20you%20in%20backend/server-to-server%20flows.%20That%27s%20why%20you%20need%20to%20extract%20the%20cookie%20value%20from%20%60set-cookie%60%20and%20send%20it%20as%20a%20%60cookie%60%20header%20in%20your%20next%20API%20call%E2%80%94otherwise%2C%20you%27ll%20get%20a%20401%20error.%20This%20pattern%20is%20common%20in%20server-side%20integrations%20and%20is%20confirmed%20as%20expected%20behavior%20by%20maintainers%20and%20in%20the%20codebase%20%28%5Bexample%5D%28https%3A//github.com/better-auth/better-auth/issues/4945%29%2C%20%5Badmin%20plugin%20code%5D%28https%3A//github.com/better-auth/better-auth/blob/d1602ef0ae9822e462a5a42497072a0a1756e804/packages/better-auth/src/plugins/admin/routes.ts%23L11-L695%29%29.%0A%0AThis%20behavior%20isn%27t%20clearly%20documented%2C%20which%20has%20led%20to%20confusion%20for%20others%20as%20well%20%28%5Bdiscussion%5D%28https%3A//github.com/better-auth/better-auth/issues/6530%29%29.%20For%20backend-to-backend%20API%20calls%2C%20you%20must%20manually%20manage%20the%20cookie%20header.%20There%20isn%27t%20a%20built-in%20helper%20for%20this%20in%20Better%20Auth%20as%20of%20v1.4.17.%0A%0AIf%20you%20want%20a%20more%20ergonomic%20or%20secure%20approach%20for%20backend%20automation%2C%20consider%20using%20the%20API%20Key%20or%20Bearer%20token%20plugins%20for%20admin%20endpoints%2C%20which%20avoid%20cookie%20juggling%20altogether%20%28%5Breference%5D%28https%3A//github.com/better-auth/better-auth/discussions/5659%29%29.%20But%20for%20session-based%20flows%2C%20manual%20cookie%20header%20propagation%20is%20required.)&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/7553)
Author
Owner

@bytaesu commented on GitHub (Jan 22, 2026):

Hi @wszgrcy,

You might want to take a look at cookie helpers like setCookieToHeader and parseSetCookieHeader.

And... It might actually be cleaner to check this instead.
https://www.better-auth.com/docs/concepts/hooks#internal-adapter

@bytaesu commented on GitHub (Jan 22, 2026): Hi @wszgrcy, You might want to take a look at cookie helpers like `setCookieToHeader` and `parseSetCookieHeader`. And... It might actually be cleaner to check this instead. https://www.better-auth.com/docs/concepts/hooks#internal-adapter
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2752