100% stateless backend support for the organization plugin #2184

Closed
opened 2026-03-13 09:32:29 -05:00 by GiteaMirror · 5 comments
Owner

Originally created by @casvandergun on GitHub (Oct 22, 2025).

Is this suited for github?

  • Yes, this is suited for github

I’m using better-auth on my backend to serve both a web app and a mobile app. I’m running into issues fetching membership and roles because of the reliance on the active organization stored on the session object.

Currently, I believe it is only possible to access the membership and roles of the active organization, not from any other organization the signed in user is part of.

For a mobile app, where there might be connectivity issues, I don't want to rely on setting the active organization first, before fetching the membership and roles. A user might want to switch organizations when offline, causing the active organization on the backend to be out of drift.

In general, I think this project would benefit from better stateless support for implementations where the active organization state is managed on the frontend.

Describe the solution you'd like

I believe the entire organization plugin should be allowed to work without requiring the active organization to be set on the backend, so in a 100% stateless manner.

Proposal A (Minimal Change)
I'm not familiar with the entire API surface, so I might be missing something, but I believe adding organizationId and organizationSlug as optional query parameters to at least the .getActiveMember() and .getActiveMemberRole() functions should solve the problem. If no query parameters are passed, it could still default to the active organization.

const { data: member, error } = await authClient.organization.getActiveMember({
    query: {
        organizationId: "org-id",
        organizationSlug: "org-slug",
    },
});

const { data: roles, error } = await authClient.organization.getActiveMemberRole({
    query: {
        organizationId: "org-id",
        organizationSlug: "org-slug",
    },
});

Proposal B (Cleaner Solution)
Since the proposed behavior decouples the function from the active organization, you could alternatively introduce a .getMembership() function, which could also contain the roles and permissions for the signed in user.

const { data: membership, error } = await authClient.organization.getMembership({
    query: {
        organizationId: "org-id",
        organizationSlug: "org-slug",
    },
});

const { user, organization, roles, permissions } = membership

This approach would also allow for better client side permission checks. On mobile, it's not always preferred to check permissions by fetching the backend each time.

Describe alternatives you've considered

I have considered creating a rest api proxy for the organization plugin, calling server functions with the organizationId as query parameter. For getting the membership (roles and permissions) of a user for a specific organization, I wrote a custom database query and created a custom endpoint: /organizations/:organizationId/membership. This introduced many challenges regarding type-safe error handling on the web client, since I couldn't use the authClient with the organization plugin anymore.

Additional context

No response

