[GH-ISSUE #7719] TypeScript type prevents custom role assignment in SSO organization provisioning #10883

Closed
opened 2026-04-13 07:15:33 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @PascalCompiles on GitHub (Jan 31, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/7719

Description

Custom roles are supported at the organization level using the Organization plugin, as documented here:
https://www.better-auth.com/docs/plugins/organization

The SSO plugin also documents organization provisioning with custom roles:
https://www.better-auth.com/docs/plugins/sso#advanced-organization-provisioning-with-custom-roles

However, the current TypeScript types in the SSO plugin only allow the default roles ("member" and "admin"), which prevents assigning custom roles.

Details

In the Organization plugin, a role is defined as arbitrary strings:

// better-auth/packages/better-auth/src/plugins/organization/schema.ts
role: z.string()

However in the SSO plugin:

// packages/sso/src/linking/org-assignment.ts
interface OrganizationProvisioningOptions {
  ...
  getRole?: (data: {...}) => Promise<"member" | "admin">
}

This restricts the getRole callback (used to assign roles) to only the default roles, even though the underlying system supports custom roles.

Impact

This makes it impossible (from a type-safety perspective) to use custom organization roles with SSO, despite the documentation suggesting that this is supported.

Proposed Solution

Change the return type of getRole to allow arbitrary strings, e.g.

// packages/sso/src/linking/org-assignment.ts
interface OrganizationProvisioningOptions {
  ...
  getRole?: (data: {...}) => Promise<string>
}

or potentially stronger typing may be desired while allowing the use of custom roles.

I’m happy to open a PR if this approach makes sense to the maintainers.

Originally created by @PascalCompiles on GitHub (Jan 31, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/7719 ## Description Custom roles are supported at the organization level using the Organization plugin, as documented here: https://www.better-auth.com/docs/plugins/organization The SSO plugin also documents organization provisioning with custom roles: https://www.better-auth.com/docs/plugins/sso#advanced-organization-provisioning-with-custom-roles However, the current TypeScript types in the SSO plugin only allow the default roles ("member" and "admin"), which prevents assigning custom roles. ## Details In the Organization plugin, a role is defined as arbitrary strings: ``` // better-auth/packages/better-auth/src/plugins/organization/schema.ts role: z.string() ``` However in the SSO plugin: ``` // packages/sso/src/linking/org-assignment.ts interface OrganizationProvisioningOptions { ... getRole?: (data: {...}) => Promise<"member" | "admin"> } ``` This restricts the `getRole` callback (used to assign roles) to only the default roles, even though the underlying system supports custom roles. ## Impact This makes it impossible (from a type-safety perspective) to use custom organization roles with SSO, despite the documentation suggesting that this is supported. ## Proposed Solution Change the return type of `getRole` to allow arbitrary strings, e.g. ``` // packages/sso/src/linking/org-assignment.ts interface OrganizationProvisioningOptions { ... getRole?: (data: {...}) => Promise<string> } ``` or potentially stronger typing may be desired while allowing the use of custom roles. I’m happy to open a PR if this approach makes sense to the maintainers.
GiteaMirror added the enhancementlocked labels 2026-04-13 07:15:33 -05:00
Author
Owner

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

It seems there is an issue with the current TypeScript types in the SSO plugin, which restricts the assigned roles to only the defaults of "member" and "admin." This limitation contradicts the documentation suggesting that custom roles should be supported. Your proposed solution to change the return type of the getRole function to allow for arbitrary strings is reasonable.

If you're considering opening a PR with this approach, it would be helpful to mention it in the GitHub issues where similar discussions are happening. Currently, there are ongoing discussions related to enhancements for role management in the Organization plugin that might be relevant for your proposal [1]. You could reference those discussions in your PR to provide context.

What other features or improvements do you think would enhance the authentication experience with Better Auth?

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

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3827845180 --> @better-auth-agent[bot] commented on GitHub (Jan 31, 2026): It seems there is an issue with the current TypeScript types in the SSO plugin, which restricts the assigned roles to only the defaults of "member" and "admin." This limitation contradicts the documentation suggesting that custom roles should be supported. Your proposed solution to change the return type of the `getRole` function to allow for arbitrary strings is reasonable. If you're considering opening a PR with this approach, it would be helpful to mention it in the GitHub issues where similar discussions are happening. Currently, there are ongoing discussions related to enhancements for role management in the Organization plugin that might be relevant for your proposal [[1]](https://github.com/better-auth/better-auth/issues/6772). You could reference those discussions in your PR to provide context. What other features or improvements do you think would enhance the authentication experience with 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 31, 2026):

Hi @PascalCompiles! I'm Dosu and I’m helping the better-auth team.

You're correct: the SSO plugin currently restricts the getRole callback to only return "member" or "admin" due to its TypeScript type, even though the Organization plugin and the underlying system support arbitrary string roles at runtime. The value returned by getRole is written directly to the member record without further checks, so this restriction is purely at the type level and not enforced at runtime. Changing the return type to Promise (and widening defaultRole to string) would align the SSO plugin's types with the actual flexibility of the Organization plugin and would not break existing functionality. This approach matches how custom roles are handled elsewhere in the codebase and is consistent with the documentation and schema definitions for organization roles as arbitrary strings citation.

If you want to propose a PR, updating both getRole and defaultRole to accept string is the right direction. There are no other parts of the SSO plugin that depend on getRole being limited to the default roles citation. For best results, ensure your runtime logic still validates roles as needed, since type safety for dynamic roles is enforced at runtime by Zod schemas in the Organization plugin citation.

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

<!-- gh-comment-id:3827848542 --> @dosubot[bot] commented on GitHub (Jan 31, 2026): <!-- Greeting --> Hi @PascalCompiles! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> You're correct: the SSO plugin currently restricts the getRole callback to only return "member" or "admin" due to its TypeScript type, even though the Organization plugin and the underlying system support arbitrary string roles at runtime. The value returned by getRole is written directly to the member record without further checks, so this restriction is purely at the type level and not enforced at runtime. Changing the return type to Promise<string> (and widening defaultRole to string) would align the SSO plugin's types with the actual flexibility of the Organization plugin and would not break existing functionality. This approach matches how custom roles are handled elsewhere in the codebase and is consistent with the documentation and schema definitions for organization roles as arbitrary strings [citation](https://github.com/better-auth/better-auth/blob/583f12fb7db38681ee882d219ce3895faa4a6976/packages/sso/src/linking/org-assignment.ts#L6-L184). If you want to propose a PR, updating both getRole and defaultRole to accept string is the right direction. There are no other parts of the SSO plugin that depend on getRole being limited to the default roles [citation](https://github.com/better-auth/better-auth/pull/6652). For best results, ensure your runtime logic still validates roles as needed, since type safety for dynamic roles is enforced at runtime by Zod schemas in the Organization plugin [citation](https://github.com/better-auth/better-auth/blob/583f12fb7db38681ee882d219ce3895faa4a6976/packages/better-auth/src/plugins/organization/schema.ts#L35-L380). <!-- 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/38f2aafe-9583-49c4-9954-bb7722ddde6c?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/38f2aafe-9583-49c4-9954-bb7722ddde6c?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/38f2aafe-9583-49c4-9954-bb7722ddde6c?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/38f2aafe-9583-49c4-9954-bb7722ddde6c?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/38f2aafe-9583-49c4-9954-bb7722ddde6c?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/38f2aafe-9583-49c4-9954-bb7722ddde6c?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/38f2aafe-9583-49c4-9954-bb7722ddde6c?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=You%27re%20correct%3A%20the%20SSO%20plugin%20currently%20restricts%20the%20getRole%20callback%20to%20only%20return%20%22member%22%20or%20%22admin%22%20due%20to%20its%20TypeScript%20type%2C%20even%20though%20the%20Organization%20plugin%20and%20the%20underlying%20system%20support%20arbitrary%20string%20roles%20at%20runtime.%20The%20value%20returned%20by%20getRole%20is%20written%20directly%20to%20the%20member%20record%20without%20further%20checks%2C%20so%20this%20restriction%20is%20purely%20at%20the%20type%20level%20and%20not%20enforced%20at%20runtime.%20Changing%20the%20return%20type%20to%20Promise%3Cstring%3E%20%28and%20widening%20defaultRole%20to%20string%29%20would%20align%20the%20SSO%20plugin%27s%20types%20with%20the%20actual%20flexibility%20of%20the%20Organization%20plugin%20and%20would%20not%20break%20existing%20functionality.%20This%20approach%20matches%20how%20custom%20roles%20are%20handled%20elsewhere%20in%20the%20codebase%20and%20is%20consistent%20with%20the%20documentation%20and%20schema%20definitions%20for%20organization%20roles%20as%20arbitrary%20strings%C2%A0%5Bcitation%5D%28https%3A//github.com/better-auth/better-auth/blob/583f12fb7db38681ee882d219ce3895faa4a6976/packages/sso/src/linking/org-assignment.ts%23L6-L184%29.%0A%0AIf%20you%20want%20to%20propose%20a%20PR%2C%20updating%20both%20getRole%20and%20defaultRole%20to%20accept%20string%20is%20the%20right%20direction.%20There%20are%20no%20other%20parts%20of%20the%20SSO%20plugin%20that%20depend%20on%20getRole%20being%20limited%20to%20the%20default%20roles%C2%A0%5Bcitation%5D%28https%3A//github.com/better-auth/better-auth/pull/6652%29.%20For%20best%20results%2C%20ensure%20your%20runtime%20logic%20still%20validates%20roles%20as%20needed%2C%20since%20type%20safety%20for%20dynamic%20roles%20is%20enforced%20at%20runtime%20by%20Zod%20schemas%20in%20the%20Organization%20plugin%C2%A0%5Bcitation%5D%28https%3A//github.com/better-auth/better-auth/blob/583f12fb7db38681ee882d219ce3895faa4a6976/packages/better-auth/src/plugins/organization/schema.ts%23L35-L380%29.)&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/7719)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#10883