Log in with apple idToken. The callbackURL in the received email verification URL is undefined. #1240

Closed
opened 2026-03-13 08:29:39 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @gee1k on GitHub (May 21, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Image

Verification URL: https://xxx.com/api/auth/verify-email?token=_m_2yxOf_8tl9bsrBFePZrT6o&callbackURL=undefined

Current vs. Expected behavior

Verification URL: https://xxx.com/api/auth/verify-email?token=_m_2yxOf_8tl9bsrBFePZrT6o&callbackURL=undefined

When registering with an email, you will receive the correct URL.

Verification URL: https://xxx.com/api/auth/verify-email?token=_m_2yxOf_8tl9bsrBFePZrT6o&callbackURL=exp:///verify-email

What version of Better Auth are you using?

1.2.8

Provide environment information

Expo SDK 53

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

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"
import { expo } from '@better-auth/expo';
export const auth = betterAuth({
  plugins: [expo()],
  trustedOrigins: ['exp://'],
  database: createPool({
    host: process.env.DATABASE_HOST,
    port: parseInt(process.env.DATABASE_PORT, 10) || 3306,
    user: process.env.DATABASE_USERNAME,
    password: process.env.DATABASE_PASSWORD,
    database: process.env.DATABASE_NAME,
  }),
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
    autoSignIn: true,
  },
  emailVerification: {
    sendOnSignUp: true,
    autoSignInAfterVerification: true,
    sendVerificationEmail: async ({ user, url, token }, request) => {
      await sendMail({
        to: user.email,
        subject: 'Verify your email address',
        body: `Click the link to verify your email: ${url} `,
      });
    },
  },
  session: {
    freshAge: 10,
    modelName: 'sessions',
  },
  user: {
    modelName: 'users',
    additionalFields: {
      role: {
        type: 'string',
        defaultValue: 'user',
      },
      clientId: {
        type: 'number',
        defaultValue: '1',
      },
    },
  },
  account: {
    modelName: 'accounts',
    accountLinking: {
      enabled: true,
      trustedProviders: ['google', 'apple', 'email-password'],
      allowDifferentEmails: true,
    },
  },
  verification: {
    modelName: 'verifications',
  },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    },
    apple: {
      clientId: process.env.APPLE_CLIENT_ID as string,
      clientSecret: process.env.APPLE_CLIENT_SECRET as string,
      appBundleIdentifier: process.env.APPLE_APP_BUNDLE_IDENTIFIER as string,
    },
  },
});

Additional context

No response

Originally created by @gee1k on GitHub (May 21, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce ![Image](https://github.com/user-attachments/assets/2b58017b-de76-4e29-8751-2baa5affa578) Verification URL: https://xxx.com/api/auth/verify-email?token=_m_2yxOf_8tl9bsrBFePZrT6o&callbackURL=undefined ### Current vs. Expected behavior Verification URL: https://xxx.com/api/auth/verify-email?token=_m_2yxOf_8tl9bsrBFePZrT6o&callbackURL=undefined When registering with an email, you will receive the correct URL. Verification URL: https://xxx.com/api/auth/verify-email?token=_m_2yxOf_8tl9bsrBFePZrT6o&callbackURL=exp:///verify-email ### What version of Better Auth are you using? 1.2.8 ### Provide environment information ```bash Expo SDK 53 ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" import { expo } from '@better-auth/expo'; export const auth = betterAuth({ plugins: [expo()], trustedOrigins: ['exp://'], database: createPool({ host: process.env.DATABASE_HOST, port: parseInt(process.env.DATABASE_PORT, 10) || 3306, user: process.env.DATABASE_USERNAME, password: process.env.DATABASE_PASSWORD, database: process.env.DATABASE_NAME, }), emailAndPassword: { enabled: true, requireEmailVerification: true, autoSignIn: true, }, emailVerification: { sendOnSignUp: true, autoSignInAfterVerification: true, sendVerificationEmail: async ({ user, url, token }, request) => { await sendMail({ to: user.email, subject: 'Verify your email address', body: `Click the link to verify your email: ${url} `, }); }, }, session: { freshAge: 10, modelName: 'sessions', }, user: { modelName: 'users', additionalFields: { role: { type: 'string', defaultValue: 'user', }, clientId: { type: 'number', defaultValue: '1', }, }, }, account: { modelName: 'accounts', accountLinking: { enabled: true, trustedProviders: ['google', 'apple', 'email-password'], allowDifferentEmails: true, }, }, verification: { modelName: 'verifications', }, socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, }, apple: { clientId: process.env.APPLE_CLIENT_ID as string, clientSecret: process.env.APPLE_CLIENT_SECRET as string, appBundleIdentifier: process.env.APPLE_APP_BUNDLE_IDENTIFIER as string, }, }, }); ``` ### Additional context _No response_
Author
Owner

@gee1k commented on GitHub (May 22, 2025):

I found the root cause. After logging in through apple social, if emailVerified is false, it will be necessary to call sendVerificationEmail for verification. The final code will execute here:

f64fcc8288/packages/better-auth/src/oauth2/link-account.ts (L161-L169)

f64fcc8288/packages/better-auth/src/api/routes/sign-in.ts (L231-L312)

The specific code calls handleOAuthUserInfo without passing callbackURL.

f64fcc8288/packages/better-auth/src/api/routes/sign-in.ts (L274-L291)

This issue was also discovered before this PR. After this PR is merged, if emailVerified is automatically set to true, this issue cannot be triggered. Therefore, to debug this issue, you need to manually set emailVerified to false first.
https://github.com/better-auth/better-auth/pull/2730

@gee1k commented on GitHub (May 22, 2025): I found the root cause. After logging in through apple social, if emailVerified is false, it will be necessary to call sendVerificationEmail for verification. The final code will execute here: https://github.com/better-auth/better-auth/blob/f64fcc82880ffc8713e8b250b4748c9b41c1ab87/packages/better-auth/src/oauth2/link-account.ts#L161-L169 https://github.com/better-auth/better-auth/blob/f64fcc82880ffc8713e8b250b4748c9b41c1ab87/packages/better-auth/src/api/routes/sign-in.ts#L231-L312 The specific code calls handleOAuthUserInfo without passing callbackURL. https://github.com/better-auth/better-auth/blob/f64fcc82880ffc8713e8b250b4748c9b41c1ab87/packages/better-auth/src/api/routes/sign-in.ts#L274-L291 > This issue was also discovered before this PR. After this PR is merged, if emailVerified is automatically set to true, this issue cannot be triggered. Therefore, to debug this issue, you need to manually set emailVerified to false first. https://github.com/better-auth/better-auth/pull/2730
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1240