SSO provisionUser is called on every sign-in, not just for new users #2844

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

Originally created by @robingenz on GitHub (Feb 8, 2026).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Configure the SSO plugin with a provisionUser callback:
    sso({
      provisionUser: async ({ user, userInfo, token, provider }) => {
        console.log("provisionUser called for", user.email);
      },
    })
    
  2. Sign in via SSO (OIDC or SAML) with a new user — provisionUser is called (expected).
  3. Sign in again with the same user — provisionUser is called again (unexpected).

Current vs. Expected behavior

Current behavior: provisionUser is called on every SSO sign-in, regardless of whether the user already exists. This can be confirmed in packages/sso/src/routes/sso.ts at lines 1668, 2241, and 2700 — all three call sites invoke provisionUser unconditionally after handleOAuthUserInfo returns.

Expected behavior: According to the documentation: "When a user is authenticated, if the user does not exist, the user will be provisioned using the provisionUser function."provisionUser should only be called when the user is newly created.

handleOAuthUserInfo (in packages/better-auth/src/oauth2/link-account.ts) already returns an isRegister flag that is true only when the user didn't previously exist. This flag is used for redirect logic (line 1698) but is not checked before calling provisionUser.

The fix would be to gate provisionUser on isRegister, e.g.:

if (options?.provisionUser && linked.isRegister) {

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: Wed Nov  5 21:33:58 PST 2025; root:xnu-11417.140.69.705.2~1/RELEASE_ARM64_T6000",
    "release": "24.6.0",
    "cpuCount": 10,
    "cpuModel": "Apple M1 Pro",
    "totalMemory": "32.00 GB",
    "freeMemory": "0.21 GB"
  },
  "node": {
    "version": "v22.22.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "10.9.4"
  },
  "frameworks": [
    {
      "name": "hono",
      "version": "4.6.12"
    }
  ],
  "databases": [
    {
      "name": "postgres",
      "version": "3.4.7"
    },
    {
      "name": "drizzle",
      "version": "0.44.2"
    }
  ],
  "betterAuth": {
    "version": "1.4.17",
    "config": null
  }
}

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

Backend

Auth config (if applicable)

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

export const auth = betterAuth({
  plugins: [
    sso({
      provisionUser: async ({ user, userInfo, token, provider }) => {
        // This is called on every sign-in, not just for new users
      },
    }),
  ],
});

Additional context

There is a contradiction in the docs: the main description says provisionUser is only for new users, but the "Best Practices" section says "Make sure your provisioning functions can be safely run multiple times" — implying it may be called repeatedly. If the every-sign-in behavior is intentional, the initial description and the function name are misleading and the docs should be updated. If it's a bug, the three call sites in packages/sso/src/routes/sso.ts need to be gated on isRegister.

