[GH-ISSUE #8630] [sso plugin] provisionUser with OIDC only seems to run on register #11147

Closed
opened 2026-04-13 07:30:42 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @formatlos on GitHub (Mar 16, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/8630

Originally assigned to: @gustavovalverde on GitHub.

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

When using the suggested provisionUser hook to store additional user profile data with OIDC, it seems that it's only getting called as long as the user doesn't exists yet.

Current vs. Expected behavior

If the user gets updated in the upstream IDP we are not able to update the profile information as the provisionUser hook is not getting called again.

According to the docs where it specifically says that the operation needs to be idempotent I would expect that the hook is always called no matter if it's a new user or an updated user.

What version of Better Auth are you using?

1.5.4

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 Max",
    "totalMemory": "64.00 GB",
    "freeMemory": "0.53 GB"
  },
  "node": {
    "version": "v22.14.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "10.9.2"
  },
  "frameworks": [
    {
      "name": "fastify",
      "version": "^5.5.0"
    }
  ],
  "databases": [
    {
      "name": "pg",
      "version": "^8.17.2"
    },
    {
      "name": "postgres",
      "version": "^3.4.8"
    },
    {
      "name": "@prisma/client",
      "version": "^6.18.0"
    },
    {
      "name": "kysely",
      "version": "^0.28.9"
    }
  ],
  "betterAuth": {
    "version": "^1.5.4"
    }
  }
}

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 @formatlos on GitHub (Mar 16, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/8630 Originally assigned to: @gustavovalverde on GitHub. ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce When using the suggested `provisionUser` hook to store additional user profile data with OIDC, it seems that it's only getting called as long as the user doesn't exists yet. ### Current vs. Expected behavior If the user gets updated in the upstream IDP we are not able to update the profile information as the `provisionUser` hook is not getting called again. According to the docs where it specifically says that the operation needs to be idempotent I would expect that the hook is always called no matter if it's a new user or an updated user. ### What version of Better Auth are you using? 1.5.4 ### 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 Max", "totalMemory": "64.00 GB", "freeMemory": "0.53 GB" }, "node": { "version": "v22.14.0", "env": "development" }, "packageManager": { "name": "npm", "version": "10.9.2" }, "frameworks": [ { "name": "fastify", "version": "^5.5.0" } ], "databases": [ { "name": "pg", "version": "^8.17.2" }, { "name": "postgres", "version": "^3.4.8" }, { "name": "@prisma/client", "version": "^6.18.0" }, { "name": "kysely", "version": "^0.28.9" } ], "betterAuth": { "version": "^1.5.4" } } } ``` ### 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 enterpriselockedidentitybug labels 2026-04-13 07:30:42 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Mar 16, 2026):

This is actually the intended behavior as of version 1.4.19. The provisionUser hook was changed to only run on initial registration, not on subsequent logins. Looking at the current OIDC callback implementation:

if (options?.provisionUser && linked.isRegister) {
    await options.provisionUser({ ... });
}

The isRegister check was intentionally added to prevent provisionUser from running on every login.

That said, your use case (syncing user profile updates from the upstream IDP) is valid. Here are your options:

Option 1: Use after hooks to detect returning users

You can use the isRegister flag in after hooks to update user data on every SSO login:

hooks: {
  after: createAuthMiddleware(async ctx => {
    const result = ctx.context.returned;
    if (result && 'isRegister' in result && !result.isRegister) {
      // Returning user - update their profile from IDP data
      await auth.api.updateUser({
        userId: result.user.id,
        update: { /* profile fields */ },
      });
    }
  })
}

Option 2: Open a feature request

The documentation's mention of "idempotent" operations does suggest the hook might have been intended to run on every login. Consider opening a feature request for an option like provisionUser.runOnEveryLogin: true or a separate syncUser hook for returning users.

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:4067267914 --> @dosubot[bot] commented on GitHub (Mar 16, 2026): <!-- Answer --> This is actually the **intended behavior** as of version 1.4.19. The `provisionUser` hook was [changed to only run on initial registration](https://github.com/better-auth/better-auth/pull/7870), not on subsequent logins. Looking at the [current OIDC callback implementation](https://github.com/better-auth/better-auth/blob/8f47015af223e5db9ff406f6ca8247f6b8dcd9fe/packages/sso/src/routes/sso.ts#L1763-L1770): ```typescript if (options?.provisionUser && linked.isRegister) { await options.provisionUser({ ... }); } ``` The `isRegister` check was intentionally added to prevent provisionUser from running on every login. That said, your use case (syncing user profile updates from the upstream IDP) is valid. Here are your options: **Option 1: Use after hooks to detect returning users** You can use the [`isRegister` flag in after hooks](https://github.com/better-auth/better-auth/issues/5428) to update user data on every SSO login: ```typescript hooks: { after: createAuthMiddleware(async ctx => { const result = ctx.context.returned; if (result && 'isRegister' in result && !result.isRegister) { // Returning user - update their profile from IDP data await auth.api.updateUser({ userId: result.user.id, update: { /* profile fields */ }, }); } }) } ``` **Option 2: Open a feature request** The documentation's mention of "idempotent" operations does suggest the hook might have been intended to run on every login. Consider opening a feature request for an option like `provisionUser.runOnEveryLogin: true` or a separate `syncUser` hook for returning users. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=brand-link).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/2f65c080-4e76-4a1d-967c-58114e650b4f?feedback_type=great_response&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/2f65c080-4e76-4a1d-967c-58114e650b4f?feedback_type=irrelevant_answer&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/2f65c080-4e76-4a1d-967c-58114e650b4f?feedback_type=incorrect_sources&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/2f65c080-4e76-4a1d-967c-58114e650b4f?feedback_type=too_verbose&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/2f65c080-4e76-4a1d-967c-58114e650b4f?feedback_type=hallucination&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/2f65c080-4e76-4a1d-967c-58114e650b4f?feedback_type=bug_report&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-bug_report) | [Other](https://app.dosu.dev/response-feedback/2f65c080-4e76-4a1d-967c-58114e650b4f?feedback_type=other&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-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&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=chat-badge)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20is%20actually%20the%20%2A%2Aintended%20behavior%2A%2A%20as%20of%20version%201.4.19.%20The%20%60provisionUser%60%20hook%20was%20%5Bchanged%20to%20only%20run%20on%20initial%20registration%5D%28https%3A//github.com/better-auth/better-auth/pull/7870%29%2C%20not%20on%20subsequent%20logins.%20Looking%20at%20the%20%5Bcurrent%20OIDC%20callback%20implementation%5D%28https%3A//github.com/better-auth/better-auth/blob/8f47015af223e5db9ff406f6ca8247f6b8dcd9fe/packages/sso/src/routes/sso.ts%23L1763-L1770%29%3A%0A%0A%60%60%60typescript%0Aif%20%28options%3F.provisionUser%20%26%26%20linked.isRegister%29%20%7B%0A%20%20%20%20await%20options.provisionUser%28%7B%20...%20%7D%29%3B%0A%7D%0A%60%60%60%0A%0AThe%20%60isRegister%60%20check%20was%20intentionally%20added%20to%20prevent%20provisionUser%20from%20running%20on%20every%20login.%0A%0AThat%20said%2C%20your%20use%20case%20%28syncing%20user%20profile%20updates%20from%20the%20upstream%20IDP%29%20is%20valid.%20Here%20are%20your%20options%3A%0A%0A%2A%2AOption%201%3A%20Use%20after%20hooks%20to%20detect%20returning%20users%2A%2A%0A%0AYou%20can%20use%20the%20%5B%60isRegister%60%20flag%20in%20after%20hooks%5D%28https%3A//github.com/better-auth/better-auth/issues/5428%29%20to%20update%20user%20data%20on%20every%20SSO%20login%3A%0A%0A%60%60%60typescript%0Ahooks%3A%20%7B%0A%20%20after%3A%20createAuthMiddleware%28async%20ctx%20%3D%3E%20%7B%0A%20%20%20%20const%20result%20%3D%20ctx.context.returned%3B%0A%20%20%20%20if%20%28result%20%26%26%20%27isRegister%27%20in%20result%20%26%26%20%21result.isRegister%29%20%7B%0A%20%20%20%20%20%20//%20Returning%20user%20-%20update%20their%20profile%20from%20IDP%20data%0A%20%20%20%20%20%20await%20auth.api.updateUser%28%7B%0A%20%20%20%20%20%20%20%20userId%3A%20result.user.id%2C%0A%20%20%20%20%20%20%20%20update%3A%20%7B%20/%2A%20profile%20fields%20%2A/%20%7D%2C%0A%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%7D%0A%20%20%7D%29%0A%7D%0A%60%60%60%0A%0A%2A%2AOption%202%3A%20Open%20a%20feature%20request%2A%2A%0A%0AThe%20documentation%27s%20mention%20of%20%22idempotent%22%20operations%20does%20suggest%20the%20hook%20might%20have%20been%20intended%20to%20run%20on%20every%20login.%20Consider%20opening%20a%20feature%20request%20for%20an%20option%20like%20%60provisionUser.runOnEveryLogin%3A%20true%60%20or%20a%20separate%20%60syncUser%60%20hook%20for%20returning%20users.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=join-discord)&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/8630)
Author
Owner

@formatlos commented on GitHub (Mar 16, 2026):

@dosu for SAML it seems to run always, I'd still consider this as a bug

<!-- gh-comment-id:4067482499 --> @formatlos commented on GitHub (Mar 16, 2026): @dosu for SAML it seems to run always, I'd still consider this as a bug
Author
Owner

@dosubot[bot] commented on GitHub (Mar 16, 2026):

You're right, this is a bug. Looking at the code, there's an inconsistency between OIDC and SAML:

OIDC (sso.ts L1763-1770) - correctly checks isRegister:

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

SAML (sso.ts L2412-2418 and L2928-2934) - missing the check:

if (options?.provisionUser) {

Both SAML callbacks (callbackSSOSAML and acsEndpoint) are missing the && linked.isRegister condition that was added to OIDC in PR #7870. The result variable from handleOAuthUserInfo should have the isRegister property available that could be used here.

This issue could be updated to specifically track the SAML inconsistency, or a new bug can be filed for it.

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:4067492433 --> @dosubot[bot] commented on GitHub (Mar 16, 2026): <!-- Answer --> You're right, this is a bug. Looking at the code, there's an inconsistency between OIDC and SAML: **OIDC** ([sso.ts L1763-1770](https://github.com/better-auth/better-auth/blob/8f47015af223e5db9ff406f6ca8247f6b8dcd9fe/packages/sso/src/routes/sso.ts#L1763-L1770)) - correctly checks `isRegister`: ```typescript if (options?.provisionUser && linked.isRegister) { ``` **SAML** ([sso.ts L2412-2418](https://github.com/better-auth/better-auth/blob/8f47015af223e5db9ff406f6ca8247f6b8dcd9fe/packages/sso/src/routes/sso.ts#L2412-L2418) and [L2928-2934](https://github.com/better-auth/better-auth/blob/8f47015af223e5db9ff406f6ca8247f6b8dcd9fe/packages/sso/src/routes/sso.ts#L2928-L2934)) - missing the check: ```typescript if (options?.provisionUser) { ``` Both SAML callbacks (`callbackSSOSAML` and `acsEndpoint`) are missing the `&& linked.isRegister` condition that was added to OIDC in PR #7870. The `result` variable from `handleOAuthUserInfo` should have the `isRegister` property available that could be used here. This issue could be updated to specifically track the SAML inconsistency, or a new bug can be filed for it. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=brand-link).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/4b6e6d86-05bb-46e2-8a53-5f487964b27b?feedback_type=great_response&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/4b6e6d86-05bb-46e2-8a53-5f487964b27b?feedback_type=irrelevant_answer&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/4b6e6d86-05bb-46e2-8a53-5f487964b27b?feedback_type=incorrect_sources&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/4b6e6d86-05bb-46e2-8a53-5f487964b27b?feedback_type=too_verbose&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/4b6e6d86-05bb-46e2-8a53-5f487964b27b?feedback_type=hallucination&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/4b6e6d86-05bb-46e2-8a53-5f487964b27b?feedback_type=bug_report&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-bug_report) | [Other](https://app.dosu.dev/response-feedback/4b6e6d86-05bb-46e2-8a53-5f487964b27b?feedback_type=other&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-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&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=chat-badge)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=You%27re%20right%2C%20this%20is%20a%20bug.%20Looking%20at%20the%20code%2C%20there%27s%20an%20inconsistency%20between%20OIDC%20and%20SAML%3A%0A%0A%2A%2AOIDC%2A%2A%20%28%5Bsso.ts%20L1763-1770%5D%28https%3A//github.com/better-auth/better-auth/blob/8f47015af223e5db9ff406f6ca8247f6b8dcd9fe/packages/sso/src/routes/sso.ts%23L1763-L1770%29%29%20-%20correctly%20checks%20%60isRegister%60%3A%0A%60%60%60typescript%0Aif%20%28options%3F.provisionUser%20%26%26%20linked.isRegister%29%20%7B%0A%60%60%60%0A%0A%2A%2ASAML%2A%2A%20%28%5Bsso.ts%20L2412-2418%5D%28https%3A//github.com/better-auth/better-auth/blob/8f47015af223e5db9ff406f6ca8247f6b8dcd9fe/packages/sso/src/routes/sso.ts%23L2412-L2418%29%20and%20%5BL2928-2934%5D%28https%3A//github.com/better-auth/better-auth/blob/8f47015af223e5db9ff406f6ca8247f6b8dcd9fe/packages/sso/src/routes/sso.ts%23L2928-L2934%29%29%20-%20missing%20the%20check%3A%0A%60%60%60typescript%0Aif%20%28options%3F.provisionUser%29%20%7B%0A%60%60%60%0A%0ABoth%20SAML%20callbacks%20%28%60callbackSSOSAML%60%20and%20%60acsEndpoint%60%29%20are%20missing%20the%20%60%26%26%20linked.isRegister%60%20condition%20that%20was%20added%20to%20OIDC%20in%20PR%20%237870.%20The%20%60result%60%20variable%20from%20%60handleOAuthUserInfo%60%20should%20have%20the%20%60isRegister%60%20property%20available%20that%20could%20be%20used%20here.%0A%0AThis%20issue%20could%20be%20updated%20to%20specifically%20track%20the%20SAML%20inconsistency%2C%20or%20a%20new%20bug%20can%20be%20filed%20for%20it.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=join-discord)&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/8630)
Author
Owner

@github-actions[bot] commented on GitHub (Apr 7, 2026):

This issue has been locked as it was closed more than 7 days ago. If you're experiencing a similar problem or you have additional context, please open a new issue and reference this one.

<!-- gh-comment-id:4195715410 --> @github-actions[bot] commented on GitHub (Apr 7, 2026): This issue has been locked as it was closed more than 7 days ago. If you're experiencing a similar problem or you have additional context, please open a new issue and reference this one.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#11147