@better-auth/core 1.4.0-beta.25 → 1.4.0-beta.28

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @better-auth/core@1.4.0-beta.25 build /home/runner/work/better-auth/better-auth/packages/core
2
+ > @better-auth/core@1.4.0-beta.28 build /home/runner/work/better-auth/better-auth/packages/core
3
3
  > tsdown
4
4
 
5
5
  ℹ tsdown v0.16.5 powered by rolldown v1.0.0-beta.50
@@ -7,7 +7,7 @@
7
7
  ℹ entry: src/index.ts, src/db/index.ts, src/db/adapter/index.ts, src/async_hooks/index.ts, src/context/index.ts, src/env/index.ts, src/oauth2/index.ts, src/api/index.ts, src/social-providers/index.ts, src/utils/index.ts, src/error/index.ts
8
8
  ℹ tsconfig: tsconfig.json
9
9
  ℹ Build start
10
- ℹ dist/social-providers/index.mjs  77.94 kB │ gzip: 10.14 kB
10
+ ℹ dist/social-providers/index.mjs  78.21 kB │ gzip: 10.17 kB
11
11
  ℹ dist/db/index.mjs  1.58 kB │ gzip: 0.49 kB
12
12
  ℹ dist/api/index.mjs  0.83 kB │ gzip: 0.40 kB
13
13
  ℹ dist/context/index.mjs  0.74 kB │ gzip: 0.27 kB
@@ -18,25 +18,25 @@
18
18
  ℹ dist/utils/index.mjs  0.09 kB │ gzip: 0.09 kB
19
19
  ℹ dist/db/adapter/index.mjs  0.01 kB │ gzip: 0.03 kB
20
20
  ℹ dist/index.mjs  0.01 kB │ gzip: 0.03 kB
21
- ℹ dist/oauth2-D3aE32ZH.mjs  9.16 kB │ gzip: 2.12 kB
21
+ ℹ dist/oauth2-DmgZmPEg.mjs  9.17 kB │ gzip: 2.13 kB
22
22
  ℹ dist/env-DwlNAN_D.mjs  7.67 kB │ gzip: 2.54 kB
23
23
  ℹ dist/context-DgQ9XGBl.mjs  3.89 kB │ gzip: 1.00 kB
24
24
  ℹ dist/error-BhAKg8LX.mjs  1.77 kB │ gzip: 0.79 kB
25
25
  ℹ dist/async_hooks-BfRfbd1J.mjs  0.87 kB │ gzip: 0.46 kB
26
26
  ℹ dist/utils-C5EN75oV.mjs  0.13 kB │ gzip: 0.12 kB
27
- ℹ dist/social-providers/index.d.mts  3.78 kB │ gzip: 1.17 kB
27
+ ℹ dist/social-providers/index.d.mts  3.78 kB │ gzip: 1.16 kB
28
28
  ℹ dist/context/index.d.mts  3.05 kB │ gzip: 0.96 kB
29
29
  ℹ dist/error/index.d.mts  1.84 kB │ gzip: 0.72 kB
30
30
  ℹ dist/db/index.d.mts  1.01 kB │ gzip: 0.38 kB
31
+ ℹ dist/index.d.mts  0.87 kB │ gzip: 0.34 kB
31
32
  ℹ dist/utils/index.d.mts  0.84 kB │ gzip: 0.43 kB
32
- ℹ dist/index.d.mts  0.83 kB │ gzip: 0.32 kB
33
33
  ℹ dist/oauth2/index.d.mts  0.79 kB │ gzip: 0.30 kB
34
34
  ℹ dist/env/index.d.mts  0.59 kB │ gzip: 0.30 kB
35
- ℹ dist/db/adapter/index.d.mts  0.53 kB │ gzip: 0.25 kB
35
+ ℹ dist/db/adapter/index.d.mts  0.53 kB │ gzip: 0.24 kB
36
36
  ℹ dist/api/index.d.mts  0.29 kB │ gzip: 0.16 kB
37
37
  ℹ dist/async_hooks/index.d.mts  0.14 kB │ gzip: 0.10 kB
38
- ℹ dist/index-X4TpuzeM.d.mts 204.34 kB │ gzip: 32.16 kB
38
+ ℹ dist/index-CkAWdKH8.d.mts 205.84 kB │ gzip: 32.50 kB
39
39
  ℹ dist/index-CdubV7uy.d.mts  3.31 kB │ gzip: 1.11 kB
40
40
  ℹ dist/index-DgwIISs7.d.mts  0.24 kB │ gzip: 0.16 kB
41
- ℹ 31 files, total: 327.60 kB
42
- ✔ Build complete in 4660ms
41
+ ℹ 31 files, total: 329.43 kB
42
+ ✔ Build complete in 4688ms
@@ -1,3 +1,3 @@
1
- import { a as optionsMiddleware, i as createAuthMiddleware, n as AuthMiddleware, r as createAuthEndpoint, t as AuthEndpoint } from "../index-X4TpuzeM.mjs";
1
+ import { a as optionsMiddleware, i as createAuthMiddleware, n as AuthMiddleware, r as createAuthEndpoint, t as AuthEndpoint } from "../index-CkAWdKH8.mjs";
2
2
  import "../index-CdubV7uy.mjs";
3
3
  export { AuthEndpoint, AuthMiddleware, createAuthEndpoint, createAuthMiddleware, optionsMiddleware };
@@ -1,4 +1,4 @@
1
- import { Jn as DBTransactionAdapter, Un as DBAdapter, d as AuthContext } from "../index-X4TpuzeM.mjs";
1
+ import { Wn as DBAdapter, Yn as DBTransactionAdapter, f as AuthContext } from "../index-CkAWdKH8.mjs";
2
2
  import "../index-CdubV7uy.mjs";
3
3
  import { t as AsyncLocalStorage } from "../index-DgwIISs7.mjs";
4
4
  import { EndpointContext, InputContext } from "better-call";
@@ -1,3 +1,3 @@
1
- import { Gn as DBAdapterFactoryConfig, Hn as CustomAdapter, Jn as DBTransactionAdapter, Kn as DBAdapterInstance, Un as DBAdapter, Vn as CleanedWhere, Wn as DBAdapterDebugLogOption, Xn as JoinOption, Yn as JoinConfig, Zn as Where, qn as DBAdapterSchemaCreation } from "../../index-X4TpuzeM.mjs";
1
+ import { Gn as DBAdapterDebugLogOption, Hn as CleanedWhere, Jn as DBAdapterSchemaCreation, Kn as DBAdapterFactoryConfig, Qn as Where, Un as CustomAdapter, Wn as DBAdapter, Xn as JoinConfig, Yn as DBTransactionAdapter, Zn as JoinOption, qn as DBAdapterInstance } from "../../index-CkAWdKH8.mjs";
2
2
  import "../../index-CdubV7uy.mjs";
3
3
  export { CleanedWhere, CustomAdapter, DBAdapter, DBAdapterDebugLogOption, DBAdapterFactoryConfig, DBAdapterInstance, DBAdapterSchemaCreation, DBTransactionAdapter, JoinConfig, JoinOption, Where };
