change email does not update the customer's email in stripe #1091

Closed
opened 2026-03-13 08:21:58 -05:00 by GiteaMirror · 12 comments
Owner

Originally created by @DevDuki on GitHub (Apr 21, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Setup BA with Stripe and set the createCustomerOnSignUp flag to true
  2. Sign up a user with the email/password credential
  3. Change that user's email with BA's change email flow

Current vs. Expected behavior

The email is changed in my DB, but it is not reflected in Stripe's customers table. I expected BA to check whether the current user has a customerId, if so update the email in Stripe too. Either right after updating the user's email or after the new email has been verified, depending on the requireEmailVerification flag perhaps?

What version of Better Auth are you using?

1.2.7

Provide environment information

- MacOS: Sequoia 15.1
- Chrome

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

Backend

Auth config (if applicable)

export const auth = betterAuth({
	// Database
	database: prismaAdapter(prisma, {
		provider: 'sqlite'
	}),

	// Email/Password
	emailAndPassword: {
		enabled: true,
		sendResetPassword: async ({ user, url }, request) => {
			// ...
		}
	},
	emailVerification: {
		sendOnSignUp: true,
		autoSignInAfterVerification: true,
		sendVerificationEmail: async ({ user, url }, request) => {
			// ...
		}
	},

	// User
	user: {
		changeEmail: {
			enabled: true,
			sendChangeEmailVerification: async ({ user, url }, request) => {
				// ...
			}
		}
	},

	// Socials
	socialProviders: {
		// ...
	},

	// Plugins
	plugins: [
		passkey(),
		stripe({
      stripeClient: stripeBackendClient,
      stripeWebhookSecret: STRIPE_WEBHOOK_SECRET,
      createCustomerOnSignUp: true,
      subscription: {
        enabled: true,
        plans: [
          // ...
        ]
      }
    })
	],

	// Redis
	secondaryStorage: {
		get: async (key) => {
			const value = await redis.get(REDIS_PREFIX + key);
			return value ? value : null;
		},
		set: async (key, value, ttl) => {
			if (ttl) await redis.set(REDIS_PREFIX + key, value, { EX: ttl });
			else await redis.set(REDIS_PREFIX + key, value);
		},
		delete: async (key) => {
			await redis.del(REDIS_PREFIX + key);
		}
	}
});

Additional context

No response

Originally created by @DevDuki on GitHub (Apr 21, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Setup BA with Stripe and set the `createCustomerOnSignUp` flag to `true` 2. Sign up a user with the email/password credential 3. Change that user's email with BA's change email flow ### Current vs. Expected behavior The email is changed in my DB, but it is not reflected in Stripe's customers table. I expected BA to check whether the current user has a customerId, if so update the email in Stripe too. Either right after updating the user's email or after the new email has been verified, depending on the `requireEmailVerification` flag perhaps? ### What version of Better Auth are you using? 1.2.7 ### Provide environment information ```bash - MacOS: Sequoia 15.1 - Chrome ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript export const auth = betterAuth({ // Database database: prismaAdapter(prisma, { provider: 'sqlite' }), // Email/Password emailAndPassword: { enabled: true, sendResetPassword: async ({ user, url }, request) => { // ... } }, emailVerification: { sendOnSignUp: true, autoSignInAfterVerification: true, sendVerificationEmail: async ({ user, url }, request) => { // ... } }, // User user: { changeEmail: { enabled: true, sendChangeEmailVerification: async ({ user, url }, request) => { // ... } } }, // Socials socialProviders: { // ... }, // Plugins plugins: [ passkey(), stripe({ stripeClient: stripeBackendClient, stripeWebhookSecret: STRIPE_WEBHOOK_SECRET, createCustomerOnSignUp: true, subscription: { enabled: true, plans: [ // ... ] } }) ], // Redis secondaryStorage: { get: async (key) => { const value = await redis.get(REDIS_PREFIX + key); return value ? value : null; }, set: async (key, value, ttl) => { if (ttl) await redis.set(REDIS_PREFIX + key, value, { EX: ttl }); else await redis.set(REDIS_PREFIX + key, value); }, delete: async (key) => { await redis.del(REDIS_PREFIX + key); } } }); ``` ### Additional context _No response_
GiteaMirror added the bug label 2026-03-13 08:21:58 -05:00
Author
Owner

@iamsg97 commented on GitHub (May 27, 2025):

Hi @DevDuki do we know is this a bug only for stripe, or any other such vendors?
What I mean is, in case of email update we want to update email in the vendor's DB only for stripe, or the solution should be a feature (rather than a bug) that handles such user details modifications for applicable all vendors?

cc @Kinfe123 @ping-maxwell -- let me know?

I've started to do some analysis on this bug
If someone wants to keep a track, you can check here

I'll come back if there are any other questions

Cheers,
Suvadeep

@iamsg97 commented on GitHub (May 27, 2025): Hi @DevDuki do we know is this a bug only for stripe, or any other such vendors? What I mean is, in case of email update we want to update email in the vendor's DB only for stripe, or the solution should be a feature (rather than a bug) that handles such user details modifications for applicable all vendors? > cc @Kinfe123 @ping-maxwell -- let me know? I've started to do some analysis on this [bug](https://github.com/better-auth/better-auth/issues/2385) If someone wants to keep a track, you can check [here](https://github.com/iamsg97/better-auth/tree/feature/issue-2431) I'll come back if there are any other questions Cheers, Suvadeep
Author
Owner

@DevDuki commented on GitHub (Jun 2, 2025):

@iamsg97

I haven't tested any other vendors. For now I'm only using stripe. Which other vendors do you mean btw?

@DevDuki commented on GitHub (Jun 2, 2025): @iamsg97 I haven't tested any other vendors. For now I'm only using stripe. Which other vendors do you mean btw?
Author
Owner

@iamsg97 commented on GitHub (Jun 7, 2025):

I mean in future if we support integration with let's say flexile.
I found a solution to fix it. I will post the solution soon!

@iamsg97 commented on GitHub (Jun 7, 2025): I mean in future if we support integration with let's say [flexile](https://flexile.com). I found a solution to fix it. I will post the solution soon!
Author
Owner

@iamsg97 commented on GitHub (Jun 15, 2025):

Hi @DevDuki fix is available at:

I will run some tests and raise a PR to the better-auth repo. In the meantime, you can go through it and let me know any improvements or questions!

cc: @ping-maxwell

@iamsg97 commented on GitHub (Jun 15, 2025): Hi @DevDuki fix is available at: - [Add callbacks for customer email update and error handling in Stripe integration](https://github.com/iamsg97/better-auth/commit/23122bca1938537c8fc530cd7d9022e9cb93fdde) - [Add email update handling and error logging in Stripe integration](https://github.com/iamsg97/better-auth/commit/521fd3ce1b8b311651af50dfdc95631fcdb75829) > I will run some tests and raise a PR to the better-auth repo. In the meantime, you can go through it and let me know any improvements or questions! cc: @ping-maxwell
Author
Owner

@iamsg97 commented on GitHub (Jun 18, 2025):

The PR is open at 3065

🙌 Hello, the fix is raised in the above PR, please have a look and go through the fix

Here is an example

  • Below is the image from the local database, which was used to create the customer via email (credential provider)
    image

  • Below is the stripe dashboard
    image

A sample client to mimic the sign-in and email change

// Sign in
const signInResponse = await fetch(
	`http://localhost:${process.env.PORT}/api/auth/sign-in/email`,
	{
		method: "POST",
		body: JSON.stringify({
			email: "suvadeepghoshal@gmail.com",
			password: "********",
			name: "Suvadeep Ghoshal",
		}),
		headers: {
			"content-type": "application/json",
		},
	},
);

// Extract and store cookies
extractCookiesFromResponse(signInResponse);

const signInData = await signInResponse.json();
logger.info(`Sign-in response: ${JSON.stringify(signInData, null, 2)}`);
logger.info(`Stored cookies: ${getCookieHeader()}`);

// Use stored cookies for change-email request
const changeEmailResponse = await fetch(
	`http://localhost:${process.env.PORT}/api/auth/change-email`,
	{
		method: "POST",
		body: JSON.stringify({
			newEmail: "sgzoid97@gmail.com",
		}),
		headers: {
			"content-type": "application/json",
			Cookie: getCookieHeader(),
		},
	},
);
const changeEmailData = await changeEmailResponse.json();
logger.info(
	`Change email response: ${JSON.stringify(changeEmailData, null, 2)}`,
);
  • After we run the client.ts refer to the below logs and screenshots

terminal logs
image

prisma studio
image

stripe dashboard
image


Hello @ping-maxwell @DevDuki
Kindly, let me know if you guys have questions/concerns, or if I've understood the requirements wrong or mis any parts of the requirement. I will be happy to analyze and work on it!

@iamsg97 commented on GitHub (Jun 18, 2025): ### The PR is open at [3065](https://github.com/better-auth/better-auth/pull/3065) 🙌 Hello, the fix is raised in the above PR, please have a look and go through the fix **Here is an example** - Below is the image from the local database, which was used to create the customer via email (`credential` provider) ![image](https://github.com/user-attachments/assets/8e9a61a3-3e83-4637-9a7b-f3e544cb0315) - Below is the stripe dashboard ![image](https://github.com/user-attachments/assets/b22067f3-e33d-4bc3-afce-f2453d8d1d40) A sample client to mimic the sign-in and email change ```ts // Sign in const signInResponse = await fetch( `http://localhost:${process.env.PORT}/api/auth/sign-in/email`, { method: "POST", body: JSON.stringify({ email: "suvadeepghoshal@gmail.com", password: "********", name: "Suvadeep Ghoshal", }), headers: { "content-type": "application/json", }, }, ); // Extract and store cookies extractCookiesFromResponse(signInResponse); const signInData = await signInResponse.json(); logger.info(`Sign-in response: ${JSON.stringify(signInData, null, 2)}`); logger.info(`Stored cookies: ${getCookieHeader()}`); // Use stored cookies for change-email request const changeEmailResponse = await fetch( `http://localhost:${process.env.PORT}/api/auth/change-email`, { method: "POST", body: JSON.stringify({ newEmail: "sgzoid97@gmail.com", }), headers: { "content-type": "application/json", Cookie: getCookieHeader(), }, }, ); const changeEmailData = await changeEmailResponse.json(); logger.info( `Change email response: ${JSON.stringify(changeEmailData, null, 2)}`, ); ``` - After we run the `client.ts` refer to the below logs and screenshots > terminal logs ![image](https://github.com/user-attachments/assets/8565795d-7c6a-42df-914e-6be16a3bf13d) > prisma studio ![image](https://github.com/user-attachments/assets/227279a9-8801-4b81-815e-b5555ae3d6c2) > stripe dashboard ![image](https://github.com/user-attachments/assets/1addf91f-5014-4bb5-ab55-4ca66105acea) ------------------------------------------------------------------------- Hello @ping-maxwell @DevDuki Kindly, let me know if you guys have questions/concerns, or if I've understood the requirements wrong or mis any parts of the requirement. I will be happy to analyze and work on it!
Author
Owner

@DevDuki commented on GitHub (Jun 19, 2025):

@iamsg97 Thanks for the PR!

I just tested it locally in my app and it works fine! My question is just, why does the email have to be verified for this feature? Maybe check for the requireEmailVerification flag that can be set in the stripe config (see: https://www.better-auth.com/docs/plugins/stripe#main-options) first. And only if that is set to true, do the email verification check. Also the update happens only after the user verifies their new email. That too could perhaps be precheked with the requireEmailVerification flag? If it's set to false the update should happen immediately as soon as BA updates it in the DB.

What do you think?

@DevDuki commented on GitHub (Jun 19, 2025): @iamsg97 Thanks for the PR! I just tested it locally in my app and it works fine! My question is just, why does the email have to be verified for this feature? Maybe check for the `requireEmailVerification` flag that can be set in the stripe config (see: https://www.better-auth.com/docs/plugins/stripe#main-options) first. And only if that is set to `true`, do the email verification check. Also the update happens only after the user verifies their new email. That too could perhaps be precheked with the `requireEmailVerification` flag? If it's set to `false` the update should happen immediately as soon as BA updates it in the DB. What do you think?
Author
Owner

@iamsg97 commented on GitHub (Jun 19, 2025):

Sounds, intuitive. Let me take a look into those and I'll update you about the feasibility of those changes. And work on them and update the same PR.
I am in the office (my 9-5 software job 😅) now, will get to it once I'm done here

@iamsg97 commented on GitHub (Jun 19, 2025): Sounds, intuitive. Let me take a look into those and I'll update you about the feasibility of those changes. And work on them and update the same PR. I am in the office (my 9-5 software job 😅) now, will get to it once I'm done here
Author
Owner

@iamsg97 commented on GitHub (Jun 25, 2025):

Hello @DevDuki I've updated the fix here

Please let me know if this is what you wanted, I've tested it in local & it seems fine to me!

If it looks fine you can update in the PR. FYI @ping-maxwell you can take decision on the PR based on the outcome of the discussion from DevDuki

@iamsg97 commented on GitHub (Jun 25, 2025): Hello @DevDuki I've updated the fix [here](https://github.com/better-auth/better-auth/commit/636ee178976f3dff49d6aadfc9c3f0e3e89e8410) Please let me know if this is what you wanted, I've tested it in local & it seems fine to me! > If it looks fine you can update in the PR. FYI @ping-maxwell you can take decision on the PR based on the outcome of the discussion from DevDuki
Author
Owner

@DevDuki commented on GitHub (Jun 25, 2025):

@iamsg97 Yes I just tested it and it works like a charm! Thanks a lot for your effort! Left a comment in your PR though.

@DevDuki commented on GitHub (Jun 25, 2025): @iamsg97 Yes I just tested it and it works like a charm! Thanks a lot for your effort! Left a comment in your PR though.
Author
Owner

@iamsg97 commented on GitHub (Jun 25, 2025):

I've removed the loggers; it's a miss from my end. I'm extremely sorry!

@iamsg97 commented on GitHub (Jun 25, 2025): I've removed the loggers; it's a miss from my end. I'm extremely sorry!
Author
Owner

@dosubot[bot] commented on GitHub (Sep 24, 2025):

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

Issue Summary:

  • You reported that Better Auth (v1.2.7) updated user emails locally but not in Stripe when createCustomerOnSignUp was enabled.
  • A fix was provided by iamsg97 involving callbacks to sync email changes to Stripe.
  • You tested the fix and suggested making email verification conditional based on the requireEmailVerification flag in Stripe config.
  • The conditional email verification was implemented and confirmed working.
  • The fix is currently under review with positive feedback from you and the maintainers.

Next Steps:

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

Thank you for your understanding and contribution!

@dosubot[bot] commented on GitHub (Sep 24, 2025): Hi, @DevDuki. 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 reported that Better Auth (v1.2.7) updated user emails locally but not in Stripe when createCustomerOnSignUp was enabled. - A fix was provided by iamsg97 involving callbacks to sync email changes to Stripe. - You tested the fix and suggested making email verification conditional based on the requireEmailVerification flag in Stripe config. - The conditional email verification was implemented and confirmed working. - The fix is currently under review with positive feedback from you and the maintainers. **Next Steps:** - Please let me know if this issue is still relevant with the latest version of better-auth by commenting here. - If I don’t hear back within 7 days, I will automatically close this issue. Thank you for your understanding and contribution!
Author
Owner

@DevDuki commented on GitHub (Sep 25, 2025):

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

Issue Summary:

  • You reported that Better Auth (v1.2.7) updated user emails locally but not in Stripe when createCustomerOnSignUp was enabled.
  • A fix was provided by iamsg97 involving callbacks to sync email changes to Stripe.
  • You tested the fix and suggested making email verification conditional based on the requireEmailVerification flag in Stripe config.
  • The conditional email verification was implemented and confirmed working.
  • The fix is currently under review with positive feedback from you and the maintainers.

Next Steps:

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

Thank you for your understanding and contribution!

Yes, the issue is still relevant even with the latest version of better-auth.

@DevDuki commented on GitHub (Sep 25, 2025): > Hi, [@DevDuki](https://github.com/DevDuki). 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 reported that Better Auth (v1.2.7) updated user emails locally but not in Stripe when createCustomerOnSignUp was enabled. > * A fix was provided by iamsg97 involving callbacks to sync email changes to Stripe. > * You tested the fix and suggested making email verification conditional based on the requireEmailVerification flag in Stripe config. > * The conditional email verification was implemented and confirmed working. > * The fix is currently under review with positive feedback from you and the maintainers. > > **Next Steps:** > > * Please let me know if this issue is still relevant with the latest version of better-auth by commenting here. > * If I don’t hear back within 7 days, I will automatically close this issue. > > Thank you for your understanding and contribution! Yes, the issue is still relevant even with the latest version of better-auth.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1091