[GH-ISSUE #6159] Server-side createInvitation requires session token #19061

Closed
opened 2026-04-15 17:50:43 -05:00 by GiteaMirror · 5 comments
Owner

Originally created by @pesterhazy on GitHub (Nov 21, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/6159

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

TL;DR: it seems like to issue an invitation from the server side, you need to awkwardly create a session for an existing user. Is there a better way to do this?

I'm using the organization plugin.

This code is from our integration test:

 const organization = await createTestOrganization({
    accountId: account.id,
    betterAuth: betterAuthService.getBetterAuth(),
  });

  const { user, password } = await createTestUserWithEmailPassword(
    betterAuthService.getBetterAuth(),
  );
  const { sessionToken } = await signInAndCreateSession({
    email: user.email,
    password,
    betterAuth: betterAuthService.getBetterAuth(),
  });
  await assignMemberToOrganization({
    userId: user.id,
    organizationId: organization.id,
    sessionToken,
    betterAuth: betterAuthService.getBetterAuth(),
    role: "owner",
  });

  const invitation = await betterAuthService.createInvitation({
    email: "test@test.com",
    role: "member",
    organizationId: organization.id,
    sessionToken,
  });

whereas createInvitation is a light wrapper

  async createInvitation(opts: {
    email: string;
    role: BetterAuthRole | BetterAuthRole[];
    organizationId: string;
    sessionToken: string;
  }) {
    return await this.betterAuth.api.createInvitation({
      body: {
        email: opts.email,
        role: opts.role,
        organizationId: opts.organizationId,
      },
      headers: {
        cookie: `better-auth.session_token=${opts.sessionToken}`,
      },
    });
  }

Our use case is that on creating a new account, we want to automatically send invitation emails to initial members of the org. We don't want to use the frontend to make those invitations - this should happen server-side upon account creation.

Current vs. Expected behavior

Expected behavior:

  • I can issue an invitation by supplying the user id of the inviter (initial member)
  • I don't need to create a fake session cookie

Actual behavior:

  • Invitation requires a cookie header (in a kind of fake http request)
  • I can't easily create a session cookie if the user doesn't have email/password auth enabled (at least I couldn't find a way)

Am I holding it wrong? Is there a recommended way to create an organization with pending / pre-accepted users?

What version of Better Auth are you using?

1.3.28

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 24.5.0: Tue Apr 22 19:54:29 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T6030",
    "release": "24.5.0",
    "cpuCount": 12,
    "cpuModel": "Apple M3 Pro",
    "totalMemory": "18.00 GB",
    "freeMemory": "0.16 GB"
  },
  "node": {
    "version": "v22.20.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "10.9.3"
  },
  "frameworks": [
    {
      "name": "react",
      "version": "19.0.0"
    },
    {
      "name": "fastify",
      "version": "^5.3.3"
    }
  ],
  "databases": [
    {
      "name": "better-sqlite3",
      "version": "^12.4.1"
    },
    {
      "name": "pg",
      "version": "^8.14.1"
    },
    {
      "name": "drizzle",
      "version": "^0.38.4"
    }
  ],
  "betterAuth": {
    "version": "^1.3.28",
    "config": null
  }
}

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

Additional context

No response

Originally created by @pesterhazy on GitHub (Nov 21, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/6159 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce TL;DR: it seems like to issue an invitation from the server side, you need to awkwardly create a session for an existing user. Is there a better way to do this? I'm using the organization plugin. This code is from our integration test: ``` const organization = await createTestOrganization({ accountId: account.id, betterAuth: betterAuthService.getBetterAuth(), }); const { user, password } = await createTestUserWithEmailPassword( betterAuthService.getBetterAuth(), ); const { sessionToken } = await signInAndCreateSession({ email: user.email, password, betterAuth: betterAuthService.getBetterAuth(), }); await assignMemberToOrganization({ userId: user.id, organizationId: organization.id, sessionToken, betterAuth: betterAuthService.getBetterAuth(), role: "owner", }); const invitation = await betterAuthService.createInvitation({ email: "test@test.com", role: "member", organizationId: organization.id, sessionToken, }); ``` whereas createInvitation is a light wrapper ``` async createInvitation(opts: { email: string; role: BetterAuthRole | BetterAuthRole[]; organizationId: string; sessionToken: string; }) { return await this.betterAuth.api.createInvitation({ body: { email: opts.email, role: opts.role, organizationId: opts.organizationId, }, headers: { cookie: `better-auth.session_token=${opts.sessionToken}`, }, }); } ``` Our use case is that on creating a new account, we want to automatically send invitation emails to initial members of the org. We don't want to use the frontend to make those invitations - this should happen server-side upon account creation. ### Current vs. Expected behavior Expected behavior: - I can issue an invitation by supplying the user id of the inviter (initial member) - I don't need to create a fake session cookie Actual behavior: - Invitation requires a cookie header (in a kind of fake http request) - I can't easily create a session cookie if the user doesn't have email/password auth enabled (at least I couldn't find a way) Am I holding it wrong? Is there a recommended way to create an organization with pending / pre-accepted users? ### What version of Better Auth are you using? 1.3.28 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 24.5.0: Tue Apr 22 19:54:29 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T6030", "release": "24.5.0", "cpuCount": 12, "cpuModel": "Apple M3 Pro", "totalMemory": "18.00 GB", "freeMemory": "0.16 GB" }, "node": { "version": "v22.20.0", "env": "development" }, "packageManager": { "name": "npm", "version": "10.9.3" }, "frameworks": [ { "name": "react", "version": "19.0.0" }, { "name": "fastify", "version": "^5.3.3" } ], "databases": [ { "name": "better-sqlite3", "version": "^12.4.1" }, { "name": "pg", "version": "^8.14.1" }, { "name": "drizzle", "version": "^0.38.4" } ], "betterAuth": { "version": "^1.3.28", "config": null } } ``` ### 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 }, }); ``` ### Additional context _No response_
GiteaMirror added the locked label 2026-04-15 17:50:43 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Nov 21, 2025):

Hi there! Currently, the createInvitation API is designed to require a valid session token (passed via a cookie header) to ensure that only authenticated users can send invitations. This is why you must create a session—so that the invitation request is properly authenticated and authorized.

A couple of workarounds you might consider are:

• Using an existing system or service account session token for server-initiated invitations. This way, even if the invited user isn’t yet registered via email/password, the inviter’s session cookie can be used.

• Filing a feature request for an alternative API that accepts an inviter’s user ID directly instead of a session token, which could simplify the server-side flow for sending invitations.

Have you had a chance to explore using a service account or would you be open to discussing other approaches? Tag @better-auth-agent if you would like an answer from the Agent.

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3562485490 --> @better-auth-agent[bot] commented on GitHub (Nov 21, 2025): Hi there! Currently, the createInvitation API is designed to require a valid session token (passed via a cookie header) to ensure that only authenticated users can send invitations. This is why you must create a session—so that the invitation request is properly authenticated and authorized. A couple of workarounds you might consider are: • Using an existing system or service account session token for server-initiated invitations. This way, even if the invited user isn’t yet registered via email/password, the inviter’s session cookie can be used. • Filing a feature request for an alternative API that accepts an inviter’s user ID directly instead of a session token, which could simplify the server-side flow for sending invitations. Have you had a chance to explore using a service account or would you be open to discussing other approaches? Tag @better-auth-agent if you would like an answer from the Agent. <!-- 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

@rovertrack commented on GitHub (Nov 21, 2025):

Even though the headers are optional you are getting the Error ?

<!-- gh-comment-id:3563513240 --> @rovertrack commented on GitHub (Nov 21, 2025): Even though the headers are optional you are getting the Error ?
Author
Owner

@pesterhazy commented on GitHub (Nov 21, 2025):

If I remove the headers, I get a Forbidden error

<!-- gh-comment-id:3563975822 --> @pesterhazy commented on GitHub (Nov 21, 2025): If I remove the headers, I get a Forbidden error
Author
Owner

@sboh1214 commented on GitHub (Nov 28, 2025):

Also same issue for me.
When I use auth.api.createInvitation function in Next.js actions.ts,

    await auth.api.createInvitation({
      body: {
        email: data.email,
        role: data.role,
        organizationId,
        resend: true,
      },
    })

It shows error below.

Failed to invite member: [Error [APIError]: ] {
  status: 'UNAUTHORIZED',
  body: undefined,
  headers: {},
  statusCode: 401
}

As you @pesterhazy mentions, we should add header parameter to work correctly.

    await auth.api.createInvitation({
      body: {
        email: data.email,
        role: data.role,
        organizationId,
        resend: true,
      },
      headers: await headers(),
    })
<!-- gh-comment-id:3590702621 --> @sboh1214 commented on GitHub (Nov 28, 2025): Also same issue for me. When I use auth.api.createInvitation function in Next.js actions.ts, ```js await auth.api.createInvitation({ body: { email: data.email, role: data.role, organizationId, resend: true, }, }) ``` It shows error below. ``` Failed to invite member: [Error [APIError]: ] { status: 'UNAUTHORIZED', body: undefined, headers: {}, statusCode: 401 } ``` As you @pesterhazy mentions, we should add header parameter to work correctly. ```js await auth.api.createInvitation({ body: { email: data.email, role: data.role, organizationId, resend: true, }, headers: await headers(), }) ```
Author
Owner

@dosubot[bot] commented on GitHub (Feb 27, 2026):

Hi, @pesterhazy. I'm Dosu, and I'm helping the better-auth team manage their backlog and am marking this issue as stale.

Issue Summary:

  • You reported that creating organization invitations server-side requires a session token, which complicates session management for existing users.
  • The API currently requires a valid session token for authentication when creating invitations.
  • The suggestion was made to use a service account session token or to file a feature request for an alternative API method.
  • Other users confirmed the issue, noting that omitting session headers causes unauthorized errors, while including them works.
  • The discussion points to a need for a more streamlined server-side invitation process without relying on frontend sessions.

Next Steps:

  • Please let me know if this issue is still relevant with the latest version of better-auth by commenting here to keep the discussion open.
  • If I don’t hear back within 7 days, I will automatically close this issue.

Thank you for your understanding and contribution!

<!-- gh-comment-id:3973787630 --> @dosubot[bot] commented on GitHub (Feb 27, 2026): Hi, @pesterhazy. I'm [Dosu](https://dosu.dev), and I'm helping the better-auth team manage their backlog and am marking this issue as stale. **Issue Summary:** - You reported that creating organization invitations server-side requires a session token, which complicates session management for existing users. - The API currently requires a valid session token for authentication when creating invitations. - The suggestion was made to use a service account session token or to file a feature request for an alternative API method. - Other users confirmed the issue, noting that omitting session headers causes unauthorized errors, while including them works. - The discussion points to a need for a more streamlined server-side invitation process without relying on frontend sessions. **Next Steps:** - Please let me know if this issue is still relevant with the latest version of better-auth by commenting here to keep the discussion open. - If I don’t hear back within 7 days, I will automatically close this issue. Thank you for your understanding and contribution!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#19061