@@ -1,3 +1,3 @@
1
- import { $n as BetterAuthDbSchema, Qn as AuthPluginSchema, Sr as SecondaryStorage, _r as DBFieldAttribute, ar as verificationSchema, br as DBPreservedModels, cr as coreSchema, dr as RateLimit, er as FieldAttribute, fr as rateLimitSchema, gr as BetterAuthDBSchema, hr as BetterAuthPluginDBSchema, ir as Verification, lr as Session, mr as accountSchema, nr as FieldType, or as User, pr as Account, rr as Primitive, sr as userSchema, tr as FieldAttributeConfig, ur as sessionSchema, vr as DBFieldAttributeConfig, xr as DBPrimitive, yr as DBFieldType } from "../index-X4TpuzeM.mjs";
1
+ import { $n as AuthPluginSchema, Cr as SecondaryStorage, Sr as DBPrimitive, _r as BetterAuthDBSchema, ar as Verification, br as DBFieldType, cr as userSchema, dr as sessionSchema, er as BetterAuthDbSchema, fr as RateLimit, gr as BetterAuthPluginDBSchema, hr as accountSchema, ir as Primitive, lr as coreSchema, mr as Account, nr as FieldAttributeConfig, or as verificationSchema, pr as rateLimitSchema, rr as FieldType, sr as User, tr as FieldAttribute, ur as Session, vr as DBFieldAttribute, xr as DBPreservedModels, yr as DBFieldAttributeConfig } from "../index-CkAWdKH8.mjs";
2
2
  import "../index-CdubV7uy.mjs";
3
3
  export { Account, AuthPluginSchema, BetterAuthDBSchema, BetterAuthDbSchema, BetterAuthPluginDBSchema, DBFieldAttribute, DBFieldAttributeConfig, DBFieldType, DBPreservedModels, DBPrimitive, FieldAttribute, FieldAttributeConfig, FieldType, Primitive, RateLimit, SecondaryStorage, Session, User, Verification, accountSchema, coreSchema, rateLimitSchema, sessionSchema, userSchema, verificationSchema };
@@ -775,6 +775,11 @@ interface OAuth2Tokens {
775
775
  refreshTokenExpiresAt?: Date | undefined;
776
776
  scopes?: string[] | undefined;
777
777
  idToken?: string | undefined;
778
+ /**
779
+ * Raw token response from the provider.
780
+ * Preserves provider-specific fields that are not part of the standard OAuth2 token response.
781
+ */
782
+ raw?: Record<string, unknown> | undefined;
778
783
  }
