@better-auth/core 1.4.8-beta.6 → 1.4.8

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.8-beta.6 build /home/runner/work/better-auth/better-auth/packages/core
2
+ > @better-auth/core@1.4.8 build /home/runner/work/better-auth/better-auth/packages/core
3
3
  > tsdown
4
4
 
5
5
  ℹ tsdown v0.17.2 powered by rolldown v1.0.0-beta.53
@@ -7,19 +7,19 @@
7
7
  ℹ entry: src/index.ts, src/db/index.ts, src/db/adapter/index.ts, src/async_hooks/index.ts, src/async_hooks/pure.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  80.60 kB │ gzip: 10.30 kB
11
- ℹ dist/db/adapter/index.mjs  38.13 kB │ gzip: 7.79 kB
10
+ ℹ dist/social-providers/index.mjs  80.96 kB │ gzip: 10.43 kB
11
+ ℹ dist/db/adapter/index.mjs  38.55 kB │ gzip: 7.86 kB
12
12
  ℹ dist/db/index.mjs  1.66 kB │ gzip: 0.54 kB
13
13
  ℹ dist/api/index.mjs  1.23 kB │ gzip: 0.48 kB
14
14
  ℹ dist/async_hooks/index.mjs  1.03 kB │ gzip: 0.54 kB
15
15
  ℹ dist/async_hooks/pure.index.mjs  0.99 kB │ gzip: 0.49 kB
16
+ ℹ dist/oauth2/index.mjs  0.75 kB │ gzip: 0.28 kB
16
17
  ℹ dist/context/index.mjs  0.70 kB │ gzip: 0.24 kB
17
- ℹ dist/oauth2/index.mjs  0.61 kB │ gzip: 0.24 kB
18
18
  ℹ dist/env/index.mjs  0.44 kB │ gzip: 0.25 kB
19
19
  ℹ dist/utils/index.mjs  0.24 kB │ gzip: 0.17 kB
20
20
  ℹ dist/error/index.mjs  0.19 kB │ gzip: 0.14 kB
21
21
  ℹ dist/index.mjs  0.01 kB │ gzip: 0.03 kB
22
- ℹ dist/oauth2-D2y9ALiO.mjs  9.19 kB │ gzip: 2.13 kB
22
+ ℹ dist/oauth2-BjWM15hm.mjs  12.82 kB │ gzip: 3.16 kB
23
23
  ℹ dist/env-DbssmzoK.mjs  7.67 kB │ gzip: 2.54 kB
24
24
  ℹ dist/get-tables-CMc_Emww.mjs  6.76 kB │ gzip: 1.30 kB
25
25
  ℹ dist/context-DblZrIwO.mjs  3.89 kB │ gzip: 1.00 kB
@@ -30,14 +30,14 @@
30
30
  ℹ dist/error/index.d.mts  1.84 kB │ gzip: 0.72 kB
31
31
  ℹ dist/db/adapter/index.d.mts  1.34 kB │ gzip: 0.43 kB
32
32
  ℹ dist/utils/index.d.mts  1.19 kB │ gzip: 0.55 kB
33
- ℹ dist/index.d.mts  0.92 kB │ gzip: 0.35 kB
33
+ ℹ dist/index.d.mts  0.92 kB │ gzip: 0.36 kB
34
+ ℹ dist/oauth2/index.d.mts  0.88 kB │ gzip: 0.32 kB
34
35
  ℹ dist/db/index.d.mts  0.81 kB │ gzip: 0.34 kB
35
- ℹ dist/oauth2/index.d.mts  0.76 kB │ gzip: 0.28 kB
36
36
  ℹ dist/env/index.d.mts  0.59 kB │ gzip: 0.30 kB
37
37
  ℹ dist/api/index.d.mts  0.26 kB │ gzip: 0.14 kB
38
38
  ℹ dist/async_hooks/index.d.mts  0.24 kB │ gzip: 0.16 kB
39
39
  ℹ dist/async_hooks/pure.index.d.mts  0.22 kB │ gzip: 0.16 kB
40
- ℹ dist/index-D0VJf1xh.d.mts 219.53 kB │ gzip: 34.87 kB
40
+ ℹ dist/index-CBdZH5fV.d.mts 221.21 kB │ gzip: 35.26 kB
41
41
  ℹ dist/index-BRBu0-5h.d.mts  3.31 kB │ gzip: 1.11 kB
42
- ℹ 32 files, total: 394.13 kB
43
- ✔ Build complete in 4813ms
42
+ ℹ 32 files, total: 400.50 kB
43
+ ✔ Build complete in 4838ms
@@ -1,2 +1,2 @@
1
- import { a as optionsMiddleware, i as createAuthMiddleware, n as AuthMiddleware, r as createAuthEndpoint, t as AuthEndpoint } from "../index-D0VJf1xh.mjs";
1
+ import { a as optionsMiddleware, i as createAuthMiddleware, n as AuthMiddleware, r as createAuthEndpoint, t as AuthEndpoint } from "../index-CBdZH5fV.mjs";
2
2
  export { AuthEndpoint, AuthMiddleware, createAuthEndpoint, createAuthMiddleware, optionsMiddleware };
@@ -1,4 +1,4 @@
1
- import { Kn as DBAdapter, Zn as DBTransactionAdapter, f as AuthContext } from "../index-D0VJf1xh.mjs";
1
+ import { Yn as DBAdapter, er as DBTransactionAdapter, f as AuthContext } from "../index-CBdZH5fV.mjs";
2
2
  import { AsyncLocalStorage } from "@better-auth/core/async_hooks";
3
3
  import { EndpointContext, InputContext } from "better-call";
4
4
 
@@ -1,2 +1,2 @@
1
- import { $n as JoinOption, Cr as initGetDefaultFieldName, Gn as CustomAdapter, Jn as DBAdapterFactoryConfig, Kn as DBAdapter, Qn as JoinConfig, Sr as initGetDefaultModelName, Wn as CleanedWhere, Xn as DBAdapterSchemaCreation, Yn as DBAdapterInstance, Zn as DBTransactionAdapter, ar as createAdapterFactory, br as initGetFieldName, cr as AdapterFactoryCustomizeAdapterCreator, dr as CreateAdapterOptions, er as Where, fr as CreateCustomAdapter, ir as createAdapter, lr as AdapterFactoryOptions, nr as withApplyDefault, or as AdapterConfig, qn as DBAdapterDebugLogOption, rr as AdapterFactory, sr as AdapterFactoryConfig, tr as deepmerge, ur as AdapterTestDebugLogs, vr as initGetModelName, xr as initGetFieldAttributes, yr as initGetIdField } from "../../index-D0VJf1xh.mjs";
1
+ import { $n as DBAdapterSchemaCreation, Cr as initGetFieldName, Er as initGetDefaultFieldName, Jn as CustomAdapter, Qn as DBAdapterInstance, Sr as initGetIdField, Tr as initGetDefaultModelName, Xn as DBAdapterDebugLogOption, Yn as DBAdapter, Zn as DBAdapterFactoryConfig, ar as withApplyDefault, cr as createAdapterFactory, dr as AdapterFactoryCustomizeAdapterCreator, er as DBTransactionAdapter, fr as AdapterFactoryOptions, hr as CreateCustomAdapter, ir as deepmerge, lr as AdapterConfig, mr as CreateAdapterOptions, nr as JoinOption, or as AdapterFactory, pr as AdapterTestDebugLogs, qn as CleanedWhere, rr as Where, sr as createAdapter, tr as JoinConfig, ur as AdapterFactoryConfig, wr as initGetFieldAttributes, xr as initGetModelName } from "../../index-CBdZH5fV.mjs";
2
2
  export { AdapterConfig, AdapterFactory, AdapterFactoryConfig, AdapterFactoryCustomizeAdapterCreator, AdapterFactoryOptions, AdapterTestDebugLogs, CleanedWhere, CreateAdapterOptions, CreateCustomAdapter, CustomAdapter, DBAdapter, DBAdapterDebugLogOption, DBAdapterFactoryConfig, DBAdapterInstance, DBAdapterSchemaCreation, DBTransactionAdapter, JoinConfig, JoinOption, Where, createAdapter, createAdapterFactory, deepmerge, initGetDefaultFieldName, initGetDefaultModelName, initGetFieldAttributes, initGetFieldName, initGetIdField, initGetModelName, withApplyDefault };
