better-auth 1.7.9 → 1.7.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/package.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "1.7.9";
2
+ var version = "1.7.10";
3
3
  //#endregion
4
4
  export { version };
@@ -9,6 +9,7 @@ const lastLoginMethod = (userConfig) => {
9
9
  const path = ctx.path;
10
10
  if (!path) return null;
11
11
  if (path.startsWith("/callback/")) return ctx.params?.id || path.split("/").pop();
12
+ if (path === "/one-tap/callback") return "google";
12
13
  if (path === "/sign-in/email" || path === "/sign-up/email") return "email";
13
14
  if (path.includes("siwe")) return "siwe";
14
15
  if (path.includes("/passkey/verify-authentication")) return "passkey";
@@ -81,7 +81,7 @@ interface GoogleOneTapOptions {
81
81
  /**
82
82
  * Cancel the flow when the user taps outside the prompt
83
83
  *
84
- * Note: To use this option, disable `promptOptions.fedCM`
84
+ * Note: This may have no effect, as FedCM lets the browser manage dismissal
85
85
  */
86
86
  cancelOnTapOutside?: boolean | undefined;
87
87
  /**
@@ -119,7 +119,9 @@ interface GoogleOneTapOptions {
119
119
  */
120
120
  maxAttempts?: number;
121
121
  /**
122
- * Whether to support FedCM (Federated Credential Management) support.
122
+ * Whether to call `navigator.credentials.preventSilentAccess()` on
123
+ * sign-out to clear the browser's FedCM credential state. FedCM for
124
+ * the prompt itself is managed by Google and cannot be disabled.
123
125
  *
124
126
  * @see {@link https://developer.chrome.com/docs/identity/fedcm/overview}
125
127
  * @default true
@@ -9,10 +9,7 @@ function isFedCMSupported() {
9
9
  * Reasons that should NOT trigger a retry.
10
10
  * @see https://developers.google.com/identity/gsi/web/reference/js-reference
11
11
  */
12
- const noRetryReasons = {
13
- dismissed: ["credential_returned", "cancel_called"],
14
- skipped: ["user_cancel", "tap_outside"]
15
- };
12
+ const noRetryReasons = { dismissed: ["credential_returned", "cancel_called"] };
16
13
  const oneTapClient = (options) => {
17
14
  return {
18
15
  id: "one-tap",
@@ -58,9 +55,9 @@ const oneTapClient = (options) => {
58
55
  if (isSafeUrlScheme(target)) window.location.href = target;
59
56
  }
60
57
  }
61
- const { autoSelect, cancelOnTapOutside, context } = opts ?? {};
62
- const contextValue = context ?? options.context ?? "signin";
63
- const useFedCM = options.promptOptions?.fedCM !== false;
58
+ const autoSelect = opts?.autoSelect ?? options.autoSelect;
59
+ const cancelOnTapOutside = opts?.cancelOnTapOutside ?? options.cancelOnTapOutside;
60
+ const contextValue = opts?.context ?? options.context ?? "signin";
64
61
  window.google?.accounts.id.initialize({
65
62
  client_id: options.clientId,
66
63
  callback: async (response) => {
@@ -76,7 +73,6 @@ const oneTapClient = (options) => {
76
73
  ux_mode: opts?.uxMode || "popup",
77
74
  nonce: opts?.nonce,
78
75
  itp_support: true,
79
- use_fedcm_for_prompt: useFedCM,
80
76
  ...options.additionalOptions
81
77
  });
82
78
  window.google?.accounts.id.renderButton(container, opts.button.config ?? { type: "icon" });
@@ -97,8 +93,9 @@ const oneTapClient = (options) => {
97
93
  if (isSafeUrlScheme(target)) window.location.href = target;
98
94
  }
99
95
  }
100
- const { autoSelect, cancelOnTapOutside, context } = opts ?? {};
101
- const contextValue = context ?? options.context ?? "signin";
96
+ const autoSelect = opts?.autoSelect ?? options.autoSelect;
97
+ const cancelOnTapOutside = opts?.cancelOnTapOutside ?? options.cancelOnTapOutside;
98
+ const contextValue = opts?.context ?? options.context ?? "signin";
102
99
  isRequestInProgress = true;
103
100
  try {
104
101
  await loadGoogleScript();
@@ -106,7 +103,6 @@ const oneTapClient = (options) => {
106
103
  let isResolved = false;
107
104
  const baseDelay = options.promptOptions?.baseDelay ?? 1e3;
108
105
  const maxAttempts = options.promptOptions?.maxAttempts ?? 5;
109
- const useFedCM = options.promptOptions?.fedCM !== false;
110
106
  window.google?.accounts.id.initialize({
111
107
  client_id: options.clientId,
112
108
  callback: async (response) => {
@@ -128,7 +124,6 @@ const oneTapClient = (options) => {
128
124
  * @see {@link https://developers.google.com/identity/gsi/web/guides/overview}
129
125
  */
130
126
  itp_support: true,
131
- use_fedcm_for_prompt: useFedCM,
132
127
  ...options.additionalOptions
133
128
  });
134
129
  const handlePrompt = (attempt) => {
@@ -150,19 +145,8 @@ const oneTapClient = (options) => {
150
145
  resolve();
151
146
  }
152
147
  } else if (notification.isSkippedMoment?.()) {
153
- const reason = notification.getSkippedReason?.();
154
- if (!reason || noRetryReasons.skipped.includes(reason)) {
155
- opts?.onPromptNotification?.(notification);
156
- resolve();
157
- return;
158
- }
159
- if (attempt < maxAttempts) {
160
- const delay = Math.pow(2, attempt) * baseDelay;
161
- setTimeout(() => handlePrompt(attempt + 1), delay);
162
- } else {
163
- opts?.onPromptNotification?.(notification);
164
- resolve();
165
- }
148
+ opts?.onPromptNotification?.(notification);
149
+ resolve();
166
150
  } else if (notification.isNotDisplayed?.()) {
167
151
  opts?.onPromptNotification?.(notification);
168
152
  resolve();
@@ -1,5 +1,7 @@
1
1
  import { parseUserOutput } from "../../db/schema.mjs";
2
2
  import { setSessionCookie } from "../../cookies/index.mjs";
3
+ import { getAwaitableValue } from "../../context/helpers.mjs";
4
+ import { toOAuthProfileRecord } from "../../oauth2/account-key.mjs";
3
5
  import { OAUTH_CALLBACK_ERROR_CODES } from "../../oauth2/errors.mjs";
4
6
  import { handleOAuthUserInfo } from "../../oauth2/link-account.mjs";
5
7
  import { APIError as APIError$1 } from "../../api/index.mjs";
@@ -58,16 +60,32 @@ const oneTap = (options) => ({
58
60
  ctx.context.logger.error(`Google One Tap sign-in rejected: id token hosted domain (hd) "${payload.hd ?? "<missing>"}" does not satisfy the configured "hd" option "${configuredHostedDomain}".`);
59
61
  throw new APIError$1("BAD_REQUEST", { message: "invalid id token" });
60
62
  }
61
- const { email: rawEmail, email_verified, name, picture, sub } = payload;
63
+ const googleOAuthProvider = await getAwaitableValue(ctx.context.socialProviders, { value: "google" });
64
+ const providerResult = googleOAuthProvider ? await googleOAuthProvider.getUserInfo({ idToken }) : {
65
+ user: {
66
+ name: payload.name,
67
+ email: payload.email,
68
+ image: payload.picture,
69
+ emailVerified: toBoolean(payload.email_verified)
70
+ },
71
+ data: payload
72
+ };
73
+ if (!providerResult?.user) throw new APIError$1("BAD_REQUEST", { message: "invalid id token" });
74
+ const providerUser = providerResult.user;
75
+ const { sub } = payload;
76
+ const { email: rawEmail, name, image } = providerUser;
62
77
  if (typeof rawEmail !== "string" || !rawEmail) throw new APIError$1("BAD_REQUEST", { message: "Email not available in token" });
63
78
  if (typeof sub !== "string" || !sub) throw new APIError$1("BAD_REQUEST", { message: "invalid id token" });
79
+ const email = rawEmail.toLowerCase();
80
+ const emailVerified = toBoolean(providerUser.emailVerified);
64
81
  const result = await handleOAuthUserInfo(ctx, {
65
82
  userInfo: {
83
+ ...providerUser,
66
84
  id: sub,
67
- email: rawEmail.toLowerCase(),
68
- emailVerified: typeof email_verified === "boolean" ? email_verified : toBoolean(email_verified),
85
+ email,
86
+ emailVerified,
69
87
  name: typeof name === "string" ? name : "",
70
- image: typeof picture === "string" ? picture : void 0
88
+ image: typeof image === "string" ? image : void 0
71
89
  },
72
90
  account: {
73
91
  providerId: "google",
@@ -76,11 +94,12 @@ const oneTap = (options) => ({
76
94
  scope: "openid,profile,email"
77
95
  },
78
96
  disableSignUp: options?.disableSignup || googleProvider?.disableSignUp,
97
+ overrideUserInfo: googleProvider?.overrideUserInfoOnSignIn,
79
98
  source: {
80
99
  method: "oauth",
81
100
  oauth: {
82
101
  providerId: "google",
83
- profile: payload
102
+ profile: toOAuthProfileRecord(providerResult.data)
84
103
  }
85
104
  }
86
105
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-auth",
3
- "version": "1.7.9",
3
+ "version": "1.7.10",
4
4
  "description": "The most comprehensive authentication framework for TypeScript.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -221,6 +221,11 @@
221
221
  "types": "./dist/plugins/bearer/index.d.mts",
222
222
  "default": "./dist/plugins/bearer/index.mjs"
223
223
  },
224
+ "./plugins/captcha": {
225
+ "dev-source": "./src/plugins/captcha/index.ts",
226
+ "types": "./dist/plugins/captcha/index.d.mts",
227
+ "default": "./dist/plugins/captcha/index.mjs"
228
+ },
224
229
  "./plugins/custom-session": {
225
230
  "dev-source": "./src/plugins/custom-session/index.ts",
226
231
  "types": "./dist/plugins/custom-session/index.d.mts",
@@ -276,6 +281,16 @@
276
281
  "types": "./dist/plugins/one-time-token/index.d.mts",
277
282
  "default": "./dist/plugins/one-time-token/index.mjs"
278
283
  },
284
+ "./plugins/one-tap": {
285
+ "dev-source": "./src/plugins/one-tap/index.ts",
286
+ "types": "./dist/plugins/one-tap/index.d.mts",
287
+ "default": "./dist/plugins/one-tap/index.mjs"
288
+ },
289
+ "./plugins/open-api": {
290
+ "dev-source": "./src/plugins/open-api/index.ts",
291
+ "types": "./dist/plugins/open-api/index.d.mts",
292
+ "default": "./dist/plugins/open-api/index.mjs"
293
+ },
279
294
  "./plugins/phone-number": {
280
295
  "dev-source": "./src/plugins/phone-number/index.ts",
281
296
  "types": "./dist/plugins/phone-number/index.d.mts",
@@ -355,6 +370,9 @@
355
370
  "api": [
356
371
  "./dist/api/index.d.mts"
357
372
  ],
373
+ "test": [
374
+ "./dist/test-utils/index.d.mts"
375
+ ],
358
376
  "db": [
359
377
  "./dist/db/index.d.mts"
360
378
  ],
@@ -415,6 +433,9 @@
415
433
  "plugins/bearer": [
416
434
  "./dist/plugins/bearer/index.d.mts"
417
435
  ],
436
+ "plugins/captcha": [
437
+ "./dist/plugins/captcha/index.d.mts"
438
+ ],
418
439
  "plugins/custom-session": [
419
440
  "./dist/plugins/custom-session/index.d.mts"
420
441
  ],
@@ -433,12 +454,21 @@
433
454
  "plugins/one-time-token": [
434
455
  "./dist/plugins/one-time-token/index.d.mts"
435
456
  ],
457
+ "plugins/one-tap": [
458
+ "./dist/plugins/one-tap/index.d.mts"
459
+ ],
460
+ "plugins/open-api": [
461
+ "./dist/plugins/open-api/index.d.mts"
462
+ ],
436
463
  "plugins/jwt": [
437
464
  "./dist/plugins/jwt/index.d.mts"
438
465
  ],
439
466
  "plugins/magic-link": [
440
467
  "./dist/plugins/magic-link/index.d.mts"
441
468
  ],
469
+ "plugins/multi-session": [
470
+ "./dist/plugins/multi-session/index.d.mts"
471
+ ],
442
472
  "plugins/organization": [
443
473
  "./dist/plugins/organization/index.d.mts"
444
474
  ],
@@ -473,13 +503,13 @@
473
503
  "kysely": "^0.28.17 || ^0.29.0",
474
504
  "nanostores": "^1.3.0",
475
505
  "zod": "^4.5.4",
476
- "@better-auth/core": "1.7.9",
477
- "@better-auth/drizzle-adapter": "1.7.9",
478
- "@better-auth/kysely-adapter": "1.7.9",
479
- "@better-auth/memory-adapter": "1.7.9",
480
- "@better-auth/mongo-adapter": "1.7.9",
481
- "@better-auth/prisma-adapter": "1.7.9",
482
- "@better-auth/telemetry": "1.7.9"
506
+ "@better-auth/core": "1.7.10",
507
+ "@better-auth/drizzle-adapter": "1.7.10",
508
+ "@better-auth/kysely-adapter": "1.7.10",
509
+ "@better-auth/memory-adapter": "1.7.10",
510
+ "@better-auth/mongo-adapter": "1.7.10",
511
+ "@better-auth/prisma-adapter": "1.7.10",
512
+ "@better-auth/telemetry": "1.7.10"
483
513
  },
484
514
  "devDependencies": {
485
515
  "@lynx-js/react": "^0.121.2",