Originally created by @robingenz on GitHub (Feb 8, 2026). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Configure the SSO plugin with a `provisionUser` callback: ```ts sso({ provisionUser: async ({ user, userInfo, token, provider }) => { console.log("provisionUser called for", user.email); }, }) ``` 2. Sign in via SSO (OIDC or SAML) with a new user — `provisionUser` is called (expected). 3. Sign in again with the same user — `provisionUser` is called again (unexpected). ### Current vs. Expected behavior **Current behavior:** `provisionUser` is called on **every** SSO sign-in, regardless of whether the user already exists. This can be confirmed in `packages/sso/src/routes/sso.ts` at lines 1668, 2241, and 2700 — all three call sites invoke `provisionUser` unconditionally after `handleOAuthUserInfo` returns. **Expected behavior:** According to the [documentation](https://www.better-auth.com/docs/plugins/sso): *"When a user is authenticated, if the user does not exist, the user will be provisioned using the `provisionUser` function."* — `provisionUser` should only be called when the user is newly created. `handleOAuthUserInfo` (in `packages/better-auth/src/oauth2/link-account.ts`) already returns an `isRegister` flag that is `true` only when the user didn't previously exist. This flag is used for redirect logic (line 1698) but is not checked before calling `provisionUser`. The fix would be to gate `provisionUser` on `isRegister`, e.g.: ```ts if (options?.provisionUser && linked.isRegister) { ``` ### 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: Wed Nov 5 21:33:58 PST 2025; root:xnu-11417.140.69.705.2~1/RELEASE_ARM64_T6000", "release": "24.6.0", "cpuCount": 10, "cpuModel": "Apple M1 Pro", "totalMemory": "32.00 GB", "freeMemory": "0.21 GB" }, "node": { "version": "v22.22.0", "env": "development" }, "packageManager": { "name": "npm", "version": "10.9.4" }, "frameworks": [ { "name": "hono", "version": "4.6.12" } ], "databases": [ { "name": "postgres", "version": "3.4.7" }, { "name": "drizzle", "version": "0.44.2" } ], "betterAuth": { "version": "1.4.17", "config": null } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth"; import { sso } from "@better-auth/sso"; export const auth = betterAuth({ plugins: [ sso({ provisionUser: async ({ user, userInfo, token, provider }) => { // This is called on every sign-in, not just for new users }, }), ], }); ``` ### Additional context There is a contradiction in the docs: the main description says `provisionUser` is only for new users, but the "Best Practices" section says *"Make sure your provisioning functions can be safely run multiple times"* — implying it may be called repeatedly. If the every-sign-in behavior is intentional, the initial description and the function name are misleading and the docs should be updated. If it's a bug, the three call sites in `packages/sso/src/routes/sso.ts` need to be gated on `isRegister`.
GiteaMirror added the enhancement label 2026-03-13 10:23:11 -05:00
Author
Owner

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

It appears that you are experiencing an issue where the provisionUser function is called on every SSO sign-in, regardless of whether the user exists or is new. This contradicts the expectation that provisionUser should only be triggered for new users. According to the documentation, this behavior should be corrected as it suggests that provisionUser is intended for provisioning new users only.

The suggested fix would be to modify the call to the provisionUser function to check the isRegister flag before executing it, ensuring that it is only called when a new user is being created. You can implement it like this:

if (options?.provisionUser && linked.isRegister) {

If this behavior is indeed unintentional, it may be classified as a bug, and it could require an update to the codebase to gate the invocation based on the registration status.

You also mentioned that there is a contradiction in the documentation. It may be useful to bring this to the attention of the team, especially if it leads to confusion among users.

If you have further questions or need extra assistance with this issue, consider tagging @bekacru or @ping__ for specific insights. What other SSO configurations are you utilizing, and how are they working for you?

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 (Feb 8, 2026): It appears that you are experiencing an issue where the `provisionUser` function is called on every SSO sign-in, regardless of whether the user exists or is new. This contradicts the expectation that `provisionUser` should only be triggered for new users. According to the documentation, this behavior should be corrected as it suggests that `provisionUser` is intended for provisioning new users only. The suggested fix would be to modify the call to the `provisionUser` function to check the `isRegister` flag before executing it, ensuring that it is only called when a new user is being created. You can implement it like this: ```typescript if (options?.provisionUser && linked.isRegister) { ``` If this behavior is indeed unintentional, it may be classified as a bug, and it could require an update to the codebase to gate the invocation based on the registration status. You also mentioned that there is a contradiction in the documentation. It may be useful to bring this to the attention of the team, especially if it leads to confusion among users. If you have further questions or need extra assistance with this issue, consider tagging @bekacru or @ping__ for specific insights. What other SSO configurations are you utilizing, and how are they working for you? _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

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

@Bekacru That's likely a bug (either in the backend or in the documentation). There definitely needs to be a way to identify a user as a new user when using SSO.

@robingenz commented on GitHub (Feb 8, 2026): @Bekacru That's likely a bug (either in the backend or in the documentation). There definitely needs to be a way to identify a user as a new user when using SSO.
Author
Owner

@bytaesu commented on GitHub (Feb 8, 2026):

Hi @robingenz, I'm checking this 🧐

@bytaesu commented on GitHub (Feb 8, 2026): Hi @robingenz, I'm checking this 🧐
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2844