@@ -443,7 +443,7 @@ const createAdapterFactory = ({ adapter: customAdapter, config: cfg }) => (optio
443
443
  }
444
444
  return transformedData;
445
445
  };
446
- const transformWhereClause = ({ model, where }) => {
446
+ const transformWhereClause = ({ model, where, action }) => {
447
447
  if (!where) return void 0;
448
448
  const newMappedKeys = config.mapKeysTransformInput ?? {};
449
449
  return where.map((w) => {
@@ -477,6 +477,15 @@ const createAdapterFactory = ({ adapter: customAdapter, config: cfg }) => (optio
477
477
  } catch (error) {
478
478
  throw new Error(`Failed to stringify JSON value for field ${fieldName}`, { cause: error });
479
479
  }
480
+ if (config.customTransformInput) newValue = config.customTransformInput({
481
+ data: newValue,
482
+ fieldAttributes: fieldAttr,
483
+ field: fieldName,
484
+ model: getModelName(model),
485
+ schema,
486
+ options,
487
+ action
488
+ });
480
489
  return {
481
490
  operator,
482
491
  connector,
@@ -566,7 +575,8 @@ const createAdapterFactory = ({ adapter: customAdapter, config: cfg }) => (optio
566
575
  value,
567
576
  operator: "eq",
568
577
  connector: "AND"
569
- }]
578
+ }],
579
+ action: "findOne"
570
580
  });