779
784
  type OAuth2UserInfo = {
780
785
  id: string | number;
@@ -1116,6 +1121,10 @@ type BetterAuthCookies = {
1116
1121
  name: string;
1117
1122
  options: CookieOptions;
1118
1123
  };
1124
+ accountData: {
1125
+ name: string;
1126
+ options: CookieOptions;
1127
+ };
1119
1128
  dontRememberToken: {
1120
1129
  name: string;
1121
1130
  options: CookieOptions;
@@ -1822,6 +1831,8 @@ interface MicrosoftEntraIDProfile extends Record<string, any> {
1822
1831
  verified_primary_email: string[];
1823
1832
  /** User's verified secondary email addresses */
1824
1833
  verified_secondary_email: string[];
1834
+ /** Whether the user's email is verified (optional claim, must be configured in app registration) */
1835
+ email_verified?: boolean | undefined;
1825
1836
  /** VNET specifier information */
1826
1837
  vnet: string;
1827
1838
  /** Client Capabilities */
@@ -2429,7 +2440,7 @@ declare const twitter: (options: TwitterOption) => {
2429
2440
  user?: {
2430
2441
  name?: {
2431
2442
  firstName?: string;
2432
- lastName? /** Contains details about the user's profile website. */: string;
2443
+ lastName?: string;
2433
2444
  };
2434
2445
  email?: string;
2435
2446
  } | undefined;
@@ -2759,6 +2770,7 @@ interface GitlabProfile extends Record<string, any> {
2759
2770
  commit_email: string;
2760
2771
  shared_runners_minutes_limit: number;
2761
2772
  extra_shared_runners_minutes_limit: number;
2773
+ email_verified?: boolean | undefined;
2762
2774
  }
2763
2775
  interface GitlabOptions extends ProviderOptions<GitlabProfile> {
2764
2776
  clientId: string;
@@ -2816,7 +2828,7 @@ declare const gitlab: (options: GitlabOptions) => {
2816
2828
  name: string;
2817
2829
  email: string;
2818
2830
  image: string;
2819
- emailVerified: true;
2831
+ emailVerified: boolean;
2820
2832
  } | {
2821
2833
  id: string | number;
2822
2834
  name: string;
@@ -4024,7 +4036,16 @@ declare const paypal: (options: PayPalOptions) => {
4024
4036
  getUserInfo(token: OAuth2Tokens & {
4025
4037
  user?: {
4026
4038
  name?: {
4027
- firstName?: string;
4039
+ firstName
4040
+ /**
4041
+ * Whether to request shipping address information
4042
+ * @default false
4043
+ */?
4044
+ /**
4045
+ * Whether to request shipping address information
4046
+ * @default false
4047
+ */
4048
+ : string;
4028
4049
  lastName?: string;
4029
4050
  };
4030
4051
  email?: string;
@@ -4073,6 +4094,7 @@ interface PolarProfile {
4073
4094
  github_username?: string | undefined;
4074
4095
  account_id?: string | undefined;
4075
4096
  public_name?: string | undefined;
4097
+ email_verified?: boolean | undefined;
4076
4098
  profile_settings?: {
4077
4099
  profile_settings_enabled?: boolean;
4078
4100
  profile_settings_public_name?: string;
@@ -5037,7 +5059,7 @@ declare const socialProviders: {
5037
5059
  name: string;
5038
5060
  email: string;
5039
5061
  image: string;
5040
- emailVerified: true;
5062
+ emailVerified: boolean;
5041
5063
  } | {
5042
5064
  id: string | number;
5043
5065
  name: string;
@@ -6085,27 +6107,6 @@ type BetterAuthAdvancedOptions = {
6085
6107
  */
6086
6108
  generateId?: GenerateIdFn | false | "serial" | "uuid";
6087
6109
  } | undefined;
6088
- /**
6089
- * OAuth configuration
6090
- */
6091
- oauthConfig?: {
6092
- /**
6093
- * Skip state cookie check
6094
- *
6095
- * ⚠︎ this has security implications and should only be enabled if you know what you are doing.
6096
- * @default false
6097
- */
6098
- skipStateCookieCheck?: boolean;
6099
- /**
6100
- * Strategy for storing OAuth state
6101
- *
6102
- * - "cookie": Store state in an encrypted cookie (stateless)
6103
- * - "database": Store state in the database
6104
- *
6105
- * @default "cookie"
6106
- */
6107
- storeStateStrategy?: "database" | "cookie";
6108
- } | undefined;
6109
6110
  };
6110
6111
  type BetterAuthOptions = {
6111
6112
  /**
@@ -6702,6 +6703,32 @@ type BetterAuthOptions = {
6702
6703
  * @default false
6703
6704
  */
6704
6705
  encryptOAuthTokens?: boolean;
6706
+ /**
6707
+ * Skip state cookie check
6708
+ *
6709
+ * ⚠︎ this has security implications and should only be enabled if you know what you are doing.
6710
+ * @default false
6711
+ */
6712
+ skipStateCookieCheck?: boolean;
6713
+ /**
6714
+ * Strategy for storing OAuth state
6715
+ *
6716
+ * - "cookie": Store state in an encrypted cookie (stateless)
6717
+ * - "database": Store state in the database
6718
+ *
6719
+ * @default "cookie"
6720
+ */
6721
+ storeStateStrategy?: "database" | "cookie";
6722
+ /**
6723
+ * Store account data after oauth flow on a cookie
6724
+ *
6725
+ * This is useful for database-less flow
6726
+ *
6727
+ * @default false
6728
+ *
6729
+ * @note This is automatically set to true if you haven't passed a database
6730
+ */
6731
+ storeAccountCookie?: boolean;
6705
6732
  } | undefined;
6706
6733
  /**
6707
6734
  * Verification configuration
@@ -7082,8 +7109,8 @@ interface InternalAdapter<Options extends BetterAuthOptions = BetterAuthOptions>
7082
7109
  } | null>;
7083
7110
  findUserById(userId: string): Promise<User | null>;
7084
7111
  linkAccount(account: Omit<Account, "id" | "createdAt" | "updatedAt"> & Partial<Account>): Promise<Account>;
7085
- updateUser(userId: string, data: Partial<User> & Record<string, any>): Promise<any>;
7086
- updateUserByEmail(email: string, data: Partial<User & Record<string, any>>): Promise<User>;
7112
+ updateUser<T extends Record<string, any>>(userId: string, data: Partial<User> & Record<string, any>): Promise<User & T>;
7113
+ updateUserByEmail<T extends Record<string, any>>(email: string, data: Partial<User & Record<string, any>>): Promise<User & T>;
7087
7114
  updatePassword(userId: string, password: string): Promise<void>;
7088
7115
  findAccounts(userId: string): Promise<Account[]>;
7089
7116
  findAccount(accountId: string): Promise<Account | null>;
@@ -7218,6 +7245,17 @@ type ClientAtomListener = {
7218
7245
  matcher: (path: string) => boolean;
7219
7246
  signal: "$sessionSignal" | Omit<string, "$sessionSignal">;
7220
7247
  };
7248
+ /**
7249
+ * Better-Fetch options but with additional options for the auth-client.
7250
+ */
7251
+ type ClientFetchOption<Body = any, Query extends Record<string, any> = any, Params extends Record<string, any> | Array<string> | undefined = any, Res = any> = BetterFetchOption<Body, Query, Params, Res> & {
7252
+ /**
7253
+ * Certain endpoints, upon successful response, will trigger atom signals and thus rerendering all hooks related to that atom.
7254
+ *
7255
+ * This option is useful when you want to skip hook rerenders.
7256
+ */
7257
+ disableSignal?: boolean | undefined;
7258
+ };
7221
7259
  interface RevalidateOptions {
7222
7260
  /**
7223
7261
  * A time interval (in seconds) after which the session will be re-fetched.
@@ -7248,7 +7286,7 @@ interface RevalidateOptions {
7248
7286
  refetchWhenOffline?: boolean | undefined;
7249
7287
  }
7250
7288
  interface BetterAuthClientOptions {
7251
- fetchOptions?: BetterFetchOption | undefined;
7289
+ fetchOptions?: ClientFetchOption | undefined;
7252
7290
  plugins?: BetterAuthClientPlugin[] | undefined;
7253
7291
  baseURL?: string | undefined;
7254
7292
  basePath?: string | undefined;
@@ -7311,4 +7349,4 @@ declare const createAuthEndpoint: <Path extends string, Opts extends EndpointOpt
7311
7349
  type AuthEndpoint = ReturnType<typeof createAuthEndpoint>;
7312
7350
  type AuthMiddleware = ReturnType<typeof createAuthMiddleware>;
7313
7351
  //#endregion
7314
- export { ZoomOptions as $, BetterAuthDbSchema as $n, microsoft as $t, PayPalProfile as A, generateCodeChallenge as An, DropboxOptions as At, NaverOptions as B, ProviderOptions as Bn, SpotifyProfile as Bt, SocialProviders as C, getApplePublicKey as Cn, LinearOptions as Ct, PolarProfile as D, createAuthorizationCodeRequest as Dn, KickOptions as Dt, PolarOptions as E, BetterAuthCookies as En, linear as Et, paybin as F, clientCredentialsToken as Fn, twitter as Ft, kakao as G, DBAdapterFactoryConfig as Gn, HuggingFaceOptions as Gt, naver as H, CustomAdapter as Hn, SlackOptions as Ht, LineIdTokenPayload as I, createClientCredentialsTokenRequest as In, TwitchOptions as It, notion as J, DBTransactionAdapter as Jn, GoogleOptions as Jt, NotionOptions as K, DBAdapterInstance as Kn, HuggingFaceProfile as Kt, LineOptions as L, OAuth2Tokens as Ln, TwitchProfile as Lt, paypal as M, createRefreshAccessTokenRequest as Mn, dropbox as Mt, PaybinOptions as N, refreshAccessToken as Nn, TwitterOption as Nt, polar as O, validateAuthorizationCode as On, KickProfile as Ot, PaybinProfile as P, createAuthorizationURL as Pn, TwitterProfile as Pt, PronounOption as Q, AuthPluginSchema as Qn, MicrosoftOptions as Qt, LineUserInfo as R, OAuth2UserInfo as Rn, twitch as Rt, SocialProviderListEnum as S, apple as Sn, SecondaryStorage as Sr, linkedin as St, socialProviders as T, LiteralUnion as Tn, LinearUser as Tt, KakaoOptions as U, DBAdapter as Un, SlackProfile as Ut, NaverProfile as V, CleanedWhere as Vn, spotify as Vt, KakaoProfile as W, DBAdapterDebugLogOption as Wn, slack as Wt, LoginType as X, JoinOption as Xn, google as Xt, AccountStatus as Y, JoinConfig as Yn, GoogleProfile as Yt, PhoneNumber as Z, Where as Zn, MicrosoftEntraIDProfile as Zt, GenerateIdFn as _, AtlassianProfile as _n, DBFieldAttribute as _r, GitlabOptions as _t, optionsMiddleware as a, figma as an, verificationSchema as ar, SalesforceOptions as at, SocialProvider as b, AppleOptions as bn, DBPreservedModels as br, LinkedInOptions as bt, BetterAuthClientPlugin as c, facebook as cn, coreSchema as cr, RobloxOptions as ct, AuthContext as d, discord as dn, RateLimit as dr, RedditOptions as dt, GithubOptions as en, FieldAttribute as er, ZoomProfile as et, GenericEndpointContext as f, CognitoOptions as fn, rateLimitSchema as fr, RedditProfile as ft, BetterAuthRateLimitOptions as g, AtlassianOptions as gn, BetterAuthDBSchema as gr, tiktok as gt, BetterAuthOptions as h, getCognitoPublicKey as hn, BetterAuthPluginDBSchema as hr, TiktokProfile as ht, createAuthMiddleware as i, FigmaProfile as in, Verification as ir, vk as it, PayPalTokenResponse as j, getOAuth2Tokens as jn, DropboxProfile as jt, PayPalOptions as k, validateToken as kn, kick as kt, ClientAtomListener as l, DiscordOptions as ln, Session as lr, RobloxProfile as lt, BetterAuthAdvancedOptions as m, cognito as mn, accountSchema as mr, TiktokOptions as mt, AuthMiddleware as n, github as nn, FieldType as nr, VkOption as nt, StandardSchemaV1$1 as o, FacebookOptions as on, User as or, SalesforceProfile as ot, InternalAdapter as p, CognitoProfile as pn, Account as pr, reddit as pt, NotionProfile as q, DBAdapterSchemaCreation as qn, huggingface as qt, createAuthEndpoint as r, FigmaOptions as rn, Primitive$1 as rr, VkProfile as rt, BetterAuthClientOptions as s, FacebookProfile as sn, userSchema as sr, salesforce as st, AuthEndpoint as t, GithubProfile as tn, FieldAttributeConfig as tr, zoom as tt, ClientStore as u, DiscordProfile as un, sessionSchema as ur, roblox as ut, BetterAuthPlugin as v, atlassian as vn, DBFieldAttributeConfig as vr, GitlabProfile as vt, socialProviderList as w, LiteralString as wn, LinearProfile as wt, SocialProviderList as x, AppleProfile as xn, DBPrimitive as xr, LinkedInProfile as xt, HookEndpointContext as y, AppleNonConformUser as yn, DBFieldType as yr, gitlab as yt, line as z, OAuthProvider as zn, SpotifyOptions as zt };
7352
+ export { PronounOption as $, AuthPluginSchema as $n, MicrosoftOptions as $t, PayPalOptions as A, validateToken as An, kick as At, line as B, OAuthProvider as Bn, SpotifyOptions as Bt, SocialProviderListEnum as C, apple as Cn, SecondaryStorage as Cr, linkedin as Ct, PolarOptions as D, BetterAuthCookies as Dn, linear as Dt, socialProviders as E, LiteralUnion as En, LinearUser as Et, PaybinProfile as F, createAuthorizationURL as Fn, TwitterProfile as Ft, KakaoProfile as G, DBAdapterDebugLogOption as Gn, slack as Gt, NaverProfile as H, CleanedWhere as Hn, spotify as Ht, paybin as I, clientCredentialsToken as In, twitter as It, NotionProfile as J, DBAdapterSchemaCreation as Jn, huggingface as Jt, kakao as K, DBAdapterFactoryConfig as Kn, HuggingFaceOptions as Kt, LineIdTokenPayload as L, createClientCredentialsTokenRequest as Ln, TwitchOptions as Lt, PayPalTokenResponse as M, getOAuth2Tokens as Mn, DropboxProfile as Mt, paypal as N, createRefreshAccessTokenRequest as Nn, dropbox as Nt, PolarProfile as O, createAuthorizationCodeRequest as On, KickOptions as Ot, PaybinOptions as P, refreshAccessToken as Pn, TwitterOption as Pt, PhoneNumber as Q, Where as Qn, MicrosoftEntraIDProfile as Qt, LineOptions as R, OAuth2Tokens as Rn, TwitchProfile as Rt, SocialProviderList as S, AppleProfile as Sn, DBPrimitive as Sr, LinkedInProfile as St, socialProviderList as T, LiteralString as Tn, LinearProfile as Tt, naver as U, CustomAdapter as Un, SlackOptions as Ut, NaverOptions as V, ProviderOptions as Vn, SpotifyProfile as Vt, KakaoOptions as W, DBAdapter as Wn, SlackProfile as Wt, AccountStatus as X, JoinConfig as Xn, GoogleProfile as Xt, notion as Y, DBTransactionAdapter as Yn, GoogleOptions as Yt, LoginType as Z, JoinOption as Zn, google as Zt, BetterAuthRateLimitOptions as _, AtlassianOptions as _n, BetterAuthDBSchema as _r, tiktok as _t, optionsMiddleware as a, FigmaProfile as an, Verification as ar, vk as at, HookEndpointContext as b, AppleNonConformUser as bn, DBFieldType as br, gitlab as bt, BetterAuthClientPlugin as c, FacebookProfile as cn, userSchema as cr, salesforce as ct, ClientStore as d, DiscordProfile as dn, sessionSchema as dr, roblox as dt, microsoft as en, BetterAuthDbSchema as er, ZoomOptions as et, AuthContext as f, discord as fn, RateLimit as fr, RedditOptions as ft, BetterAuthOptions as g, getCognitoPublicKey as gn, BetterAuthPluginDBSchema as gr, TiktokProfile as gt, BetterAuthAdvancedOptions as h, cognito as hn, accountSchema as hr, TiktokOptions as ht, createAuthMiddleware as i, FigmaOptions as in, Primitive$1 as ir, VkProfile as it, PayPalProfile as j, generateCodeChallenge as jn, DropboxOptions as jt, polar as k, validateAuthorizationCode as kn, KickProfile as kt, ClientAtomListener as l, facebook as ln, coreSchema as lr, RobloxOptions as lt, InternalAdapter as m, CognitoProfile as mn, Account as mr, reddit as mt, AuthMiddleware as n, GithubProfile as nn, FieldAttributeConfig as nr, zoom as nt, StandardSchemaV1$1 as o, figma as on, verificationSchema as or, SalesforceOptions as ot, GenericEndpointContext as p, CognitoOptions as pn, rateLimitSchema as pr, RedditProfile as pt, NotionOptions as q, DBAdapterInstance as qn, HuggingFaceProfile as qt, createAuthEndpoint as r, github as rn, FieldType as rr, VkOption as rt, BetterAuthClientOptions as s, FacebookOptions as sn, User as sr, SalesforceProfile as st, AuthEndpoint as t, GithubOptions as tn, FieldAttribute as tr, ZoomProfile as tt, ClientFetchOption as u, DiscordOptions as un, Session as ur, RobloxProfile as ut, GenerateIdFn as v, AtlassianProfile as vn, DBFieldAttribute as vr, GitlabOptions as vt, SocialProviders as w, getApplePublicKey as wn, LinearOptions as wt, SocialProvider as x, AppleOptions as xn, DBPreservedModels as xr, LinkedInOptions as xt, BetterAuthPlugin as y, atlassian as yn, DBFieldAttributeConfig as yr, GitlabProfile as yt, LineUserInfo as z, OAuth2UserInfo as zn, twitch as zt };
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { En as BetterAuthCookies, Tn as LiteralUnion, _ as GenerateIdFn, c as BetterAuthClientPlugin, d as AuthContext, f as GenericEndpointContext, g as BetterAuthRateLimitOptions, h as BetterAuthOptions, l as ClientAtomListener, m as BetterAuthAdvancedOptions, o as StandardSchemaV1, p as InternalAdapter, s as BetterAuthClientOptions, u as ClientStore, v as BetterAuthPlugin, wn as LiteralString, y as HookEndpointContext } from "./index-X4TpuzeM.mjs";
1
+ import { Dn as BetterAuthCookies, En as LiteralUnion, Tn as LiteralString, _ as BetterAuthRateLimitOptions, b as HookEndpointContext, c as BetterAuthClientPlugin, d as ClientStore, f as AuthContext, g as BetterAuthOptions, h as BetterAuthAdvancedOptions, l as ClientAtomListener, m as InternalAdapter, o as StandardSchemaV1, p as GenericEndpointContext, s as BetterAuthClientOptions, u as ClientFetchOption, v as GenerateIdFn, y as BetterAuthPlugin } from "./index-CkAWdKH8.mjs";
2
2
  import "./index-CdubV7uy.mjs";
3
- export { AuthContext, BetterAuthAdvancedOptions, BetterAuthClientOptions, BetterAuthClientPlugin, BetterAuthCookies, BetterAuthOptions, BetterAuthPlugin, BetterAuthRateLimitOptions, ClientAtomListener, ClientStore, GenerateIdFn, GenericEndpointContext, HookEndpointContext, InternalAdapter, LiteralString, LiteralUnion, StandardSchemaV1 };
3
+ export { AuthContext, BetterAuthAdvancedOptions, BetterAuthClientOptions, BetterAuthClientPlugin, BetterAuthCookies, BetterAuthOptions, BetterAuthPlugin, BetterAuthRateLimitOptions, ClientAtomListener, ClientFetchOption, ClientStore, GenerateIdFn, GenericEndpointContext, HookEndpointContext, InternalAdapter, LiteralString, LiteralUnion, StandardSchemaV1 };
@@ -1,3 +1,3 @@
1
- import { An as generateCodeChallenge, Bn as ProviderOptions, Dn as createAuthorizationCodeRequest, Fn as clientCredentialsToken, In as createClientCredentialsTokenRequest, Ln as OAuth2Tokens, Mn as createRefreshAccessTokenRequest, Nn as refreshAccessToken, On as validateAuthorizationCode, Pn as createAuthorizationURL, Rn as OAuth2UserInfo, jn as getOAuth2Tokens, kn as validateToken, zn as OAuthProvider } from "../index-X4TpuzeM.mjs";
1
+ import { An as validateToken, Bn as OAuthProvider, Fn as createAuthorizationURL, In as clientCredentialsToken, Ln as createClientCredentialsTokenRequest, Mn as getOAuth2Tokens, Nn as createRefreshAccessTokenRequest, On as createAuthorizationCodeRequest, Pn as refreshAccessToken, Rn as OAuth2Tokens, Vn as ProviderOptions, jn as generateCodeChallenge, kn as validateAuthorizationCode, zn as OAuth2UserInfo } from "../index-CkAWdKH8.mjs";
2
2
  import "../index-CdubV7uy.mjs";
3
3
  export { OAuth2Tokens, OAuth2UserInfo, OAuthProvider, ProviderOptions, clientCredentialsToken, createAuthorizationCodeRequest, createAuthorizationURL, createClientCredentialsTokenRequest, createRefreshAccessTokenRequest, generateCodeChallenge, getOAuth2Tokens, refreshAccessToken, validateAuthorizationCode, validateToken };
@@ -1,3 +1,3 @@
1
- import { a as refreshAccessToken, c as getOAuth2Tokens, i as createRefreshAccessTokenRequest, l as clientCredentialsToken, n as validateAuthorizationCode, o as createAuthorizationURL, r as validateToken, s as generateCodeChallenge, t as createAuthorizationCodeRequest, u as createClientCredentialsTokenRequest } from "../oauth2-D3aE32ZH.mjs";
1
+ import { a as refreshAccessToken, c as getOAuth2Tokens, i as createRefreshAccessTokenRequest, l as clientCredentialsToken, n as validateAuthorizationCode, o as createAuthorizationURL, r as validateToken, s as generateCodeChallenge, t as createAuthorizationCodeRequest, u as createClientCredentialsTokenRequest } from "../oauth2-DmgZmPEg.mjs";
2
2
 
3
3
  export { clientCredentialsToken, createAuthorizationCodeRequest, createAuthorizationURL, createClientCredentialsTokenRequest, createRefreshAccessTokenRequest, generateCodeChallenge, getOAuth2Tokens, refreshAccessToken, validateAuthorizationCode, validateToken };
@@ -65,7 +65,8 @@ function getOAuth2Tokens(data) {
65
65
  accessTokenExpiresAt: data.expires_in ? getDate(data.expires_in) : void 0,
66
66
  refreshTokenExpiresAt: data.refresh_token_expires_in ? getDate(data.refresh_token_expires_in) : void 0,
67
67
  scopes: data?.scope ? typeof data.scope === "string" ? data.scope.split(" ") : data.scope : [],
68
- idToken: data.id_token
68
+ idToken: data.id_token,
69
+ raw: data
69
70
  };
70
71
  }
71
72
  async function generateCodeChallenge(codeVerifier) {
@@ -1,3 +1,3 @@
1
- import { $ as ZoomOptions, $t as microsoft, A as PayPalProfile, At as DropboxOptions, B as NaverOptions, Bt as SpotifyProfile, C as SocialProviders, Cn as getApplePublicKey, Ct as LinearOptions, D as PolarProfile, Dt as KickOptions, E as PolarOptions, Et as linear, F as paybin, Ft as twitter, G as kakao, Gt as HuggingFaceOptions, H as naver, Ht as SlackOptions, I as LineIdTokenPayload, It as TwitchOptions, J as notion, Jt as GoogleOptions, K as NotionOptions, Kt as HuggingFaceProfile, L as LineOptions, Lt as TwitchProfile, M as paypal, Mt as dropbox, N as PaybinOptions, Nt as TwitterOption, O as polar, Ot as KickProfile, P as PaybinProfile, Pt as TwitterProfile, Q as PronounOption, Qt as MicrosoftOptions, R as LineUserInfo, Rt as twitch, S as SocialProviderListEnum, Sn as apple, St as linkedin, T as socialProviders, Tt as LinearUser, U as KakaoOptions, Ut as SlackProfile, V as NaverProfile, Vt as spotify, W as KakaoProfile, Wt as slack, X as LoginType, Xt as google, Y as AccountStatus, Yt as GoogleProfile, Z as PhoneNumber, Zt as MicrosoftEntraIDProfile, _n as AtlassianProfile, _t as GitlabOptions, an as figma, at as SalesforceOptions, b as SocialProvider, bn as AppleOptions, bt as LinkedInOptions, cn as facebook, ct as RobloxOptions, dn as discord, dt as RedditOptions, en as GithubOptions, et as ZoomProfile, fn as CognitoOptions, ft as RedditProfile, gn as AtlassianOptions, gt as tiktok, hn as getCognitoPublicKey, ht as TiktokProfile, in as FigmaProfile, it as vk, j as PayPalTokenResponse, jt as DropboxProfile, k as PayPalOptions, kt as kick, ln as DiscordOptions, lt as RobloxProfile, mn as cognito, mt as TiktokOptions, nn as github, nt as VkOption, on as FacebookOptions, ot as SalesforceProfile, pn as CognitoProfile, pt as reddit, q as NotionProfile, qt as huggingface, rn as FigmaOptions, rt as VkProfile, sn as FacebookProfile, st as salesforce, tn as GithubProfile, tt as zoom, un as DiscordProfile, ut as roblox, vn as atlassian, vt as GitlabProfile, w as socialProviderList, wt as LinearProfile, x as SocialProviderList, xn as AppleProfile, xt as LinkedInProfile, yn as AppleNonConformUser, yt as gitlab, z as line, zt as SpotifyOptions } from "../index-X4TpuzeM.mjs";
1
+ import { $ as PronounOption, $t as MicrosoftOptions, A as PayPalOptions, At as kick, B as line, Bt as SpotifyOptions, C as SocialProviderListEnum, Cn as apple, Ct as linkedin, D as PolarOptions, Dt as linear, E as socialProviders, Et as LinearUser, F as PaybinProfile, Ft as TwitterProfile, G as KakaoProfile, Gt as slack, H as NaverProfile, Ht as spotify, I as paybin, It as twitter, J as NotionProfile, Jt as huggingface, K as kakao, Kt as HuggingFaceOptions, L as LineIdTokenPayload, Lt as TwitchOptions, M as PayPalTokenResponse, Mt as DropboxProfile, N as paypal, Nt as dropbox, O as PolarProfile, Ot as KickOptions, P as PaybinOptions, Pt as TwitterOption, Q as PhoneNumber, Qt as MicrosoftEntraIDProfile, R as LineOptions, Rt as TwitchProfile, S as SocialProviderList, Sn as AppleProfile, St as LinkedInProfile, T as socialProviderList, Tt as LinearProfile, U as naver, Ut as SlackOptions, V as NaverOptions, Vt as SpotifyProfile, W as KakaoOptions, Wt as SlackProfile, X as AccountStatus, Xt as GoogleProfile, Y as notion, Yt as GoogleOptions, Z as LoginType, Zt as google, _n as AtlassianOptions, _t as tiktok, an as FigmaProfile, at as vk, bn as AppleNonConformUser, bt as gitlab, cn as FacebookProfile, ct as salesforce, dn as DiscordProfile, dt as roblox, en as microsoft, et as ZoomOptions, fn as discord, ft as RedditOptions, gn as getCognitoPublicKey, gt as TiktokProfile, hn as cognito, ht as TiktokOptions, in as FigmaOptions, it as VkProfile, j as PayPalProfile, jt as DropboxOptions, k as polar, kt as KickProfile, ln as facebook, lt as RobloxOptions, mn as CognitoProfile, mt as reddit, nn as GithubProfile, nt as zoom, on as figma, ot as SalesforceOptions, pn as CognitoOptions, pt as RedditProfile, q as NotionOptions, qt as HuggingFaceProfile, rn as github, rt as VkOption, sn as FacebookOptions, st as SalesforceProfile, tn as GithubOptions, tt as ZoomProfile, un as DiscordOptions, ut as RobloxProfile, vn as AtlassianProfile, vt as GitlabOptions, w as SocialProviders, wn as getApplePublicKey, wt as LinearOptions, x as SocialProvider, xn as AppleOptions, xt as LinkedInOptions, yn as atlassian, yt as GitlabProfile, z as LineUserInfo, zt as twitch } from "../index-CkAWdKH8.mjs";
2
2
  import "../index-CdubV7uy.mjs";
3
3
  export { AccountStatus, AppleNonConformUser, AppleOptions, AppleProfile, AtlassianOptions, AtlassianProfile, CognitoOptions, CognitoProfile, DiscordOptions, DiscordProfile, DropboxOptions, DropboxProfile, FacebookOptions, FacebookProfile, FigmaOptions, FigmaProfile, GithubOptions, GithubProfile, GitlabOptions, GitlabProfile, GoogleOptions, GoogleProfile, HuggingFaceOptions, HuggingFaceProfile, KakaoOptions, KakaoProfile, KickOptions, KickProfile, LineIdTokenPayload, LineOptions, LineUserInfo, LinearOptions, LinearProfile, LinearUser, LinkedInOptions, LinkedInProfile, LoginType, MicrosoftEntraIDProfile, MicrosoftOptions, NaverOptions, NaverProfile, NotionOptions, NotionProfile, PayPalOptions, PayPalProfile, PayPalTokenResponse, PaybinOptions, PaybinProfile, PhoneNumber, PolarOptions, PolarProfile, PronounOption, RedditOptions, RedditProfile, RobloxOptions, RobloxProfile, SalesforceOptions, SalesforceProfile, SlackOptions, SlackProfile, SocialProvider, SocialProviderList, SocialProviderListEnum, SocialProviders, SpotifyOptions, SpotifyProfile, TiktokOptions, TiktokProfile, TwitchOptions, TwitchProfile, TwitterOption, TwitterProfile, VkOption, VkProfile, ZoomOptions, ZoomProfile, apple, atlassian, cognito, discord, dropbox, facebook, figma, getApplePublicKey, getCognitoPublicKey, github, gitlab, google, huggingface, kakao, kick, line, linear, linkedin, microsoft, naver, notion, paybin, paypal, polar, reddit, roblox, salesforce, slack, socialProviderList, socialProviders, spotify, tiktok, twitch, twitter, vk, zoom };
@@ -1,5 +1,5 @@
1
1
  import { i as logger } from "../env-DwlNAN_D.mjs";
2
- import { a as refreshAccessToken, c as getOAuth2Tokens, n as validateAuthorizationCode, o as createAuthorizationURL, s as generateCodeChallenge } from "../oauth2-D3aE32ZH.mjs";
2
+ import { a as refreshAccessToken, c as getOAuth2Tokens, n as validateAuthorizationCode, o as createAuthorizationURL, s as generateCodeChallenge } from "../oauth2-DmgZmPEg.mjs";
3
3
  import "../utils-C5EN75oV.mjs";
4
4
  import { t as BetterAuthError } from "../error-BhAKg8LX.mjs";
5
5
  import * as z from "zod";
@@ -517,12 +517,12 @@ const facebook = (options) => {
517
517
  };
518
518
  const userMap$1 = await options.mapProfileToUser?.({
519
519
  ...user,
520
- email_verified: true
520
+ email_verified: false
521
521
  });
522
522
  return {
523
523
  user: {
524
524
  ...user,
525
- emailVerified: true,
525
+ emailVerified: false,
526
526
  ...userMap$1
527
527
  },
528
528
  data: profile$1
@@ -766,7 +766,7 @@ const gitlab = (options) => {
766
766
  name: profile.name ?? profile.username,
767
767
  email: profile.email,
768
768
  image: profile.avatar_url,
769
- emailVerified: true,
769
+ emailVerified: profile.email_verified ?? false,
770
770
  ...userMap
771
771
  },
772
772
  data: profile
@@ -1036,7 +1036,7 @@ const kick = (options) => {
1036
1036
  name: profile.name,
1037
1037
  email: profile.email,
1038
1038
  image: profile.profile_picture,
1039
- emailVerified: true,
1039
+ emailVerified: false,
1040
1040
  ...userMap
1041
1041
  },
1042
1042
  data: profile
@@ -1222,7 +1222,7 @@ const linear = (options) => {
1222
1222
  name: profile.data.viewer.name,
1223
1223
  email: profile.data.viewer.email,
1224
1224
  image: profile.data.viewer.avatarUrl,
1225
- emailVerified: true,
1225
+ emailVerified: false,
1226
1226
  ...userMap
1227
1227
  },
1228
1228
  data: userData
@@ -1360,13 +1360,14 @@ const microsoft = (options) => {
1360
1360
  }
1361
1361
  });
1362
1362
  const userMap = await options.mapProfileToUser?.(user);
1363
+ const emailVerified = user.email_verified !== void 0 ? user.email_verified : user.email && (user.verified_primary_email?.includes(user.email) || user.verified_secondary_email?.includes(user.email)) ? true : false;
1363
1364
  return {
1364
1365
  user: {
1365
1366
  id: user.sub,
1366
1367
  name: user.name,
1367
1368
  email: user.email,
1368
1369
  image: user.picture,
1369
- emailVerified: true,
1370
+ emailVerified,
1370
1371
  ...userMap
1371
1372
  },
1372
1373
  data: user
@@ -1788,7 +1789,7 @@ const polar = (options) => {
1788
1789
  name: profile.public_name || profile.username,
1789
1790
  email: profile.email,
1790
1791
  image: profile.avatar_url,
1791
- emailVerified: true,
1792
+ emailVerified: profile.email_verified ?? false,
1792
1793
  ...userMap
1793
1794
  },
1794
1795
  data: profile
@@ -1916,7 +1917,7 @@ const roblox = (options) => {
1916
1917
  name: profile.nickname || profile.preferred_username || "",
1917
1918
  image: profile.picture,
1918
1919
  email: profile.preferred_username || null,
1919
- emailVerified: true,
1920
+ emailVerified: false,
1920
1921
  ...userMap
1921
1922
  },
1922
1923
  data: { ...profile }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/core",
3
- "version": "1.4.0-beta.25",
3
+ "version": "1.4.0-beta.28",
4
4
  "description": "The most comprehensive authentication framework for TypeScript.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",
@@ -103,7 +103,7 @@
103
103
  "@better-auth/utils": "0.3.0",
104
104
  "@better-fetch/fetch": "1.1.18",
105
105
  "@types/better-sqlite3": "^7.6.13",
106
- "better-call": "1.0.28",
106
+ "better-call": "1.1.0",
107
107
  "better-sqlite3": "^12.4.1",
108
108
  "jose": "^6.1.0",
109
109
  "kysely": "^0.28.5",
@@ -117,7 +117,7 @@
117
117
  "peerDependencies": {
118
118
  "@better-auth/utils": "0.3.0",
119
119
  "@better-fetch/fetch": "1.1.18",
120
- "better-call": "1.0.28",
120
+ "better-call": "1.1.0",
121
121
  "jose": "^6.1.0",
122
122
  "kysely": "^0.28.5",
123
123
  "nanostores": "^1.0.1"
@@ -8,6 +8,11 @@ export interface OAuth2Tokens {
8
8
  refreshTokenExpiresAt?: Date | undefined;
9
9
  scopes?: string[] | undefined;
10
10
  idToken?: string | undefined;
11
+ /**
12
+ * Raw token response from the provider.
13
+ * Preserves provider-specific fields that are not part of the standard OAuth2 token response.
14
+ */
15
+ raw?: Record<string, unknown> | undefined;
11
16
  }
12
17
 
13
18
  export type OAuth2UserInfo = {
@@ -23,6 +23,8 @@ export function getOAuth2Tokens(data: Record<string, any>): OAuth2Tokens {
23
23
  : data.scope
24
24
  : [],
25
25
  idToken: data.id_token,
26
+ // Preserve the raw token response for provider-specific fields
27
+ raw: data,
26
28
  };
27
29
  }
28
30
 
@@ -152,15 +152,17 @@ export const facebook = (options: FacebookOptions) => {
152
152
  };
153
153
 
154
154
  // https://developers.facebook.com/docs/facebook-login/limited-login/permissions
155
+ // Facebook ID token does not include email_verified claim.
156
+ // We default to false for security consistency.
155
157
  const userMap = await options.mapProfileToUser?.({
156
158
  ...user,
157
- email_verified: true,
159
+ email_verified: false,
158
160
  });
159
161
 
160
162
  return {
161
163
  user: {
162
164
  ...user,
163
- emailVerified: true,
165
+ emailVerified: false,
164
166
  ...userMap,
165
167
  },
166
168
  data: profile,
@@ -49,6 +49,7 @@ export interface GitlabProfile extends Record<string, any> {
49
49
  commit_email: string;
50
50
  shared_runners_minutes_limit: number;
51
51
  extra_shared_runners_minutes_limit: number;
52
+ email_verified?: boolean | undefined;
52
53
  }
53
54
 
54
55
  export interface GitlabOptions extends ProviderOptions<GitlabProfile> {
@@ -135,13 +136,15 @@ export const gitlab = (options: GitlabOptions) => {
135
136
  return null;
136
137
  }
137
138
  const userMap = await options.mapProfileToUser?.(profile);
139
+ // GitLab may provide email_verified claim, but it's not guaranteed.
140
+ // We check for it first, then default to false for security consistency.
138
141
  return {
139
142
  user: {
140
143
  id: profile.id,
141
144
  name: profile.name ?? profile.username,
142
145
  email: profile.email,
143
146
  image: profile.avatar_url,
144
- emailVerified: true,
147
+ emailVerified: profile.email_verified ?? false,
145
148
  ...userMap,
146
149
  },
147
150
  data: profile,
@@ -74,14 +74,15 @@ export const kick = (options: KickOptions) => {
74
74
  const profile = data.data[0]!;
75
75
 
76
76
  const userMap = await options.mapProfileToUser?.(profile);
77
-
77
+ // Kick does not provide email_verified claim.
78
+ // We default to false for security consistency.
78
79
  return {
79
80
  user: {
80
81
  id: profile.user_id,
81
82
  name: profile.name,
82
83
  email: profile.email,
83
84
  image: profile.profile_picture,
84
- emailVerified: true,
85
+ emailVerified: false,
85
86
  ...userMap,
86
87
  },
87
88
  data: profile,
@@ -102,14 +102,15 @@ export const linear = (options: LinearOptions) => {
102
102
 
103
103
  const userData = profile.data.viewer;
104
104
  const userMap = await options.mapProfileToUser?.(userData);
105
-
105
+ // Linear does not provide email_verified claim.
106
+ // We default to false for security consistency.
106
107
  return {
107
108
  user: {
108
109
  id: profile.data.viewer.id,
109
110
  name: profile.data.viewer.name,
110
111
  email: profile.data.viewer.email,
111
112
  image: profile.data.viewer.avatarUrl,
112
- emailVerified: true,
113
+ emailVerified: false,
113
114
  ...userMap,
114
115
  },
115
116
  data: userData,
@@ -81,6 +81,8 @@ export interface MicrosoftEntraIDProfile extends Record<string, any> {
81
81
  verified_primary_email: string[];
82
82
  /** User's verified secondary email addresses */
83
83
  verified_secondary_email: string[];
84
+ /** Whether the user's email is verified (optional claim, must be configured in app registration) */
85
+ email_verified?: boolean | undefined;
84
86
  /** VNET specifier information */
85
87
  vnet: string;
86
88
  /** Client Capabilities */
@@ -208,13 +210,25 @@ export const microsoft = (options: MicrosoftOptions) => {
208
210
  },
209
211
  );
210
212
  const userMap = await options.mapProfileToUser?.(user);
213
+ // Microsoft Entra ID does NOT include email_verified claim by default.
214
+ // It must be configured as an optional claim in the app registration.
215
+ // We default to false when not provided for security consistency.
216
+ // We can also check verified_primary_email/verified_secondary_email arrays as fallback.
217
+ const emailVerified =
218
+ user.email_verified !== undefined
219
+ ? user.email_verified
220
+ : user.email &&
221
+ (user.verified_primary_email?.includes(user.email) ||
222
+ user.verified_secondary_email?.includes(user.email))
223
+ ? true
224
+ : false;
211
225
  return {
212
226
  user: {
213
227
  id: user.sub,
214
228
  name: user.name,
215
229
  email: user.email,
216
230
  image: user.picture,
217
- emailVerified: true,
231
+ emailVerified,
218
232
  ...userMap,
219
233
  },
220
234
  data: user,
@@ -14,6 +14,7 @@ export interface PolarProfile {
14
14
  github_username?: string | undefined;
15
15
  account_id?: string | undefined;
16
16
  public_name?: string | undefined;
17
+ email_verified?: boolean | undefined;
17
18
  profile_settings?:
18
19
  | {
19
20
  profile_settings_enabled?: boolean;
@@ -90,13 +91,15 @@ export const polar = (options: PolarOptions) => {
90
91
  return null;
91
92
  }
92
93
  const userMap = await options.mapProfileToUser?.(profile);
94
+ // Polar may provide email_verified claim, but it's not guaranteed.
95
+ // We check for it first, then default to false for security consistency.
93
96
  return {
94
97
  user: {
95
98
  id: profile.id,
96
99
  name: profile.public_name || profile.username,
97
100
  email: profile.email,
98
101
  image: profile.avatar_url,
99
- emailVerified: true,
102
+ emailVerified: profile.email_verified ?? false,
100
103
  ...userMap,
101
104
  },
102
105
  data: profile,
@@ -90,14 +90,15 @@ export const roblox = (options: RobloxOptions) => {
90
90
  }
91
91
 
92
92
  const userMap = await options.mapProfileToUser?.(profile);
93
-
93
+ // Roblox does not provide email or email_verified claim.
94
+ // We default to false for security consistency.
94
95
  return {
95
96
  user: {
96
97
  id: profile.sub,
97
98
  name: profile.nickname || profile.preferred_username || "",
98
99
  image: profile.picture,
99
100
  email: profile.preferred_username || null, // Roblox does not provide email
100
- emailVerified: true,
101
+ emailVerified: false,
101
102
  ...userMap,
102
103
  },
103
104
  data: {
@@ -104,16 +104,16 @@ export interface InternalAdapter<
104
104
  account: Omit<Account, "id" | "createdAt" | "updatedAt"> & Partial<Account>,
105
105
  ): Promise<Account>;
106
106
 
107
- // fixme: any type
108
- updateUser(
107
+ // Record<string, any> is to take into account additional fields or plugin-added fields
108
+ updateUser<T extends Record<string, any>>(
109
109
  userId: string,
110
110
  data: Partial<User> & Record<string, any>,
111
- ): Promise<any>;
111
+ ): Promise<User & T>;
112
112
 
113
- updateUserByEmail(
113
+ updateUserByEmail<T extends Record<string, any>>(
114
114
  email: string,
115
115
  data: Partial<User & Record<string, any>>,
116
- ): Promise<User>;
116
+ ): Promise<User & T>;
117
117
 
118
118
  updatePassword(userId: string, password: string): Promise<void>;
119
119
 
@@ -3,5 +3,6 @@ import type { CookieOptions } from "better-call";
3
3
  export type BetterAuthCookies = {
4
4
  sessionToken: { name: string; options: CookieOptions };
5
5
  sessionData: { name: string; options: CookieOptions };
6
+ accountData: { name: string; options: CookieOptions };
6
7
  dontRememberToken: { name: string; options: CookieOptions };
7
8
  };
@@ -17,5 +17,6 @@ export type {
17
17
  BetterAuthClientOptions,
18
18
  BetterAuthClientPlugin,
19
19
  ClientAtomListener,
20
+ ClientFetchOption,
20
21
  ClientStore,
21
22
  } from "./plugin-client";
@@ -193,6 +193,7 @@ export type BetterAuthAdvancedOptions = {
193
193
  * - "session_token"
194
194
  * - "session_data"
195
195
  * - "dont_remember"
196
+ * - "account_data"
196
197
  *
197
198
  * plugins can also add additional cookies
198
199
  */
@@ -256,29 +257,6 @@ export type BetterAuthAdvancedOptions = {
256
257
  generateId?: GenerateIdFn | false | "serial" | "uuid";
257
258
  }
258
259
  | undefined;
259
- /**
260
- * OAuth configuration
261
- */
262
- oauthConfig?:
263
- | {
264
- /**
265
- * Skip state cookie check
266
- *
267
- * ⚠︎ this has security implications and should only be enabled if you know what you are doing.
268
- * @default false
269
- */
270
- skipStateCookieCheck?: boolean;
271
- /**
272
- * Strategy for storing OAuth state
273
- *
274
- * - "cookie": Store state in an encrypted cookie (stateless)
275
- * - "database": Store state in the database
276
- *
277
- * @default "cookie"
278
- */
279
- storeStateStrategy?: "database" | "cookie";
280
- }
281
- | undefined;
282
260
  };
283
261
 
284
262
  export type BetterAuthOptions = {
@@ -921,6 +899,32 @@ export type BetterAuthOptions = {
921
899
  * @default false
922
900
  */
923
901
  encryptOAuthTokens?: boolean;
902
+ /**
903
+ * Skip state cookie check
904
+ *
905
+ * ⚠︎ this has security implications and should only be enabled if you know what you are doing.
906
+ * @default false
907
+ */
908
+ skipStateCookieCheck?: boolean;
909
+ /**
910
+ * Strategy for storing OAuth state
911
+ *
912
+ * - "cookie": Store state in an encrypted cookie (stateless)
913
+ * - "database": Store state in the database
914
+ *
915
+ * @default "cookie"
916
+ */
917
+ storeStateStrategy?: "database" | "cookie";
918
+ /**
919
+ * Store account data after oauth flow on a cookie
920
+ *
921
+ * This is useful for database-less flow
922
+ *
923
+ * @default false
924
+ *
925
+ * @note This is automatically set to true if you haven't passed a database
926
+ */
927
+ storeAccountCookie?: boolean;
924
928
  }
925
929
  | undefined;
926
930
  /**
@@ -19,6 +19,23 @@ export type ClientAtomListener = {
19
19
  signal: "$sessionSignal" | Omit<string, "$sessionSignal">;
20
20
  };
21
21
 
22
+ /**
23
+ * Better-Fetch options but with additional options for the auth-client.
24
+ */
25
+ export type ClientFetchOption<
26
+ Body = any,
27
+ Query extends Record<string, any> = any,
28
+ Params extends Record<string, any> | Array<string> | undefined = any,
29
+ Res = any,
30
+ > = BetterFetchOption<Body, Query, Params, Res> & {
31
+ /**
32
+ * Certain endpoints, upon successful response, will trigger atom signals and thus rerendering all hooks related to that atom.
33
+ *
34
+ * This option is useful when you want to skip hook rerenders.
35
+ */
36
+ disableSignal?: boolean | undefined;
37
+ };
38
+
22
39
  export interface RevalidateOptions {
23
40
  /**
24
41
  * A time interval (in seconds) after which the session will be re-fetched.
@@ -50,7 +67,7 @@ export interface RevalidateOptions {
50
67
  }
51
68
 
52
69
  export interface BetterAuthClientOptions {
53
- fetchOptions?: BetterFetchOption | undefined;
70
+ fetchOptions?: ClientFetchOption | undefined;
54
71
  plugins?: BetterAuthClientPlugin[] | undefined;
55
72
  baseURL?: string | undefined;
56
73
  basePath?: string | undefined;