[GH-ISSUE #7759] SSO Provider CASCADE DELETE on userId removes org-wide SSO when admin is deleted #28217

Closed
opened 2026-04-17 19:40:22 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @robingenz on GitHub (Feb 2, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/7759

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Set up Better Auth with the SSO plugin and organization plugin enabled
  2. Create an organization and add members to it
  3. Register an SSO provider for the organization as an admin user (this sets ssoProvider.userId to the admin's ID and ssoProvider.organizationId to the org ID)
  4. Have organization members successfully authenticate via the SSO provider
  5. Delete the admin user who registered the SSO provider

Expected: Organization members can still use SSO since organizationId is set
Actual: Since the userId field is required and has ON DELETE CASCADE, deleting the admin user deletes the SSO provider, breaking SSO for all organization members.

Current vs. Expected behavior

Current behavior:

The SSO provider schema defines userId with a foreign key that cascades on delete:

// From packages/sso/src/index.ts - schema definition
userId: {
  type: "string",
  references: {
    model: "user",
    field: "id",
  },
  // This generates: ON DELETE CASCADE by default
}

When implementing this schema, the default behavior is ON DELETE CASCADE on userId. This causes:

  1. Admin creates SSO provider for organization → userId = admin-id, organizationId = org-id
  2. Organization members successfully use SSO
  3. Admin account deleted → SSO provider CASCADE deleted
  4. All organization members lose SSO access

Expected behavior:

SSO providers should handle two distinct use cases differently:

  1. Personal SSO (organizationId is NULL): Deleting the user should delete their personal SSO config (current behavior is correct)
  2. Organization SSO (organizationId is set): Deleting the user who registered it should NOT delete org-wide SSO (current behavior is incorrect)

The userId field tracks who registered the provider (audit/ownership), while organizationId determines who can use it. For organization SSO, the configuration should survive admin deletion.

I've also created a discussion but without any feedback from the community so far: https://github.com/better-auth/better-auth/discussions/7751.

What version of Better Auth are you using?

1.4.17

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 24.6.0",
    "cpuCount": 10,
    "cpuModel": "Apple M1 Pro",
    "totalMemory": "32.00 GB"
  },
  "node": {
    "version": "v22.21.1",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "10.9.4"
  },
  "betterAuth": {
    "version": "1.4.17"
  }
}

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

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth";
import { organization } from "better-auth/plugins";
import { sso } from "@better-auth/sso";

export const auth = betterAuth({
  database: {
    provider: "postgres",
    url: process.env.DATABASE_URL
  },
  plugins: [
    organization(),
    sso({
      // SSO configuration
    })
  ]
});

Additional context

No response

Originally created by @robingenz on GitHub (Feb 2, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/7759 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Set up Better Auth with the SSO plugin and organization plugin enabled 2. Create an organization and add members to it 3. Register an SSO provider for the organization as an admin user (this sets `ssoProvider.userId` to the admin's ID and `ssoProvider.organizationId` to the org ID) 4. Have organization members successfully authenticate via the SSO provider 5. Delete the admin user who registered the SSO provider **Expected:** Organization members can still use SSO since `organizationId` is set **Actual:** Since the `userId` field is required and has `ON DELETE CASCADE`, deleting the admin user deletes the SSO provider, breaking SSO for all organization members. ### Current vs. Expected behavior **Current behavior:** The SSO provider schema defines `userId` with a foreign key that cascades on delete: ```typescript // From packages/sso/src/index.ts - schema definition userId: { type: "string", references: { model: "user", field: "id", }, // This generates: ON DELETE CASCADE by default } ``` When implementing this schema, the default behavior is `ON DELETE CASCADE` on `userId`. This causes: 1. Admin creates SSO provider for organization → `userId = admin-id`, `organizationId = org-id` 2. Organization members successfully use SSO 3. Admin account deleted → SSO provider CASCADE deleted 4. All organization members lose SSO access **Expected behavior:** SSO providers should handle two distinct use cases differently: 1. **Personal SSO** (`organizationId` is NULL): Deleting the user should delete their personal SSO config ✅ (current behavior is correct) 2. **Organization SSO** (`organizationId` is set): Deleting the user who registered it should NOT delete org-wide SSO ❌ (current behavior is incorrect) The `userId` field tracks *who registered* the provider (audit/ownership), while `organizationId` determines *who can use it*. For organization SSO, the configuration should survive admin deletion. I've also created a discussion but without any feedback from the community so far: https://github.com/better-auth/better-auth/discussions/7751. ### What version of Better Auth are you using? 1.4.17 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 24.6.0", "cpuCount": 10, "cpuModel": "Apple M1 Pro", "totalMemory": "32.00 GB" }, "node": { "version": "v22.21.1", "env": "development" }, "packageManager": { "name": "npm", "version": "10.9.4" }, "betterAuth": { "version": "1.4.17" } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth"; import { organization } from "better-auth/plugins"; import { sso } from "@better-auth/sso"; export const auth = betterAuth({ database: { provider: "postgres", url: process.env.DATABASE_URL }, plugins: [ organization(), sso({ // SSO configuration }) ] }); ``` ### Additional context _No response_
GiteaMirror added the lockedenhancement labels 2026-04-17 19:40:22 -05:00
Author
Owner

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

It seems like you've encountered an issue where the SSO provider linked to an organization is deleted when the admin user who registered it is deleted. You’re correct that this behavior is due to the ON DELETE CASCADE setting on the userId field in the SSO provider schema. The expectation is that organization-wide SSO configurations should not be deleted when an admin user is removed, which the current implementation does not support.

To address this, there might be an opportunity to request a change in the schema so that the behavior differentiates between personal SSO and organization SSO. The current implementation deletes the org SSO provider when the related admin user is removed, which is not ideal for accessibility of organization members [1].

As for next steps, you may consider raising this concern in the active discussion you created on GitHub, if it hasn't gained traction yet, or tag the Better Auth team members, Beka and Max, directly in the discussion for their insights.

Have you had any responses in the discussion regarding this matter?

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

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3834407210 --> @better-auth-agent[bot] commented on GitHub (Feb 2, 2026): It seems like you've encountered an issue where the SSO provider linked to an organization is deleted when the admin user who registered it is deleted. You’re correct that this behavior is due to the `ON DELETE CASCADE` setting on the `userId` field in the SSO provider schema. The expectation is that organization-wide SSO configurations should not be deleted when an admin user is removed, which the current implementation does not support. To address this, there might be an opportunity to request a change in the schema so that the behavior differentiates between personal SSO and organization SSO. The current implementation deletes the org SSO provider when the related admin user is removed, which is not ideal for accessibility of organization members [[1]](https://github.com/better-auth/better-auth/pull/7140). As for next steps, you may consider raising this concern in the active discussion you created on GitHub, if it hasn't gained traction yet, or tag the Better Auth team members, Beka and Max, directly in the discussion for their insights. Have you had any responses in the discussion regarding this matter? _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 (Feb 2, 2026):

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

This is a known schema issue in Better Auth v1.4.17: the SSO provider's userId foreign key defaults to ON DELETE CASCADE, so deleting the user who registered an org-wide SSO provider also deletes the provider, breaking SSO for the whole org. This isn't configurable in v1.4.17 and there's no built-in logic to distinguish personal from org SSO at the database level—it's a side effect of the schema design and migration defaults (source).

A fix was merged after v1.4.17 in PR #4973: the userId field is now optional and uses ON DELETE SET NULL, so deleting the registering user just nulls userId and preserves the SSO provider for the org. Tests confirm this works as expected (source).

If you can't upgrade, you can manually fix this by altering your ssoProvider table: make userId nullable and change the foreign key to ON DELETE SET NULL. This requires a DB migration and possibly updating your application logic to handle SSO providers with a null userId. There’s no built-in Better Auth config for this in v1.4.17, so it’s a manual change (source).

If you want to see the exact schema and test changes, check PR #4973.

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:3834432491 --> @dosubot[bot] commented on GitHub (Feb 2, 2026): <!-- Greeting --> Hi @robingenz! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> This is a known schema issue in Better Auth v1.4.17: the SSO provider's userId foreign key defaults to ON DELETE CASCADE, so deleting the user who registered an org-wide SSO provider also deletes the provider, breaking SSO for the whole org. This isn't configurable in v1.4.17 and there's no built-in logic to distinguish personal from org SSO at the database level—it's a side effect of the schema design and migration defaults [(source)](https://github.com/better-auth/better-auth/issues/4971#issuecomment-3348313930). A fix was merged after v1.4.17 in [PR #4973](https://github.com/better-auth/better-auth/pull/4973): the userId field is now optional and uses ON DELETE SET NULL, so deleting the registering user just nulls userId and preserves the SSO provider for the org. Tests confirm this works as expected [(source)](https://github.com/better-auth/better-auth/pull/4973). If you can't upgrade, you can manually fix this by altering your ssoProvider table: make userId nullable and change the foreign key to ON DELETE SET NULL. This requires a DB migration and possibly updating your application logic to handle SSO providers with a null userId. There’s no built-in Better Auth config for this in v1.4.17, so it’s a manual change [(source)](https://github.com/better-auth/better-auth/issues/4971#issuecomment-3348313930). If you want to see the exact schema and test changes, check [PR #4973](https://github.com/better-auth/better-auth/pull/4973). <!-- 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/c5b08cfc-c7ce-44ec-b624-9c0a70e3743f?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/c5b08cfc-c7ce-44ec-b624-9c0a70e3743f?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/c5b08cfc-c7ce-44ec-b624-9c0a70e3743f?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/c5b08cfc-c7ce-44ec-b624-9c0a70e3743f?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/c5b08cfc-c7ce-44ec-b624-9c0a70e3743f?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/c5b08cfc-c7ce-44ec-b624-9c0a70e3743f?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/c5b08cfc-c7ce-44ec-b624-9c0a70e3743f?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%20is%20a%20known%20schema%20issue%20in%20Better%20Auth%20v1.4.17%3A%20the%20SSO%20provider%27s%20userId%20foreign%20key%20defaults%20to%20ON%20DELETE%20CASCADE%2C%20so%20deleting%20the%20user%20who%20registered%20an%20org-wide%20SSO%20provider%20also%20deletes%20the%20provider%2C%20breaking%20SSO%20for%20the%20whole%20org.%20This%20isn%27t%20configurable%20in%20v1.4.17%20and%20there%27s%20no%20built-in%20logic%20to%20distinguish%20personal%20from%20org%20SSO%20at%20the%20database%20level%E2%80%94it%27s%20a%20side%20effect%20of%20the%20schema%20design%20and%20migration%20defaults%20%5B%28source%29%5D%28https%3A//github.com/better-auth/better-auth/issues/4971%23issuecomment-3348313930%29.%0A%0AA%20fix%20was%20merged%20after%20v1.4.17%20in%20%5BPR%20%234973%5D%28https%3A//github.com/better-auth/better-auth/pull/4973%29%3A%20the%20userId%20field%20is%20now%20optional%20and%20uses%20ON%20DELETE%20SET%20NULL%2C%20so%20deleting%20the%20registering%20user%20just%20nulls%20userId%20and%20preserves%20the%20SSO%20provider%20for%20the%20org.%20Tests%20confirm%20this%20works%20as%20expected%20%5B%28source%29%5D%28https%3A//github.com/better-auth/better-auth/pull/4973%29.%0A%0AIf%20you%20can%27t%20upgrade%2C%20you%20can%20manually%20fix%20this%20by%20altering%20your%20ssoProvider%20table%3A%20make%20userId%20nullable%20and%20change%20the%20foreign%20key%20to%20ON%20DELETE%20SET%20NULL.%20This%20requires%20a%20DB%20migration%20and%20possibly%20updating%20your%20application%20logic%20to%20handle%20SSO%20providers%20with%20a%20null%20userId.%20There%E2%80%99s%20no%20built-in%20Better%20Auth%20config%20for%20this%20in%20v1.4.17%2C%20so%20it%E2%80%99s%20a%20manual%20change%20%5B%28source%29%5D%28https%3A//github.com/better-auth/better-auth/issues/4971%23issuecomment-3348313930%29.%0A%0AIf%20you%20want%20to%20see%20the%20exact%20schema%20and%20test%20changes%2C%20check%20%5BPR%20%234973%5D%28https%3A//github.com/better-auth/better-auth/pull/4973%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/7759)
Author
Owner

@robingenz commented on GitHub (Feb 2, 2026):

Oh wow. Closed by #4973.

<!-- gh-comment-id:3834550601 --> @robingenz commented on GitHub (Feb 2, 2026): Oh wow. Closed by #4973.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#28217