571
581
  try {
572
582
  if (joinConfig.relation === "one-to-one") result = await adapterInstance.findOne({
@@ -658,7 +668,8 @@ const createAdapterFactory = ({ adapter: customAdapter, config: cfg }) => (optio
658
668
  const model = getModelName(unsafeModel);
659
669
  const where = transformWhereClause({
660
670
  model: unsafeModel,
661
- where: unsafeWhere
671
+ where: unsafeWhere,
672
+ action: "update"
662
673
  });
663
674
  debugLog({ method: "update" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 4)}`, `${formatMethod("update")} ${formatAction("Unsafe Input")}:`, {
664
675
  model,
@@ -693,7 +704,8 @@ const createAdapterFactory = ({ adapter: customAdapter, config: cfg }) => (optio
693
704
  const model = getModelName(unsafeModel);
694
705
  const where = transformWhereClause({
695
706
  model: unsafeModel,
696
- where: unsafeWhere
707
+ where: unsafeWhere,
708
+ action: "updateMany"
697
709
  });
698
710
  unsafeModel = getDefaultModelName(unsafeModel);
699
711
  debugLog({ method: "updateMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 4)}`, `${formatMethod("updateMany")} ${formatAction("Unsafe Input")}:`, {
@@ -727,7 +739,8 @@ const createAdapterFactory = ({ adapter: customAdapter, config: cfg }) => (optio
727
739
  const model = getModelName(unsafeModel);
728
740
  const where = transformWhereClause({
729
741
  model: unsafeModel,
730
- where: unsafeWhere
742
+ where: unsafeWhere,
743
+ action: "findOne"
731
744
  });
732
745
  unsafeModel = getDefaultModelName(unsafeModel);
733
746
  let join;
@@ -771,7 +784,8 @@ const createAdapterFactory = ({ adapter: customAdapter, config: cfg }) => (optio
771
784
  const model = getModelName(unsafeModel);
772
785
  const where = transformWhereClause({
773
786
  model: unsafeModel,
774
- where: unsafeWhere
787
+ where: unsafeWhere,
788
+ action: "findMany"
775
789
  });
776
790
  unsafeModel = getDefaultModelName(unsafeModel);
777
791
  let join;
@@ -817,7 +831,8 @@ const createAdapterFactory = ({ adapter: customAdapter, config: cfg }) => (optio
817
831
  const model = getModelName(unsafeModel);
818
832
  const where = transformWhereClause({
819
833
  model: unsafeModel,
820
- where: unsafeWhere
834
+ where: unsafeWhere,
835
+ action: "delete"
821
836
  });
822
837
  unsafeModel = getDefaultModelName(unsafeModel);
823
838
  debugLog({ method: "delete" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 2)}`, `${formatMethod("delete")}:`, {
@@ -836,7 +851,8 @@ const createAdapterFactory = ({ adapter: customAdapter, config: cfg }) => (optio
836
851
  const model = getModelName(unsafeModel);
837
852
  const where = transformWhereClause({
838
853
  model: unsafeModel,
839
- where: unsafeWhere
854
+ where: unsafeWhere,
855
+ action: "deleteMany"
840
856
  });
841
857
  unsafeModel = getDefaultModelName(unsafeModel);
842
858
  debugLog({ method: "deleteMany" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 2)}`, `${formatMethod("deleteMany")} ${formatAction("DeleteMany")}:`, {
@@ -859,7 +875,8 @@ const createAdapterFactory = ({ adapter: customAdapter, config: cfg }) => (optio
859
875
  const model = getModelName(unsafeModel);
860
876
  const where = transformWhereClause({
861
877
  model: unsafeModel,
862
- where: unsafeWhere
878
+ where: unsafeWhere,
879
+ action: "count"
863
880
  });
864
881
  unsafeModel = getDefaultModelName(unsafeModel);
865
882
  debugLog({ method: "count" }, `${formatTransactionId(thisTransactionId)} ${formatStep(1, 2)}`, `${formatMethod("count")}:`, {
@@ -1,2 +1,2 @@
1
- import { Ar as sessionSchema, Br as DBFieldAttributeConfig, Dr as userSchema, Er as User, Fr as BetterAuthPluginDBSchema, Hr as DBPrimitive, Ir as getAuthTables, Lr as BaseModelNames, Mr as rateLimitSchema, Nr as Account, Or as coreSchema, Pr as accountSchema, Rr as BetterAuthDBSchema, Tr as verificationSchema, Ur as ModelNames, Vr as DBFieldType, Wr as SecondaryStorage, jr as RateLimit, kr as Session, wr as Verification, zr as DBFieldAttribute } from "../index-D0VJf1xh.mjs";
1
+ import { Ar as userSchema, Br as BaseModelNames, Dr as Verification, Fr as rateLimitSchema, Gr as DBPrimitive, Hr as DBFieldAttribute, Ir as Account, Kr as ModelNames, Lr as accountSchema, Mr as Session, Nr as sessionSchema, Or as verificationSchema, Pr as RateLimit, Rr as BetterAuthPluginDBSchema, Ur as DBFieldAttributeConfig, Vr as BetterAuthDBSchema, Wr as DBFieldType, jr as coreSchema, kr as User, qr as SecondaryStorage, zr as getAuthTables } from "../index-CBdZH5fV.mjs";
2
2
  export { Account, BaseModelNames, BetterAuthDBSchema, BetterAuthPluginDBSchema, DBFieldAttribute, DBFieldAttributeConfig, DBFieldType, DBPrimitive, ModelNames, RateLimit, SecondaryStorage, Session, User, Verification, accountSchema, coreSchema, getAuthTables, rateLimitSchema, sessionSchema, userSchema, verificationSchema };
@@ -2,6 +2,7 @@ import { i as Logger, o as createLogger } from "./index-BRBu0-5h.mjs";
2
2
  import * as z from "zod";
3
3
  import { BetterFetch, BetterFetchOption, BetterFetchPlugin } from "@better-fetch/fetch";
4
4
  import * as jose0 from "jose";
5
+ import { JSONWebKeySet, JWTPayload, JWTVerifyOptions } from "jose";
5
6
  import * as better_call0 from "better-call";
6
7
  import { CookieOptions, Endpoint, EndpointContext, EndpointOptions, InputContext, Middleware, StrictEndpoint } from "better-call";
7
8
  import { StandardSchemaV1, StandardSchemaV1 as StandardSchemaV1$1 } from "@standard-schema/spec";
@@ -451,10 +452,12 @@ type AdapterFactoryCustomizeAdapterCreator = (config: {
451
452
  transformOutput: (data: Record<string, unknown>, defaultModelName: string, select?: string[] | undefined, joinConfig?: JoinConfig | undefined) => Promise<Record<string, unknown>>;
452
453
  transformWhereClause: <W extends Where[] | undefined>({
453
454
  model,
454
- where
455
+ where,
456
+ action
455
457
  }: {
456
458
  where: W;
457
459
  model: string;
460
+ action: "create" | "update" | "findOne" | "findMany" | "updateMany" | "delete" | "deleteMany" | "count";
458
461
  }) => W extends undefined ? undefined : CleanedWhere$1[];
459
462
  }) => CustomAdapter$1;
460
463
  /**
@@ -700,7 +703,7 @@ interface DBAdapterFactoryConfig<Options extends BetterAuthOptions = BetterAuthO
700
703
  /**
701
704
  * The action which was called from the adapter.
702
705
  */
703
- action: "create" | "update" | "findOne" | "findMany";
706
+ action: "create" | "update" | "findOne" | "findMany" | "updateMany" | "delete" | "deleteMany" | "count";
704
707
  /**
705
708
  * The model name.
706
709
  */
@@ -1357,6 +1360,52 @@ declare function validateAuthorizationCode({
1357
1360
  }): Promise<OAuth2Tokens>;
1358
1361
  declare function validateToken(token: string, jwksEndpoint: string): Promise<jose0.JWTVerifyResult<jose0.JWTPayload>>;
1359
1362
  //#endregion
1363
+ //#region src/oauth2/verify.d.ts
1364
+ interface VerifyAccessTokenRemote {
1365
+ /** Full url of the introspect endpoint. Should end with `/oauth2/introspect` */
1366
+ introspectUrl: string;
1367
+ /** Client Secret */
1368
+ clientId: string;
1369
+ /** Client Secret */
1370
+ clientSecret: string;
1371
+ /**
1372
+ * Forces remote verification of a token.
1373
+ * This ensures attached session (if applicable)
1374
+ * is also still active.
1375
+ */
1376
+ force?: boolean;
1377
+ }
1378
+ /**
1379
+ * Performs local verification of an access token for your APIs.
1380
+ *
1381
+ * Can also be configured for remote verification.
1382
+ */
1383
+ declare function verifyJwsAccessToken(token: string, opts: {
1384
+ /** Jwks url or promise of a Jwks */
1385
+ jwksFetch: string | (() => Promise<JSONWebKeySet | undefined>);
1386
+ /** Verify options */
1387
+ verifyOptions: JWTVerifyOptions & Required<Pick<JWTVerifyOptions, "audience" | "issuer">>;
1388
+ }): Promise<JWTPayload>;
1389
+ declare function getJwks(token: string, opts: {
1390
+ /** Jwks url or promise of a Jwks */
1391
+ jwksFetch: string | (() => Promise<JSONWebKeySet | undefined>);
1392
+ }): Promise<JSONWebKeySet>;
1393
+ /**
1394
+ * Performs local verification of an access token for your API.
1395
+ *
1396
+ * Can also be configured for remote verification.
1397
+ */
1398
+ declare function verifyAccessToken(token: string, opts: {
1399
+ /** Verify options */
1400
+ verifyOptions: JWTVerifyOptions & Required<Pick<JWTVerifyOptions, "audience" | "issuer">>;
1401
+ /** Scopes to additionally verify. Token must include all but not exact. */
1402
+ scopes?: string[];
1403
+ /** Required to verify access token locally */
1404
+ jwksUrl?: string;
1405
+ /** If provided, can verify a token remotely */
1406
+ remoteVerify?: VerifyAccessTokenRemote;
1407
+ }): Promise<JWTPayload>;
1408
+ //#endregion
1360
1409
  //#region src/types/cookie.d.ts
1361
1410
  type BetterAuthCookies = {
1362
1411
  sessionToken: {
@@ -7139,16 +7188,8 @@ type BetterAuthOptions = {
7139
7188
  } | undefined;
7140
7189
  /**
7141
7190
  * List of trusted origins.
7142
- *
7143
- * @param request - The request object.
7144
- * It'll be undefined if no request was
7145
- * made. Like during a create context call
7146
- * or `auth.api` call.
7147
- *
7148
- * Trusted origins will be dynamically
7149
- * calculated based on the request.
7150
7191
  */
7151
- trustedOrigins?: (string[] | ((request?: Request | undefined) => Awaitable<string[]>)) | undefined;
7192
+ trustedOrigins?: (string[] | ((request: Request) => Awaitable<string[]>)) | undefined;
7152
7193
  /**
7153
7194
  * Rate limiting configuration
7154
7195
  */
@@ -7771,4 +7812,4 @@ declare function createAuthEndpoint<Path extends string, Options extends Endpoin
7771
7812
  type AuthEndpoint<Path extends string, Opts extends EndpointOptions, R> = ReturnType<typeof createAuthEndpoint<Path, Opts, R>>;
7772
7813
  type AuthMiddleware = ReturnType<typeof createAuthMiddleware>;
7773
7814
  //#endregion
7774
- export { AccountStatus as $, JoinOption as $n, GoogleProfile as $t, PolarOptions as A, createAuthorizationCodeRequest as An, sessionSchema as Ar, linear as At, LineIdTokenPayload as B, OAuth2Tokens as Bn, DBFieldAttributeConfig as Br, TwitchOptions as Bt, SocialProviderListEnum as C, atlassian as Cn, initGetDefaultFieldName as Cr, gitlab as Ct, VercelOptions as D, apple as Dn, userSchema as Dr, LinearOptions as Dt, socialProviders as E, AppleProfile as En, User as Er, linkedin as Et, PayPalTokenResponse as F, createRefreshAccessTokenRequest as Fn, BetterAuthPluginDBSchema as Fr, DropboxProfile as Ft, NaverProfile as G, CustomAdapter as Gn, spotify as Gt, LineUserInfo as H, OAuthProvider as Hn, DBPrimitive as Hr, twitch as Ht, paypal as I, refreshAccessToken as In, getAuthTables as Ir, dropbox as It, KakaoProfile as J, DBAdapterFactoryConfig as Jn, slack as Jt, naver as K, DBAdapter as Kn, SlackOptions as Kt, PaybinOptions as L, createAuthorizationURL as Ln, BaseModelNames as Lr, TwitterOption as Lt, polar as M, validateToken as Mn, rateLimitSchema as Mr, KickProfile as Mt, PayPalOptions as N, generateCodeChallenge as Nn, Account as Nr, kick as Nt, VercelProfile as O, getApplePublicKey as On, coreSchema as Or, LinearProfile as Ot, PayPalProfile as P, getOAuth2Tokens as Pn, accountSchema as Pr, DropboxOptions as Pt, notion as Q, JoinConfig as Qn, GoogleOptions as Qt, PaybinProfile as R, clientCredentialsToken as Rn, BetterAuthDBSchema as Rr, TwitterProfile as Rt, SocialProviderList as S, AtlassianProfile as Sn, initGetDefaultModelName as Sr, GitlabProfile as St, socialProviderList as T, AppleOptions as Tn, verificationSchema as Tr, LinkedInProfile as Tt, line as U, ProviderOptions as Un, ModelNames as Ur, SpotifyOptions as Ut, LineOptions as V, OAuth2UserInfo as Vn, DBFieldType as Vr, TwitchProfile as Vt, NaverOptions as W, CleanedWhere as Wn, SecondaryStorage as Wr, SpotifyProfile as Wt, NotionOptions as X, DBAdapterSchemaCreation as Xn, HuggingFaceProfile as Xt, kakao as Y, DBAdapterInstance as Yn, HuggingFaceOptions as Yt, NotionProfile as Z, DBTransactionAdapter as Zn, huggingface as Zt, BetterAuthRateLimitOptions as _, CognitoOptions as _n, Primitive as _r, reddit as _t, optionsMiddleware as a, GithubOptions as an, createAdapterFactory as ar, zoom as at, HookEndpointContext as b, getCognitoPublicKey as bn, initGetFieldName as br, tiktok as bt, BetterAuthClientPlugin as c, FigmaOptions as cn, AdapterFactoryCustomizeAdapterCreator as cr, vk as ct, ClientStore as d, FacebookOptions as dn, CreateAdapterOptions as dr, salesforce as dt, getGooglePublicKey as en, Where as er, LoginType as et, AuthContext as f, FacebookProfile as fn, CreateCustomAdapter as fr, RobloxOptions as ft, BetterAuthOptions as g, discord as gn, Prettify as gr, RedditProfile as gt, BetterAuthAdvancedOptions as h, DiscordProfile as hn, LiteralUnion as hr, RedditOptions as ht, createAuthMiddleware as i, microsoft as in, createAdapter as ir, ZoomProfile as it, PolarProfile as j, validateAuthorizationCode as jn, RateLimit as jr, KickOptions as jt, vercel as k, BetterAuthCookies as kn, Session as kr, LinearUser as kt, ClientAtomListener as l, FigmaProfile as ln, AdapterFactoryOptions as lr, SalesforceOptions as lt, InternalAdapter as m, DiscordOptions as mn, LiteralString as mr, roblox as mt, AuthMiddleware as n, MicrosoftEntraIDProfile as nn, withApplyDefault as nr, PronounOption as nt, StandardSchemaV1$1 as o, GithubProfile as on, AdapterConfig as or, VkOption as ot, GenericEndpointContext as p, facebook as pn, Awaitable as pr, RobloxProfile as pt, KakaoOptions as q, DBAdapterDebugLogOption as qn, SlackProfile as qt, createAuthEndpoint as r, MicrosoftOptions as rn, AdapterFactory as rr, ZoomOptions as rt, BetterAuthClientOptions as s, github as sn, AdapterFactoryConfig as sr, VkProfile as st, AuthEndpoint as t, google as tn, deepmerge as tr, PhoneNumber as tt, ClientFetchOption as u, figma as un, AdapterTestDebugLogs as ur, SalesforceProfile as ut, GenerateIdFn as v, CognitoProfile as vn, initGetModelName as vr, TiktokOptions as vt, SocialProviders as w, AppleNonConformUser as wn, Verification as wr, LinkedInOptions as wt, SocialProvider as x, AtlassianOptions as xn, initGetFieldAttributes as xr, GitlabOptions as xt, BetterAuthPlugin as y, cognito as yn, initGetIdField as yr, TiktokProfile as yt, paybin as z, createClientCredentialsTokenRequest as zn, DBFieldAttribute as zr, twitter as zt };
7815
+ export { AccountStatus as $, DBAdapterSchemaCreation as $n, GoogleProfile as $t, PolarOptions as A, getJwks as An, userSchema as Ar, linear as At, LineIdTokenPayload as B, createAuthorizationURL as Bn, BaseModelNames as Br, TwitchOptions as Bt, SocialProviderListEnum as C, atlassian as Cn, initGetFieldName as Cr, gitlab as Ct, VercelOptions as D, apple as Dn, Verification as Dr, LinearOptions as Dt, socialProviders as E, AppleProfile as En, initGetDefaultFieldName as Er, linkedin as Et, PayPalTokenResponse as F, validateToken as Fn, rateLimitSchema as Fr, DropboxProfile as Ft, NaverProfile as G, OAuthProvider as Gn, DBPrimitive as Gr, spotify as Gt, LineUserInfo as H, createClientCredentialsTokenRequest as Hn, DBFieldAttribute as Hr, twitch as Ht, paypal as I, generateCodeChallenge as In, Account as Ir, dropbox as It, KakaoProfile as J, CustomAdapter as Jn, slack as Jt, naver as K, ProviderOptions as Kn, ModelNames as Kr, SlackOptions as Kt, PaybinOptions as L, getOAuth2Tokens as Ln, accountSchema as Lr, TwitterOption as Lt, polar as M, verifyJwsAccessToken as Mn, Session as Mr, KickProfile as Mt, PayPalOptions as N, createAuthorizationCodeRequest as Nn, sessionSchema as Nr, kick as Nt, VercelProfile as O, getApplePublicKey as On, verificationSchema as Or, LinearProfile as Ot, PayPalProfile as P, validateAuthorizationCode as Pn, RateLimit as Pr, DropboxOptions as Pt, notion as Q, DBAdapterInstance as Qn, GoogleOptions as Qt, PaybinProfile as R, createRefreshAccessTokenRequest as Rn, BetterAuthPluginDBSchema as Rr, TwitterProfile as Rt, SocialProviderList as S, AtlassianProfile as Sn, initGetIdField as Sr, GitlabProfile as St, socialProviderList as T, AppleOptions as Tn, initGetDefaultModelName as Tr, LinkedInProfile as Tt, line as U, OAuth2Tokens as Un, DBFieldAttributeConfig as Ur, SpotifyOptions as Ut, LineOptions as V, clientCredentialsToken as Vn, BetterAuthDBSchema as Vr, TwitchProfile as Vt, NaverOptions as W, OAuth2UserInfo as Wn, DBFieldType as Wr, SpotifyProfile as Wt, NotionOptions as X, DBAdapterDebugLogOption as Xn, HuggingFaceProfile as Xt, kakao as Y, DBAdapter as Yn, HuggingFaceOptions as Yt, NotionProfile as Z, DBAdapterFactoryConfig as Zn, huggingface as Zt, BetterAuthRateLimitOptions as _, CognitoOptions as _n, LiteralString as _r, reddit as _t, optionsMiddleware as a, GithubOptions as an, withApplyDefault as ar, zoom as at, HookEndpointContext as b, getCognitoPublicKey as bn, Primitive as br, tiktok as bt, BetterAuthClientPlugin as c, FigmaOptions as cn, createAdapterFactory as cr, vk as ct, ClientStore as d, FacebookOptions as dn, AdapterFactoryCustomizeAdapterCreator as dr, salesforce as dt, getGooglePublicKey as en, DBTransactionAdapter as er, LoginType as et, AuthContext as f, FacebookProfile as fn, AdapterFactoryOptions as fr, RobloxOptions as ft, BetterAuthOptions as g, discord as gn, Awaitable as gr, RedditProfile as gt, BetterAuthAdvancedOptions as h, DiscordProfile as hn, CreateCustomAdapter as hr, RedditOptions as ht, createAuthMiddleware as i, microsoft as in, deepmerge as ir, ZoomProfile as it, PolarProfile as j, verifyAccessToken as jn, coreSchema as jr, KickOptions as jt, vercel as k, BetterAuthCookies as kn, User as kr, LinearUser as kt, ClientAtomListener as l, FigmaProfile as ln, AdapterConfig as lr, SalesforceOptions as lt, InternalAdapter as m, DiscordOptions as mn, CreateAdapterOptions as mr, roblox as mt, AuthMiddleware as n, MicrosoftEntraIDProfile as nn, JoinOption as nr, PronounOption as nt, StandardSchemaV1$1 as o, GithubProfile as on, AdapterFactory as or, VkOption as ot, GenericEndpointContext as p, facebook as pn, AdapterTestDebugLogs as pr, RobloxProfile as pt, KakaoOptions as q, CleanedWhere as qn, SecondaryStorage as qr, SlackProfile as qt, createAuthEndpoint as r, MicrosoftOptions as rn, Where as rr, ZoomOptions as rt, BetterAuthClientOptions as s, github as sn, createAdapter as sr, VkProfile as st, AuthEndpoint as t, google as tn, JoinConfig as tr, PhoneNumber as tt, ClientFetchOption as u, figma as un, AdapterFactoryConfig as ur, SalesforceProfile as ut, GenerateIdFn as v, CognitoProfile as vn, LiteralUnion as vr, TiktokOptions as vt, SocialProviders as w, AppleNonConformUser as wn, initGetFieldAttributes as wr, LinkedInOptions as wt, SocialProvider as x, AtlassianOptions as xn, initGetModelName as xr, GitlabOptions as xt, BetterAuthPlugin as y, cognito as yn, Prettify as yr, TiktokProfile as yt, paybin as z, refreshAccessToken as zn, getAuthTables as zr, twitter as zt };
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as BetterAuthRateLimitOptions, _r as Primitive, b as HookEndpointContext, c as BetterAuthClientPlugin, d as ClientStore, f as AuthContext, g as BetterAuthOptions, gr as Prettify, h as BetterAuthAdvancedOptions, hr as LiteralUnion, kn as BetterAuthCookies, l as ClientAtomListener, m as InternalAdapter, mr as LiteralString, o as StandardSchemaV1, p as GenericEndpointContext, pr as Awaitable, s as BetterAuthClientOptions, u as ClientFetchOption, v as GenerateIdFn, y as BetterAuthPlugin } from "./index-D0VJf1xh.mjs";
1
+ import { _ as BetterAuthRateLimitOptions, _r as LiteralString, b as HookEndpointContext, br as Primitive, c as BetterAuthClientPlugin, d as ClientStore, f as AuthContext, g as BetterAuthOptions, gr as Awaitable, h as BetterAuthAdvancedOptions, kn as BetterAuthCookies, l as ClientAtomListener, m as InternalAdapter, o as StandardSchemaV1, p as GenericEndpointContext, s as BetterAuthClientOptions, u as ClientFetchOption, v as GenerateIdFn, vr as LiteralUnion, y as BetterAuthPlugin, yr as Prettify } from "./index-CBdZH5fV.mjs";
2
2
  export { AuthContext, Awaitable, BetterAuthAdvancedOptions, BetterAuthClientOptions, BetterAuthClientPlugin, BetterAuthCookies, BetterAuthOptions, BetterAuthPlugin, BetterAuthRateLimitOptions, ClientAtomListener, ClientFetchOption, ClientStore, GenerateIdFn, GenericEndpointContext, HookEndpointContext, InternalAdapter, LiteralString, LiteralUnion, Prettify, Primitive, StandardSchemaV1 };
@@ -1,2 +1,2 @@
1
- import { An as createAuthorizationCodeRequest, Bn as OAuth2Tokens, Fn as createRefreshAccessTokenRequest, Hn as OAuthProvider, In as refreshAccessToken, Ln as createAuthorizationURL, Mn as validateToken, Nn as generateCodeChallenge, Pn as getOAuth2Tokens, Rn as clientCredentialsToken, Un as ProviderOptions, Vn as OAuth2UserInfo, jn as validateAuthorizationCode, zn as createClientCredentialsTokenRequest } from "../index-D0VJf1xh.mjs";
2
- export { OAuth2Tokens, OAuth2UserInfo, OAuthProvider, ProviderOptions, clientCredentialsToken, createAuthorizationCodeRequest, createAuthorizationURL, createClientCredentialsTokenRequest, createRefreshAccessTokenRequest, generateCodeChallenge, getOAuth2Tokens, refreshAccessToken, validateAuthorizationCode, validateToken };
1
+ import { An as getJwks, Bn as createAuthorizationURL, Fn as validateToken, Gn as OAuthProvider, Hn as createClientCredentialsTokenRequest, In as generateCodeChallenge, Kn as ProviderOptions, Ln as getOAuth2Tokens, Mn as verifyJwsAccessToken, Nn as createAuthorizationCodeRequest, Pn as validateAuthorizationCode, Rn as createRefreshAccessTokenRequest, Un as OAuth2Tokens, Vn as clientCredentialsToken, Wn as OAuth2UserInfo, jn as verifyAccessToken, zn as refreshAccessToken } from "../index-CBdZH5fV.mjs";
2
+ export { OAuth2Tokens, OAuth2UserInfo, OAuthProvider, ProviderOptions, clientCredentialsToken, createAuthorizationCodeRequest, createAuthorizationURL, createClientCredentialsTokenRequest, createRefreshAccessTokenRequest, generateCodeChallenge, getJwks, getOAuth2Tokens, refreshAccessToken, validateAuthorizationCode, validateToken, verifyAccessToken, verifyJwsAccessToken };
@@ -1,3 +1,4 @@
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-D2y9ALiO.mjs";
1
+ import "../env-DbssmzoK.mjs";
2
+ import { a as validateAuthorizationCode, c as refreshAccessToken, d as getOAuth2Tokens, f as clientCredentialsToken, i as createAuthorizationCodeRequest, l as createAuthorizationURL, n as verifyAccessToken, o as validateToken, p as createClientCredentialsTokenRequest, r as verifyJwsAccessToken, s as createRefreshAccessTokenRequest, t as getJwks, u as generateCodeChallenge } from "../oauth2-BjWM15hm.mjs";
2
3
 
3
- export { clientCredentialsToken, createAuthorizationCodeRequest, createAuthorizationURL, createClientCredentialsTokenRequest, createRefreshAccessTokenRequest, generateCodeChallenge, getOAuth2Tokens, refreshAccessToken, validateAuthorizationCode, validateToken };
4
+ export { clientCredentialsToken, createAuthorizationCodeRequest, createAuthorizationURL, createClientCredentialsTokenRequest, createRefreshAccessTokenRequest, generateCodeChallenge, getJwks, getOAuth2Tokens, refreshAccessToken, validateAuthorizationCode, validateToken, verifyAccessToken, verifyJwsAccessToken };
@@ -1,6 +1,8 @@
1
+ import { i as logger } from "./env-DbssmzoK.mjs";
1
2
  import { base64, base64Url } from "@better-auth/utils/base64";
2
3
  import { betterFetch } from "@better-fetch/fetch";
3
- import { jwtVerify } from "jose";
4
+ import { UnsecuredJWT, createLocalJWKSet, decodeProtectedHeader, jwtVerify } from "jose";
5
+ import { APIError } from "better-call";
4
6
 
5
7
  //#region src/oauth2/client-credentials-token.ts
6
8
  function createClientCredentialsTokenRequest({ options, scope, authentication, resource }) {
@@ -233,4 +235,92 @@ async function validateToken(token, jwksEndpoint) {
233
235
  }
234
236
 
235
237
  //#endregion
236
- export { refreshAccessToken as a, getOAuth2Tokens as c, createRefreshAccessTokenRequest as i, clientCredentialsToken as l, validateAuthorizationCode as n, createAuthorizationURL as o, validateToken as r, generateCodeChallenge as s, createAuthorizationCodeRequest as t, createClientCredentialsTokenRequest as u };
238
+ //#region src/oauth2/verify.ts
239
+ /** Last fetched jwks used locally in getJwks @internal */
240
+ let jwks;
241
+ /**
242
+ * Performs local verification of an access token for your APIs.
243
+ *
244
+ * Can also be configured for remote verification.
245
+ */
246
+ async function verifyJwsAccessToken(token, opts) {
247
+ try {
248
+ const jwt = await jwtVerify(token, createLocalJWKSet(await getJwks(token, opts)), opts.verifyOptions);
249
+ if (jwt.payload.azp) jwt.payload.client_id = jwt.payload.azp;
250
+ return jwt.payload;
251
+ } catch (error) {
252
+ if (error instanceof Error) throw error;
253
+ throw new Error(error);
254
+ }
255
+ }
256
+ async function getJwks(token, opts) {
257
+ let jwtHeaders;
258
+ try {
259
+ jwtHeaders = decodeProtectedHeader(token);
260
+ } catch (error) {
261
+ if (error instanceof Error) throw error;
262
+ throw new Error(error);
263
+ }
264
+ if (!jwtHeaders.kid) throw new Error("Missing jwt kid");
265
+ if (!jwks || !jwks.keys.find((jwk) => jwk.kid === jwtHeaders.kid)) {
266
+ jwks = typeof opts.jwksFetch === "string" ? await betterFetch(opts.jwksFetch, { headers: { Accept: "application/json" } }).then(async (res) => {
267
+ if (res.error) throw new Error(`Jwks failed: ${res.error.message ?? res.error.statusText}`);
268
+ return res.data;
269
+ }) : await opts.jwksFetch();
270
+ if (!jwks) throw new Error("No jwks found");
271
+ }
272
+ return jwks;
273
+ }
274
+ /**
275
+ * Performs local verification of an access token for your API.
276
+ *
277
+ * Can also be configured for remote verification.
278
+ */
279
+ async function verifyAccessToken(token, opts) {
280
+ let payload;
281
+ if (opts.jwksUrl && !opts?.remoteVerify?.force) try {
282
+ payload = await verifyJwsAccessToken(token, {
283
+ jwksFetch: opts.jwksUrl,
284
+ verifyOptions: opts.verifyOptions
285
+ });
286
+ } catch (error) {
287
+ if (error instanceof Error) if (error.name === "TypeError" || error.name === "JWSInvalid") {} else if (error.name === "JWTExpired") throw new APIError("UNAUTHORIZED", { message: "token expired" });
288
+ else if (error.name === "JWTInvalid") throw new APIError("UNAUTHORIZED", { message: "token invalid" });
289
+ else throw error;
290
+ else throw new Error(error);
291
+ }
292
+ if (opts?.remoteVerify) {
293
+ const { data: introspect, error: introspectError } = await betterFetch(opts.remoteVerify.introspectUrl, {
294
+ method: "POST",
295
+ headers: {
296
+ Accept: "application/json",
297
+ "Content-Type": "application/x-www-form-urlencoded"
298
+ },
299
+ body: new URLSearchParams({
300
+ client_id: opts.remoteVerify.clientId,
301
+ client_secret: opts.remoteVerify.clientSecret,
302
+ token,
303
+ token_type_hint: "access_token"
304
+ }).toString()
305
+ });
306
+ if (introspectError) logger.error(`Introspection failed: ${introspectError.message ?? introspectError.statusText}`);
307
+ if (!introspect) throw new APIError("INTERNAL_SERVER_ERROR", { message: "introspection failed" });
308
+ if (!introspect.active) throw new APIError("UNAUTHORIZED", { message: "token inactive" });
309
+ try {
310
+ const unsecuredJwt = new UnsecuredJWT(introspect).encode();
311
+ const { audience: _audience, ...verifyOptions } = opts.verifyOptions;
312
+ payload = (introspect.aud ? UnsecuredJWT.decode(unsecuredJwt, opts.verifyOptions) : UnsecuredJWT.decode(unsecuredJwt, verifyOptions)).payload;
313
+ } catch (error) {
314
+ throw new Error(error);
315
+ }
316
+ }
317
+ if (!payload) throw new APIError("UNAUTHORIZED", { message: `no token payload` });
318
+ if (opts.scopes) {
319
+ const validScopes = new Set(payload.scope?.split(" "));
320
+ for (const sc of opts.scopes) if (!validScopes.has(sc)) throw new APIError("FORBIDDEN", { message: `invalid scope ${sc}` });
321
+ }
322
+ return payload;
323
+ }
324
+
325
+ //#endregion
326
+ export { validateAuthorizationCode as a, refreshAccessToken as c, getOAuth2Tokens as d, clientCredentialsToken as f, createAuthorizationCodeRequest as i, createAuthorizationURL as l, verifyAccessToken as n, validateToken as o, createClientCredentialsTokenRequest as p, verifyJwsAccessToken as r, createRefreshAccessTokenRequest as s, getJwks as t, generateCodeChallenge as u };
@@ -1,2 +1,2 @@
1
- import { $ as AccountStatus, $t as GoogleProfile, A as PolarOptions, At as linear, B as LineIdTokenPayload, Bt as TwitchOptions, C as SocialProviderListEnum, Cn as atlassian, Ct as gitlab, D as VercelOptions, Dn as apple, Dt as LinearOptions, E as socialProviders, En as AppleProfile, Et as linkedin, F as PayPalTokenResponse, Ft as DropboxProfile, G as NaverProfile, Gt as spotify, H as LineUserInfo, Ht as twitch, I as paypal, It as dropbox, J as KakaoProfile, Jt as slack, K as naver, Kt as SlackOptions, L as PaybinOptions, Lt as TwitterOption, M as polar, Mt as KickProfile, N as PayPalOptions, Nt as kick, O as VercelProfile, On as getApplePublicKey, Ot as LinearProfile, P as PayPalProfile, Pt as DropboxOptions, Q as notion, Qt as GoogleOptions, R as PaybinProfile, Rt as TwitterProfile, S as SocialProviderList, Sn as AtlassianProfile, St as GitlabProfile, T as socialProviderList, Tn as AppleOptions, Tt as LinkedInProfile, U as line, Ut as SpotifyOptions, V as LineOptions, Vt as TwitchProfile, W as NaverOptions, Wt as SpotifyProfile, X as NotionOptions, Xt as HuggingFaceProfile, Y as kakao, Yt as HuggingFaceOptions, Z as NotionProfile, Zt as huggingface, _n as CognitoOptions, _t as reddit, an as GithubOptions, at as zoom, bn as getCognitoPublicKey, bt as tiktok, cn as FigmaOptions, ct as vk, dn as FacebookOptions, dt as salesforce, en as getGooglePublicKey, et as LoginType, fn as FacebookProfile, ft as RobloxOptions, gn as discord, gt as RedditProfile, hn as DiscordProfile, ht as RedditOptions, in as microsoft, it as ZoomProfile, j as PolarProfile, jt as KickOptions, k as vercel, kt as LinearUser, ln as FigmaProfile, lt as SalesforceOptions, mn as DiscordOptions, mt as roblox, nn as MicrosoftEntraIDProfile, nt as PronounOption, on as GithubProfile, ot as VkOption, pn as facebook, pt as RobloxProfile, q as KakaoOptions, qt as SlackProfile, rn as MicrosoftOptions, rt as ZoomOptions, sn as github, st as VkProfile, tn as google, tt as PhoneNumber, un as figma, ut as SalesforceProfile, vn as CognitoProfile, vt as TiktokOptions, w as SocialProviders, wn as AppleNonConformUser, wt as LinkedInOptions, x as SocialProvider, xn as AtlassianOptions, xt as GitlabOptions, yn as cognito, yt as TiktokProfile, z as paybin, zt as twitter } from "../index-D0VJf1xh.mjs";
1
+ import { $ as AccountStatus, $t as GoogleProfile, A as PolarOptions, At as linear, B as LineIdTokenPayload, Bt as TwitchOptions, C as SocialProviderListEnum, Cn as atlassian, Ct as gitlab, D as VercelOptions, Dn as apple, Dt as LinearOptions, E as socialProviders, En as AppleProfile, Et as linkedin, F as PayPalTokenResponse, Ft as DropboxProfile, G as NaverProfile, Gt as spotify, H as LineUserInfo, Ht as twitch, I as paypal, It as dropbox, J as KakaoProfile, Jt as slack, K as naver, Kt as SlackOptions, L as PaybinOptions, Lt as TwitterOption, M as polar, Mt as KickProfile, N as PayPalOptions, Nt as kick, O as VercelProfile, On as getApplePublicKey, Ot as LinearProfile, P as PayPalProfile, Pt as DropboxOptions, Q as notion, Qt as GoogleOptions, R as PaybinProfile, Rt as TwitterProfile, S as SocialProviderList, Sn as AtlassianProfile, St as GitlabProfile, T as socialProviderList, Tn as AppleOptions, Tt as LinkedInProfile, U as line, Ut as SpotifyOptions, V as LineOptions, Vt as TwitchProfile, W as NaverOptions, Wt as SpotifyProfile, X as NotionOptions, Xt as HuggingFaceProfile, Y as kakao, Yt as HuggingFaceOptions, Z as NotionProfile, Zt as huggingface, _n as CognitoOptions, _t as reddit, an as GithubOptions, at as zoom, bn as getCognitoPublicKey, bt as tiktok, cn as FigmaOptions, ct as vk, dn as FacebookOptions, dt as salesforce, en as getGooglePublicKey, et as LoginType, fn as FacebookProfile, ft as RobloxOptions, gn as discord, gt as RedditProfile, hn as DiscordProfile, ht as RedditOptions, in as microsoft, it as ZoomProfile, j as PolarProfile, jt as KickOptions, k as vercel, kt as LinearUser, ln as FigmaProfile, lt as SalesforceOptions, mn as DiscordOptions, mt as roblox, nn as MicrosoftEntraIDProfile, nt as PronounOption, on as GithubProfile, ot as VkOption, pn as facebook, pt as RobloxProfile, q as KakaoOptions, qt as SlackProfile, rn as MicrosoftOptions, rt as ZoomOptions, sn as github, st as VkProfile, tn as google, tt as PhoneNumber, un as figma, ut as SalesforceProfile, vn as CognitoProfile, vt as TiktokOptions, w as SocialProviders, wn as AppleNonConformUser, wt as LinkedInOptions, x as SocialProvider, xn as AtlassianOptions, xt as GitlabOptions, yn as cognito, yt as TiktokProfile, z as paybin, zt as twitter } from "../index-CBdZH5fV.mjs";
2
2
  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, VercelOptions, VercelProfile, VkOption, VkProfile, ZoomOptions, ZoomProfile, apple, atlassian, cognito, discord, dropbox, facebook, figma, getApplePublicKey, getCognitoPublicKey, getGooglePublicKey, 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, vercel, vk, zoom };
@@ -1,7 +1,7 @@
1
1
  import { i as logger } from "../env-DbssmzoK.mjs";
2
2
  import "../utils-NloIXYE0.mjs";
3
3
  import { t as BetterAuthError } from "../error-CzMAIrPb.mjs";
4
- import { a as refreshAccessToken, c as getOAuth2Tokens, n as validateAuthorizationCode, o as createAuthorizationURL, s as generateCodeChallenge } from "../oauth2-D2y9ALiO.mjs";
4
+ import { a as validateAuthorizationCode, c as refreshAccessToken, d as getOAuth2Tokens, l as createAuthorizationURL, u as generateCodeChallenge } from "../oauth2-BjWM15hm.mjs";
5
5
  import * as z from "zod";
6
6
  import { base64 } from "@better-auth/utils/base64";
7
7
  import { betterFetch } from "@better-fetch/fetch";
@@ -203,7 +203,7 @@ const cognito = (options) => {
203
203
  ];
204
204
  if (options.scope) _scopes.push(...options.scope);
205
205
  if (scopes) _scopes.push(...scopes);
206
- return await createAuthorizationURL({
206
+ const url = await createAuthorizationURL({
207
207
  id: "cognito",
208
208
  options: { ...options },
209
209
  authorizationEndpoint,
@@ -213,6 +213,15 @@ const cognito = (options) => {
213
213
  redirectURI,
214
214
  prompt: options.prompt
215
215
  });
216
+ const scopeValue = url.searchParams.get("scope");
217
+ if (scopeValue) {
218
+ url.searchParams.delete("scope");
219
+ const encodedScope = encodeURIComponent(scopeValue);
220
+ const urlString = url.toString();
221
+ const separator = urlString.includes("?") ? "&" : "?";
222
+ return new URL(`${urlString}${separator}scope=${encodedScope}`);
223
+ }
224
+ return url;
216
225
  },
217
226
  validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
218
227
  return validateAuthorizationCode({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/core",
3
- "version": "1.4.8-beta.6",
3
+ "version": "1.4.8",
4
4
  "description": "The most comprehensive authentication framework for TypeScript.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -474,9 +474,19 @@ export const createAdapterFactory =
474
474
  const transformWhereClause = <W extends Where[] | undefined>({
475
475
  model,
476
476
  where,
477
+ action,
477
478
  }: {
478
479
  where: W;
479
480
  model: string;
481
+ action:
482
+ | "create"
483
+ | "update"
484
+ | "findOne"
485
+ | "findMany"
486
+ | "updateMany"
487
+ | "delete"
488
+ | "deleteMany"
489
+ | "count";
480
490
  }): W extends undefined ? undefined : CleanedWhere[] => {
481
491
  if (!where) return undefined as any;
482
492
  const newMappedKeys = config.mapKeysTransformInput ?? {};
@@ -562,6 +572,18 @@ export const createAdapterFactory =
562
572
  }
563
573
  }
564
574
 
575
+ if (config.customTransformInput) {
576
+ newValue = config.customTransformInput({
577
+ data: newValue,
578
+ fieldAttributes: fieldAttr,
579
+ field: fieldName,
580
+ model: getModelName(model),
581
+ schema,
582
+ options,
583
+ action,
584
+ });
585
+ }
586
+
565
587
  return {
566
588
  operator,
567
589
  connector,
@@ -727,6 +749,7 @@ export const createAdapterFactory =
727
749
  connector: "AND",
728
750
  },
729
751
  ],
752
+ action: "findOne",
730
753
  });
731
754
  try {
732
755
  if (joinConfig.relation === "one-to-one") {
@@ -886,6 +909,7 @@ export const createAdapterFactory =
886
909
  const where = transformWhereClause({
887
910
  model: unsafeModel,
888
911
  where: unsafeWhere,
912
+ action: "update",
889
913
  });
890
914
  debugLog(
891
915
  { method: "update" },
@@ -946,6 +970,7 @@ export const createAdapterFactory =
946
970
  const where = transformWhereClause({
947
971
  model: unsafeModel,
948
972
  where: unsafeWhere,
973
+ action: "updateMany",
949
974
  });
950
975
  unsafeModel = getDefaultModelName(unsafeModel);
951
976
  debugLog(
@@ -1001,6 +1026,7 @@ export const createAdapterFactory =
1001
1026
  const where = transformWhereClause({
1002
1027
  model: unsafeModel,
1003
1028
  where: unsafeWhere,
1029
+ action: "findOne",
1004
1030
  });
1005
1031
  unsafeModel = getDefaultModelName(unsafeModel);
1006
1032
  let join: JoinConfig | undefined;
@@ -1078,6 +1104,7 @@ export const createAdapterFactory =
1078
1104
  const where = transformWhereClause({
1079
1105
  model: unsafeModel,
1080
1106
  where: unsafeWhere,
1107
+ action: "findMany",
1081
1108
  });
1082
1109
  unsafeModel = getDefaultModelName(unsafeModel);
1083
1110
  let join: JoinConfig | undefined;
@@ -1151,6 +1178,7 @@ export const createAdapterFactory =
1151
1178
  const where = transformWhereClause({
1152
1179
  model: unsafeModel,
1153
1180
  where: unsafeWhere,
1181
+ action: "delete",
1154
1182
  });
1155
1183
  unsafeModel = getDefaultModelName(unsafeModel);
1156
1184
  debugLog(
@@ -1183,6 +1211,7 @@ export const createAdapterFactory =
1183
1211
  const where = transformWhereClause({
1184
1212
  model: unsafeModel,
1185
1213
  where: unsafeWhere,
1214
+ action: "deleteMany",
1186
1215
  });
1187
1216
  unsafeModel = getDefaultModelName(unsafeModel);
1188
1217
  debugLog(
@@ -1216,6 +1245,7 @@ export const createAdapterFactory =
1216
1245
  const where = transformWhereClause({
1217
1246
  model: unsafeModel,
1218
1247
  where: unsafeWhere,
1248
+ action: "count",
1219
1249
  });
1220
1250
  unsafeModel = getDefaultModelName(unsafeModel);
1221
1251
  debugLog(
@@ -203,7 +203,15 @@ export interface DBAdapterFactoryConfig<
203
203
  /**
204
204
  * The action which was called from the adapter.
205
205
  */
206
- action: "create" | "update" | "findOne" | "findMany";
206
+ action:
207
+ | "create"
208
+ | "update"
209
+ | "findOne"
210
+ | "findMany"
211
+ | "updateMany"
212
+ | "delete"
213
+ | "deleteMany"
214
+ | "count";
207
215
  /**
208
216
  * The model name.
209
217
  */
@@ -111,9 +111,19 @@ export type AdapterFactoryCustomizeAdapterCreator = (config: {
111
111
  transformWhereClause: <W extends Where[] | undefined>({
112
112
  model,
113
113
  where,
114
+ action,
114
115
  }: {
115
116
  where: W;
116
117
  model: string;
118
+ action:
119
+ | "create"
120
+ | "update"
121
+ | "findOne"
122
+ | "findMany"
123
+ | "updateMany"
124
+ | "delete"
125
+ | "deleteMany"
126
+ | "count";
117
127
  }) => W extends undefined ? undefined : CleanedWhere[];
118
128
  }) => CustomAdapter;
119
129
 
@@ -19,3 +19,8 @@ export {
19
19
  validateAuthorizationCode,
20
20
  validateToken,
21
21
  } from "./validate-authorization-code";
22
+ export {
23
+ getJwks,
24
+ verifyAccessToken,
25
+ verifyJwsAccessToken,
26
+ } from "./verify";
@@ -0,0 +1,221 @@
1
+ import { betterFetch } from "@better-fetch/fetch";
2
+ import { APIError } from "better-call";
3
+ import type {
4
+ JSONWebKeySet,
5
+ JWTPayload,
6
+ JWTVerifyOptions,
7
+ ProtectedHeaderParameters,
8
+ } from "jose";
9
+ import {
10
+ createLocalJWKSet,
11
+ decodeProtectedHeader,
12
+ jwtVerify,
13
+ UnsecuredJWT,
14
+ } from "jose";
15
+ import { logger } from "../env";
16
+
17
+ /** Last fetched jwks used locally in getJwks @internal */
18
+ let jwks: JSONWebKeySet | undefined;
19
+
20
+ export interface VerifyAccessTokenRemote {
21
+ /** Full url of the introspect endpoint. Should end with `/oauth2/introspect` */
22
+ introspectUrl: string;
23
+ /** Client Secret */
24
+ clientId: string;
25
+ /** Client Secret */
26
+ clientSecret: string;
27
+ /**
28
+ * Forces remote verification of a token.
29
+ * This ensures attached session (if applicable)
30
+ * is also still active.
31
+ */
32
+ force?: boolean;
33
+ }
34
+
35
+ /**
36
+ * Performs local verification of an access token for your APIs.
37
+ *
38
+ * Can also be configured for remote verification.
39
+ */
40
+ export async function verifyJwsAccessToken(
41
+ token: string,
42
+ opts: {
43
+ /** Jwks url or promise of a Jwks */
44
+ jwksFetch: string | (() => Promise<JSONWebKeySet | undefined>);
45
+ /** Verify options */
46
+ verifyOptions: JWTVerifyOptions &
47
+ Required<Pick<JWTVerifyOptions, "audience" | "issuer">>;
48
+ },
49
+ ) {
50
+ try {
51
+ const jwks = await getJwks(token, opts);
52
+ const jwt = await jwtVerify<JWTPayload>(
53
+ token,
54
+ createLocalJWKSet(jwks),
55
+ opts.verifyOptions,
56
+ );
57
+ // Return the JWT payload in introspection format
58
+ // https://datatracker.ietf.org/doc/html/rfc7662#section-2.2
59
+ if (jwt.payload.azp) {
60
+ jwt.payload.client_id = jwt.payload.azp;
61
+ }
62
+ return jwt.payload;
63
+ } catch (error) {
64
+ if (error instanceof Error) throw error;
65
+ throw new Error(error as unknown as string);
66
+ }
67
+ }
68
+
69
+ export async function getJwks(
70
+ token: string,
71
+ opts: {
72
+ /** Jwks url or promise of a Jwks */
73
+ jwksFetch: string | (() => Promise<JSONWebKeySet | undefined>);
74
+ },
75
+ ) {
76
+ // Attempt to decode the token and find a matching kid in jwks
77
+ let jwtHeaders: ProtectedHeaderParameters | undefined;
78
+ try {
79
+ jwtHeaders = decodeProtectedHeader(token);
80
+ } catch (error) {
81
+ if (error instanceof Error) throw error;
82
+ throw new Error(error as unknown as string);
83
+ }
84
+
85
+ if (!jwtHeaders.kid) throw new Error("Missing jwt kid");
86
+
87
+ // Fetch jwks if not set or has a different kid than the one stored
88
+ if (!jwks || !jwks.keys.find((jwk) => jwk.kid === jwtHeaders.kid)) {
89
+ jwks =
90
+ typeof opts.jwksFetch === "string"
91
+ ? await betterFetch<JSONWebKeySet>(opts.jwksFetch, {
92
+ headers: {
93
+ Accept: "application/json",
94
+ },
95
+ }).then(async (res) => {
96
+ if (res.error)
97
+ throw new Error(
98
+ `Jwks failed: ${res.error.message ?? res.error.statusText}`,
99
+ );
100
+ return res.data;
101
+ })
102
+ : await opts.jwksFetch();
103
+ if (!jwks) throw new Error("No jwks found");
104
+ }
105
+
106
+ return jwks;
107
+ }
108
+
109
+ /**
110
+ * Performs local verification of an access token for your API.
111
+ *
112
+ * Can also be configured for remote verification.
113
+ */
114
+ export async function verifyAccessToken(
115
+ token: string,
116
+ opts: {
117
+ /** Verify options */
118
+ verifyOptions: JWTVerifyOptions &
119
+ Required<Pick<JWTVerifyOptions, "audience" | "issuer">>;
120
+ /** Scopes to additionally verify. Token must include all but not exact. */
121
+ scopes?: string[];
122
+ /** Required to verify access token locally */
123
+ jwksUrl?: string;
124
+ /** If provided, can verify a token remotely */
125
+ remoteVerify?: VerifyAccessTokenRemote;
126
+ },
127
+ ) {
128
+ let payload: JWTPayload | undefined;
129
+ // Locally verify
130
+ if (opts.jwksUrl && !opts?.remoteVerify?.force) {
131
+ try {
132
+ payload = await verifyJwsAccessToken(token, {
133
+ jwksFetch: opts.jwksUrl,
134
+ verifyOptions: opts.verifyOptions,
135
+ });
136
+ } catch (error) {
137
+ if (error instanceof Error) {
138
+ if (error.name === "TypeError" || error.name === "JWSInvalid") {
139
+ // likely an opaque token (continue)
140
+ } else if (error.name === "JWTExpired") {
141
+ throw new APIError("UNAUTHORIZED", {
142
+ message: "token expired",
143
+ });
144
+ } else if (error.name === "JWTInvalid") {
145
+ throw new APIError("UNAUTHORIZED", {
146
+ message: "token invalid",
147
+ });
148
+ } else {
149
+ throw error;
150
+ }
151
+ } else {
152
+ throw new Error(error as unknown as string);
153
+ }
154
+ }
155
+ }
156
+
157
+ // Remote verify
158
+ if (opts?.remoteVerify) {
159
+ const { data: introspect, error: introspectError } = await betterFetch<
160
+ JWTPayload & {
161
+ active: boolean;
162
+ }
163
+ >(opts.remoteVerify.introspectUrl, {
164
+ method: "POST",
165
+ headers: {
166
+ Accept: "application/json",
167
+ "Content-Type": "application/x-www-form-urlencoded",
168
+ },
169
+ body: new URLSearchParams({
170
+ client_id: opts.remoteVerify.clientId,
171
+ client_secret: opts.remoteVerify.clientSecret,
172
+ token,
173
+ token_type_hint: "access_token",
174
+ }).toString(),
175
+ });
176
+ if (introspectError)
177
+ logger.error(
178
+ `Introspection failed: ${introspectError.message ?? introspectError.statusText}`,
179
+ );
180
+ if (!introspect)
181
+ throw new APIError("INTERNAL_SERVER_ERROR", {
182
+ message: "introspection failed",
183
+ });
184
+ if (!introspect.active)
185
+ throw new APIError("UNAUTHORIZED", {
186
+ message: "token inactive",
187
+ });
188
+ // Verifies payload using verify options (token valid through introspect)
189
+ try {
190
+ const unsecuredJwt = new UnsecuredJWT(introspect).encode();
191
+ const { audience: _audience, ...verifyOptions } = opts.verifyOptions;
192
+ const verify = introspect.aud
193
+ ? UnsecuredJWT.decode(unsecuredJwt, opts.verifyOptions)
194
+ : UnsecuredJWT.decode(unsecuredJwt, verifyOptions);
195
+ payload = verify.payload;
196
+ } catch (error) {
197
+ throw new Error(error as unknown as string);
198
+ }
199
+ }
200
+
201
+ if (!payload)
202
+ throw new APIError("UNAUTHORIZED", {
203
+ message: `no token payload`,
204
+ });
205
+
206
+ // Check scopes if provided
207
+ if (opts.scopes) {
208
+ const validScopes = new Set(
209
+ (payload.scope as string | undefined)?.split(" "),
210
+ );
211
+ for (const sc of opts.scopes) {
212
+ if (!validScopes.has(sc)) {
213
+ throw new APIError("FORBIDDEN", {
214
+ message: `invalid scope ${sc}`,
215
+ });
216
+ }
217
+ }
218
+ }
219
+
220
+ return payload;
221
+ }
@@ -92,6 +92,17 @@ export const cognito = (options: CognitoOptions) => {
92
92
  redirectURI,
93
93
  prompt: options.prompt,
94
94
  });
95
+ // AWS Cognito requires scopes to be encoded with %20 instead of +
96
+ // URLSearchParams encodes spaces as + by default, so we need to fix this
97
+ const scopeValue = url.searchParams.get("scope");
98
+ if (scopeValue) {
99
+ url.searchParams.delete("scope");
100
+ const encodedScope = encodeURIComponent(scopeValue);
101
+ // Manually append the scope with proper encoding to the URL
102
+ const urlString = url.toString();
103
+ const separator = urlString.includes("?") ? "&" : "?";
104
+ return new URL(`${urlString}${separator}scope=${encodedScope}`);
105
+ }
95
106
  return url;
96
107
  },
97
108
 
@@ -994,17 +994,9 @@ export type BetterAuthOptions = {
994
994
  | undefined;
995
995
  /**
996
996
  * List of trusted origins.
997
- *
998
- * @param request - The request object.
999
- * It'll be undefined if no request was
1000
- * made. Like during a create context call
1001
- * or `auth.api` call.
1002
- *
1003
- * Trusted origins will be dynamically
1004
- * calculated based on the request.
1005
997
  */
1006
998
  trustedOrigins?:
1007
- | (string[] | ((request?: Request | undefined) => Awaitable<string[]>))
999
+ | (string[] | ((request: Request) => Awaitable<string[]>))
1008
1000
  | undefined;
1009
1001
  /**
1010
1002
  * Rate limiting configuration