Originally created by @casvandergun on GitHub (Oct 22, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### Is your feature request related to a problem? Please describe. I’m using better-auth on my backend to serve both a web app and a mobile app. I’m running into issues fetching membership and roles because of the reliance on the active organization stored on the session object. Currently, I believe it is only possible to access the membership and roles of the active organization, not from any other organization the signed in user is part of. For a mobile app, where there might be connectivity issues, I don't want to rely on setting the active organization first, before fetching the membership and roles. A user might want to switch organizations when offline, causing the active organization on the backend to be out of drift. In general, I think this project would benefit from better stateless support for implementations where the active organization state is managed on the frontend. ### Describe the solution you'd like I believe the entire organization plugin should be allowed to work without requiring the active organization to be set on the backend, so in a 100% stateless manner. **Proposal A (Minimal Change)** I'm not familiar with the entire API surface, so I might be missing something, but I believe adding organizationId and organizationSlug as optional query parameters to at least the `.getActiveMember()` and `.getActiveMemberRole()` functions should solve the problem. If no query parameters are passed, it could still default to the active organization. ``` const { data: member, error } = await authClient.organization.getActiveMember({ query: { organizationId: "org-id", organizationSlug: "org-slug", }, }); const { data: roles, error } = await authClient.organization.getActiveMemberRole({ query: { organizationId: "org-id", organizationSlug: "org-slug", }, }); ``` **Proposal B (Cleaner Solution)** Since the proposed behavior decouples the function from the active organization, you could alternatively introduce a `.getMembership()` function, which could also contain the roles and permissions for the signed in user. ``` const { data: membership, error } = await authClient.organization.getMembership({ query: { organizationId: "org-id", organizationSlug: "org-slug", }, }); const { user, organization, roles, permissions } = membership ``` This approach would also allow for better client side permission checks. On mobile, it's not always preferred to check permissions by fetching the backend each time. ### Describe alternatives you've considered I have considered creating a rest api proxy for the organization plugin, calling server functions with the organizationId as query parameter. For getting the membership (roles and permissions) of a user for a specific organization, I wrote a custom database query and created a custom endpoint: `/organizations/:organizationId/membership`. This introduced many challenges regarding type-safe error handling on the web client, since I couldn't use the authClient with the organization plugin anymore. ### Additional context _No response_
GiteaMirror added the enhancementplugin labels 2026-03-13 09:32:29 -05:00
Author
Owner

@himself65 commented on GitHub (Oct 22, 2025):

We are working on stateless session management right now.

Does it sound good if you put some org data into a session cookie?

@himself65 commented on GitHub (Oct 22, 2025): We are working on stateless session management right now. Does it sound good if you put some org data into a session cookie?
Author
Owner

@casvandergun commented on GitHub (Oct 22, 2025):

Hi, thanks for your reply!

Hmm, I don't think this would solve my problem, as it would still only allow for a single implicit active organization.

I want to be able to get the membership of the signed in user for an explicit organization, independent of any server or cookie state.

I also think being able to run requests for different organizations in parallel is important here. This matters for pre-fetching and pre-rendering (React Activity) components for organizations other than the active organization, and mobile development in general.

A cookie helps make sessions stateless on the server, but it still encodes a single implicit organization and requires a round-trip to the server in order to change. For me, that’s the core limitation.

Finally, given your suggestion, "activeOrganizationStrategy" with values "database"|"cookie"|"none" could be a configuration option for the organization plugin, resulting in a different database schema and/or cookie payload.

@casvandergun commented on GitHub (Oct 22, 2025): Hi, thanks for your reply! Hmm, I don't think this would solve my problem, as it would still only allow for a single implicit active organization. I want to be able to get the membership of the signed in user for an explicit organization, independent of any server or cookie state. I also think being able to run requests for different organizations in parallel is important here. This matters for pre-fetching and pre-rendering (React Activity) components for organizations other than the active organization, and mobile development in general. A cookie helps make sessions stateless on the server, but it still encodes a single implicit organization and requires a round-trip to the server in order to change. For me, that’s the core limitation. Finally, given your suggestion, "activeOrganizationStrategy" with values "database"|"cookie"|"none" could be a configuration option for the organization plugin, resulting in a different database schema and/or cookie payload.
Author
Owner

@Bekacru commented on GitHub (Oct 27, 2025):

You can already do this - just ignore the active org and always pass the organizationId for all organization related endpoints

@Bekacru commented on GitHub (Oct 27, 2025): You can already do this - just ignore the active org and always pass the `organizationId` for all organization related endpoints
Author
Owner

@Bekacru commented on GitHub (Oct 27, 2025):

We're working making activeOrganizationId optional field and having more guide on how to manage active org without database state

@Bekacru commented on GitHub (Oct 27, 2025): We're working making `activeOrganizationId` optional field and having more guide on how to manage active org without database state
Author
Owner

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

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

Issue Summary:

  • You requested fully stateless backend support for the organization plugin to avoid relying on an active organization stored in session.
  • You proposed adding optional organizationId/organizationSlug parameters or a new getMembership() function for explicit organization membership retrieval.
  • The team clarified that passing organizationId directly to endpoints already supports stateless usage.
  • Work is ongoing to make activeOrganizationId optional and provide guidance for managing active organization state without server or cookie state.

Next Steps:

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

Thanks for your understanding and contribution!

@dosubot[bot] commented on GitHub (Jan 26, 2026): Hi, @casvandergun. 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 requested fully stateless backend support for the organization plugin to avoid relying on an active organization stored in session. - You proposed adding optional organizationId/organizationSlug parameters or a new getMembership() function for explicit organization membership retrieval. - The team clarified that passing organizationId directly to endpoints already supports stateless usage. - Work is ongoing to make activeOrganizationId optional and provide guidance for managing active organization state without server or cookie state. **Next Steps:** - Please let me know if this issue is still relevant to the latest version of better-auth by commenting here. - If I don’t hear back within 7 days, this issue will be automatically closed. Thanks 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#2184