@iskra-bun/auth-kit 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,54 @@
1
1
  # @iskra-bun/auth-kit
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 76028ab: **Breaking (0.x):** `createBetterAuth` no longer defaults `baseURL` to `http://localhost:3000` everywhere. It now reads `BETTER_AUTH_URL` when `baseURL` is not passed (the hardcoded default overrode better-auth's own fallback to it), keeps the localhost default only outside production, and with `NODE_ENV=production` throws when neither is set or when the origin is plain `http://` on a host other than `localhost`, `127.0.0.1` or `[::1]`. better-auth marks the session cookies `Secure` only for an https `baseURL` and trusts that origin, so a production app built without one sent its session cookies over plain HTTP and trusted `http://localhost:3000`. Pass `baseURL: 'https://your-app.example.com'` (or set `BETTER_AUTH_URL`) in production. The rule is exported as `resolveAuthBaseURL(baseURL?, who?)`, which web-kit's `AuthFeature` now uses (its behaviour is unchanged).
8
+ - 7720bd5: New `rateLimit: false` and `ipAddressHeaders` options for better-auth's rate limiter and client IP. The MySQL `verification.value` column is `text` (OAuth state is longer than 255 characters, so OIDC sign-in failed in strict mode); existing tables need `ALTER TABLE verification MODIFY value TEXT NOT NULL`.
9
+ - cb3ec43: **Breaking (types):** `User` and `SignUpInput` custom fields are `unknown` (were `any`), and `socialProviders` takes better-auth's own option type. The OIDC profile mapping (`mapOidcProfile`, now exported and tested) returns only local user fields: the `id` it returned was ignored by better-auth, which takes the account's identity from the verified `sub`.
10
+ - 0f1ce5b: **Security:** authorization fixes.
11
+
12
+ - `ApiKeyFeature`: an `Authorization: Bearer` token that is not a valid API key no longer returns 401 for every request (it broke JWT/session auth app-wide, public routes included); `requireApiKey()`/`requireScope()` still reject it with the validation error. Cache hits now re-check expiry and ignore keys removed from the config (a Redis cache outlives the restart that rotated them). The `onError`, `onValidated` and `customExtractor` / `"custom"` strategy options are now honored.
13
+ - `PermissionsFeature`: role permissions were pushed into the array returned by `loadPermissions()`; a loader returning a shared/cached array leaked them (including admin `"*"`) to other users. The array is now copied.
14
+ - `AuthFeature` (**breaking**): email/password login is only enabled in `authMode: "email"` (previously hardcoded on, so OIDC deployments still exposed an open `/sign-up/email`); opt back in with the new `enableEmailPassword` option. `enableSelfRegistration: false` is now honored and disables sign-up.
15
+ - `auth-kit`: new `disableSignUp` option for `createBetterAuth`.
16
+
17
+ - ef2009b: **Security:** update dependencies with known vulnerabilities (`bun audit` went from 67 findings, 1 critical and 38 high, to one accepted dev-only finding).
18
+
19
+ - `better-auth` ^1.6.33 (account takeover via pre-account hijacking), `hono` ^4.12.34, `ajv` ^8.20.0, `mysql2` ^3.24.4 (web-kit, auth-kit, db-kit).
20
+ - `drizzle-orm` ^0.45.2 (SQL injection via improperly escaped identifiers). **db-kit moves from 0.30 to 0.45**, the same line web-kit and auth-kit already used, so schemas are shared across kits again; `drizzle-kit` ^0.31.11 now matches it (0.30 exited with "requires newer version of drizzle-orm", so migrations never ran), and `@libsql/client` ^0.18.0 satisfies drizzle's peer range.
21
+ - `c12` ^3.3.4 in core (drops the vulnerable `tar` 6 pulled in through `giget` 1).
22
+ - `nodemailer` ^10.0.10 in mailer-kit (arbitrary file read / SSRF via the raw option, SMTP command and header injection).
23
+
24
+ - f2346f5: **Breaking behavior:** production safeguards now apply unless `NODE_ENV` is `development` or `test`. They applied only to `NODE_ENV=production` exactly, so a deploy that forgot it (or used `staging`) sent session cookies without `Secure`, accepted sample secrets and plain-http auth URLs, honored `disableCSRFCheck` and wrote pretty logs. `NODE_ENV` is also read when the app runs: `bun build` replaced a literal `process.env.NODE_ENV` with `"development"` when it was unset while building, so a compiled binary ignored the value it ran with. `app.start()` logs a warning when `NODE_ENV` is unset. Set `NODE_ENV=development` for local development; the templates' `bun dev` scripts do. New `nodeEnv()`, `isProductionEnv()` and `isDevelopmentEnv()` in `@iskra-bun/core`.
25
+ - c24201a: **Security (breaking):** with `NODE_ENV=production`, `createBetterAuth` refuses a secret that is still a sample value: one containing `change-me`, `dev-secret`, `dev-only`, `your-secret` or `placeholder`, compared without case, `-`, `_`, `.` or spaces (so `changeme` and `CHANGE_ME` count too). A sample secret copied from docs or an `.env.example` is public, and it signs better-auth's session cookie cache, which is trusted without a database lookup: anyone could forge a session for any user. The error names the matching word, never the secret.
26
+
27
+ ### Patch Changes
28
+
29
+ - d6151cb: `oidcConfig.mapping` is now applied: `email`, `name`, `image` and `emailVerified` name the claims the user's fields are read from, falling back to the standard claims when the profile lacks them (a mapped `emailVerified` claim counts as verified when it is `true` or `"true"`). A mapped email is verified only by its paired mapped flag, or by the standard `email_verified` when it is the same address, so a verified standard email never vouches for a different mapped one (better-auth links verified emails to existing local users). It was accepted but never read, so a provider with non-standard claim names created users without them. `mapOidcProfile(profile, mapping?)` takes the mapping as an optional second argument. `jwksEndpoint`, `mapping.id` and `mapping.extraFields` are marked `@deprecated` and still ignored: better-auth takes the JWKS only from the discovery document's `jwks_uri`, the account's identity always comes from the verified `sub`, and extra user fields need better-auth `user.additionalFields`.
30
+ - 093656f: `oidcConfig` endpoints that are not set now come from the issuer's discovery document. They defaulted to Keycloak's `${issuer}/protocol/openid-connect/{auth,token,userinfo}` paths, and better-auth only fills the endpoints left unset from discovery, so every other provider (Auth0, Okta, Entra ID, …) got URLs that do not exist and sign-in failed unless all three were configured by hand. `authorizationEndpoint`, `tokenEndpoint` and `userinfoEndpoint` still override the discovered ones. The provider config is built by the new exported `oidcProviderConfig(oidcConfig)`; web-kit's `AuthFeature` passes its `oidcConfig` through, so it gets the same behaviour. With only the `issuer` set, the provider now depends on discovery at startup: if the discovery document cannot be fetched then (for example the IdP container starts after the app), better-auth logs the error and leaves the provider out until the app restarts. Set the three endpoints explicitly to avoid that dependency.
31
+ - 840439a: Packages declare the runtime they are tested on: `engines.bun` `>=1.3.0` (the monorepo now builds and tests on Bun 1.3). `create-iskra`, a CLI that also runs under `npm create iskra`, declares `engines.node` `>=18`.
32
+
33
+ Every package is published with an npm provenance attestation (`publishConfig.provenance`), linking each version to the commit and CI run that built it.
34
+
35
+ - 8f31aa5: **Security:** `createBetterAuth` pins `advanced.disableOriginCheck: false`. Left unset, better-auth skips its Origin check (CSRF on cookie-authenticated requests) and its `callbackURL`/`redirectTo` validation (open redirects) whenever it believes it runs under test: `NODE_ENV=test`, or any `TEST` environment variable other than `"false"` (`TEST=0` included), which a production image can carry from its build.
36
+ - Updated dependencies [620da18]
37
+ - Updated dependencies [b635a2c]
38
+ - Updated dependencies [5b2b0fd]
39
+ - Updated dependencies [58d4a8f]
40
+ - Updated dependencies [5c70c5b]
41
+ - Updated dependencies [ec198d4]
42
+ - Updated dependencies [cb3ec43]
43
+ - Updated dependencies [ef2009b]
44
+ - Updated dependencies [840439a]
45
+ - Updated dependencies [dbf8817]
46
+ - Updated dependencies [3dc5581]
47
+ - Updated dependencies [9872d30]
48
+ - Updated dependencies [f2346f5]
49
+ - Updated dependencies [3579944]
50
+ - @iskra-bun/core@0.2.0
51
+
3
52
  ## 0.1.0
4
53
 
5
54
  ### Minor Changes
package/README.md CHANGED
@@ -28,7 +28,7 @@ El esquema Drizzle (`pgSchema`, `mysqlSchema`, `sqliteSchema`) y los tipos (`Use
28
28
 
29
29
  ## Documentacion
30
30
 
31
- Guia completa: [docs/auth-kit.md](../../docs/auth-kit.md)
31
+ Guia completa: [@iskra-bun/auth-kit](https://iskra-docs.fly.dev/es/packages/auth-kit/)
32
32
 
33
33
  ## Licencia
34
34
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { Auth as Auth$1 } from 'better-auth';
1
+ import { BetterAuthOptions, Auth as Auth$1 } from 'better-auth';
2
+ import { GenericOAuthUserInfo } from 'better-auth/plugins/generic-oauth';
2
3
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
3
4
  import { PgDatabase, PgQueryResultHKT } from 'drizzle-orm/pg-core';
4
5
  import * as drizzle_orm_mysql_core from 'drizzle-orm/mysql-core';
@@ -12,15 +13,30 @@ import { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core';
12
13
  * Drizzle instance rather than `any` leaking into callers. The dialect-core base
13
14
  * classes are part of `drizzle-orm` itself, so no driver dependency is required.
14
15
  */
15
- type AuthKitDrizzleDb = PgDatabase<PgQueryResultHKT, Record<string, unknown>> | MySqlDatabase<MySqlQueryResultHKT, PreparedQueryHKTBase, Record<string, unknown>> | BaseSQLiteDatabase<"sync" | "async", unknown, Record<string, unknown>>;
16
+ type AuthKitDrizzleDb = PgDatabase<PgQueryResultHKT, Record<string, unknown>> | MySqlDatabase<MySqlQueryResultHKT, PreparedQueryHKTBase, Record<string, unknown>> | BaseSQLiteDatabase<'sync' | 'async', unknown, Record<string, unknown>>;
17
+ /**
18
+ * The origin better-auth runs on: `baseURL`, else `BETTER_AUTH_URL`, else
19
+ * `http://localhost:3000` outside production. It decides the cookies'
20
+ * `Secure` flag and is a trusted origin, so production requires one and it
21
+ * must be https (plain http only for localhost, 127.0.0.1 and [::1]). `who`
22
+ * prefixes the error messages.
23
+ */
24
+ declare function resolveAuthBaseURL(baseURL?: string, who?: string): string;
16
25
  interface BetterAuthConfigOptions {
17
26
  db: AuthKitDrizzleDb;
18
- adapterType: "postgres" | "mysql" | "sqlite";
27
+ adapterType: 'postgres' | 'mysql' | 'sqlite';
19
28
  secret: string;
29
+ /**
30
+ * The app's public origin. Defaults to `BETTER_AUTH_URL`, then (outside
31
+ * production only) `http://localhost:3000`; must be https in production
32
+ * unless it is localhost. See `resolveAuthBaseURL`.
33
+ */
20
34
  baseURL?: string;
21
35
  basePath?: string;
22
36
  trustedOrigins?: string[];
23
37
  enableEmailPassword?: boolean;
38
+ /** Reject `/sign-up/email` (accounts are provisioned another way). Default false. */
39
+ disableSignUp?: boolean;
24
40
  disableCSRFCheck?: boolean;
25
41
  /**
26
42
  * Cookie-cache lifetime in seconds. This is the session-revocation lag: a
@@ -29,7 +45,19 @@ interface BetterAuthConfigOptions {
29
45
  * frequent DB lookups). Defaults to 300 (5 minutes).
30
46
  */
31
47
  cookieCacheMaxAge?: number;
32
- socialProviders?: Record<string, any>;
48
+ /**
49
+ * `false` turns off better-auth's own rate limiter (on by default in
50
+ * production), e.g. when the app limits the auth routes itself.
51
+ */
52
+ rateLimit?: false;
53
+ /**
54
+ * Request headers better-auth reads the client IP from, for its rate
55
+ * limiter and the sessions' `ipAddress` (default `x-forwarded-for`, first
56
+ * entry). Without a usable one, every client shares one rate-limit bucket.
57
+ */
58
+ ipAddressHeaders?: string[];
59
+ /** better-auth's socialProviders option, as is. */
60
+ socialProviders?: BetterAuthOptions['socialProviders'];
33
61
  oidcConfig?: {
34
62
  clientId: string;
35
63
  clientSecret: string;
@@ -38,20 +66,74 @@ interface BetterAuthConfigOptions {
38
66
  authorizationEndpoint?: string;
39
67
  tokenEndpoint?: string;
40
68
  userinfoEndpoint?: string;
69
+ /**
70
+ * @deprecated Ignored: better-auth takes the JWKS only from the
71
+ * discovery document's `jwks_uri`; point `discoveryEndpoint` at a
72
+ * document that has the right one instead.
73
+ */
41
74
  jwksEndpoint?: string;
42
75
  discoveryEndpoint?: string;
43
76
  scopes?: string[];
44
77
  pkce?: boolean;
45
- mapping?: {
46
- id?: string;
47
- email?: string;
48
- emailVerified?: string;
49
- name?: string;
50
- image?: string;
51
- extraFields?: Record<string, string>;
52
- };
78
+ /** Claim names to read the user's fields from, instead of the standard ones. */
79
+ mapping?: OidcClaimMapping;
53
80
  };
54
81
  }
82
+ /** Claim names `mapOidcProfile` reads the user's fields from. */
83
+ interface OidcClaimMapping {
84
+ /**
85
+ * @deprecated Ignored: better-auth always takes the account's identity
86
+ * from the verified `sub` claim.
87
+ */
88
+ id?: string;
89
+ email?: string;
90
+ /** The claim is read as verified when it is `true` or `"true"`. */
91
+ emailVerified?: string;
92
+ name?: string;
93
+ image?: string;
94
+ /**
95
+ * @deprecated Ignored: extra user fields need better-auth
96
+ * `user.additionalFields`, which `createBetterAuth` does not declare.
97
+ */
98
+ extraFields?: Record<string, string>;
99
+ }
100
+ /**
101
+ * The local user fields for an OIDC login (standard claims, with the common
102
+ * non-standard fallbacks). A claim named in `mapping` is read instead of the
103
+ * standard one when the profile has it. No `id`: better-auth takes the
104
+ * account's identity from the verified `sub` (accountSubject) and ignores one
105
+ * returned here.
106
+ */
107
+ declare function mapOidcProfile(profile: GenericOAuthUserInfo, mapping?: OidcClaimMapping): {
108
+ email: string | null | undefined;
109
+ name: string | undefined;
110
+ image: string | undefined;
111
+ emailVerified: boolean;
112
+ };
113
+ /**
114
+ * The generic-oauth provider config for `oidcConfig`. The endpoints left
115
+ * unset come from the issuer's discovery document: better-auth fills only
116
+ * the ones not given, so a default here (e.g. Keycloak's
117
+ * `/protocol/openid-connect/*` paths) would override discovery for every
118
+ * other provider.
119
+ */
120
+ declare function oidcProviderConfig(oidcConfig: NonNullable<BetterAuthConfigOptions['oidcConfig']>): {
121
+ providerId: string;
122
+ clientId: string;
123
+ clientSecret: string;
124
+ authorizationUrl: string | undefined;
125
+ tokenUrl: string | undefined;
126
+ userInfoUrl: string | undefined;
127
+ discoveryUrl: string;
128
+ scopes: string[];
129
+ pkce: boolean;
130
+ mapProfileToUser: (profile: GenericOAuthUserInfo) => {
131
+ email: string | null | undefined;
132
+ name: string | undefined;
133
+ image: string | undefined;
134
+ emailVerified: boolean;
135
+ };
136
+ };
55
137
  declare function createBetterAuth(options: BetterAuthConfigOptions): Auth$1;
56
138
  type Auth = ReturnType<typeof createBetterAuth>;
57
139
 
@@ -1808,9 +1890,9 @@ declare const mysqlVerification: drizzle_orm_mysql_core.MySqlTableWithColumns<{
1808
1890
  name: "value";
1809
1891
  tableName: "verification";
1810
1892
  dataType: "string";
1811
- columnType: "MySqlVarChar";
1893
+ columnType: "MySqlText";
1812
1894
  data: string;
1813
- driverParam: string | number;
1895
+ driverParam: string;
1814
1896
  notNull: true;
1815
1897
  hasDefault: false;
1816
1898
  isPrimaryKey: false;
@@ -2415,9 +2497,9 @@ declare const mysqlSchema: {
2415
2497
  name: "value";
2416
2498
  tableName: "verification";
2417
2499
  dataType: "string";
2418
- columnType: "MySqlVarChar";
2500
+ columnType: "MySqlText";
2419
2501
  data: string;
2420
- driverParam: string | number;
2502
+ driverParam: string;
2421
2503
  notNull: true;
2422
2504
  hasDefault: false;
2423
2505
  isPrimaryKey: false;
@@ -3793,7 +3875,8 @@ interface User {
3793
3875
  image?: string | null;
3794
3876
  createdAt: Date;
3795
3877
  updatedAt: Date;
3796
- [key: string]: any;
3878
+ /** Custom fields: narrow them where they are read. */
3879
+ [key: string]: unknown;
3797
3880
  }
3798
3881
  interface Account {
3799
3882
  id: string;
@@ -3854,7 +3937,8 @@ interface SignUpInput {
3854
3937
  email: string;
3855
3938
  password: string;
3856
3939
  name?: string;
3857
- [key: string]: any;
3940
+ /** Custom fields: narrow them where they are read. */
3941
+ [key: string]: unknown;
3858
3942
  }
3859
3943
  /**
3860
3944
  * Login input
@@ -3883,4 +3967,4 @@ interface EmailVerificationRequest {
3883
3967
  token: string;
3884
3968
  }
3885
3969
 
3886
- export { type Account, type Auth, type AuthContext, type AuthKitDrizzleDb, type AuthSession, type BetterAuthConfigOptions, type EmailVerificationRequest, type EmailVerificationToken, type PasswordResetConfirm, type PasswordResetRequest, type PasswordResetToken, type SignInInput, type SignUpInput, type User, type Verification, createBetterAuth, mysqlAccount, mysqlSchema, mysqlSession, mysqlUser, mysqlVerification, pgAccount, pgSchema, pgSession, pgUser, pgVerification, sqliteAccount, sqliteSchema, sqliteSession, sqliteUser, sqliteVerification };
3970
+ export { type Account, type Auth, type AuthContext, type AuthKitDrizzleDb, type AuthSession, type BetterAuthConfigOptions, type EmailVerificationRequest, type EmailVerificationToken, type OidcClaimMapping, type PasswordResetConfirm, type PasswordResetRequest, type PasswordResetToken, type SignInInput, type SignUpInput, type User, type Verification, createBetterAuth, mapOidcProfile, mysqlAccount, mysqlSchema, mysqlSession, mysqlUser, mysqlVerification, oidcProviderConfig, pgAccount, pgSchema, pgSession, pgUser, pgVerification, resolveAuthBaseURL, sqliteAccount, sqliteSchema, sqliteSession, sqliteUser, sqliteVerification };
package/dist/index.js CHANGED
@@ -5,7 +5,13 @@ import { genericOAuth } from "better-auth/plugins/generic-oauth";
5
5
 
6
6
  // src/schema.ts
7
7
  import { pgTable, text, timestamp, boolean } from "drizzle-orm/pg-core";
8
- import { mysqlTable, varchar, timestamp as mysqlTimestamp, boolean as mysqlBoolean, text as mysqlText } from "drizzle-orm/mysql-core";
8
+ import {
9
+ mysqlTable,
10
+ varchar,
11
+ timestamp as mysqlTimestamp,
12
+ boolean as mysqlBoolean,
13
+ text as mysqlText
14
+ } from "drizzle-orm/mysql-core";
9
15
  import { sqliteTable, text as sqliteText, integer } from "drizzle-orm/sqlite-core";
10
16
  var pgUser = pgTable("user", {
11
17
  id: text("id").primaryKey(),
@@ -92,7 +98,9 @@ var mysqlAccount = mysqlTable("account", {
92
98
  var mysqlVerification = mysqlTable("verification", {
93
99
  id: varchar("id", { length: 36 }).primaryKey(),
94
100
  identifier: varchar("identifier", { length: 255 }).notNull(),
95
- value: varchar("value", { length: 255 }).notNull(),
101
+ // text: better-auth stores OAuth state here (JSON longer than 255 characters),
102
+ // which MySQL strict mode rejected, failing every OIDC sign-in.
103
+ value: mysqlText("value").notNull(),
96
104
  expiresAt: mysqlTimestamp("expiresAt").notNull(),
97
105
  createdAt: mysqlTimestamp("createdAt"),
98
106
  updatedAt: mysqlTimestamp("updatedAt")
@@ -153,26 +161,103 @@ var sqliteSchema = {
153
161
  };
154
162
 
155
163
  // src/better-auth-config.ts
164
+ import { isProductionEnv } from "@iskra-bun/core";
156
165
  var MIN_SECRET_LENGTH = 32;
166
+ var PLACEHOLDER_SECRET_MARKERS = ["change-me", "dev-secret", "dev-only", "your-secret", "placeholder"];
167
+ var normalizeSecret = (value) => value.toLowerCase().replace(/[-_.\s]/g, "");
168
+ function placeholderMarker(secret) {
169
+ const normalized = normalizeSecret(secret);
170
+ return PLACEHOLDER_SECRET_MARKERS.find((marker) => normalized.includes(normalizeSecret(marker)));
171
+ }
172
+ var LOCAL_HOSTNAMES = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
173
+ function resolveAuthBaseURL(baseURL, who = "createBetterAuth") {
174
+ const resolved = baseURL || process.env.BETTER_AUTH_URL;
175
+ if (resolved) {
176
+ assertHttpsInProduction(resolved, who);
177
+ return resolved;
178
+ }
179
+ if (isProductionEnv()) {
180
+ throw new Error(
181
+ `${who}: set baseURL (or BETTER_AUTH_URL) to the app's public origin in production, e.g. "https://app.example.com"; without it cookies are sent without Secure.`
182
+ );
183
+ }
184
+ return "http://localhost:3000";
185
+ }
186
+ function assertHttpsInProduction(baseURL, who) {
187
+ if (!isProductionEnv()) return;
188
+ let url;
189
+ try {
190
+ url = new URL(baseURL);
191
+ } catch {
192
+ return;
193
+ }
194
+ if (url.protocol === "https:" || LOCAL_HOSTNAMES.has(url.hostname)) return;
195
+ throw new Error(
196
+ `${who}: baseURL "${baseURL}" must use https in production: better-auth marks the session cookies Secure only for an https baseURL. Plain http is allowed only for localhost, 127.0.0.1 and [::1].`
197
+ );
198
+ }
199
+ function mapOidcProfile(profile, mapping = {}) {
200
+ const str = (v) => typeof v === "string" && v !== "" ? v : void 0;
201
+ const claim = (name) => name ? profile[name] : void 0;
202
+ const isTrue = (v) => v === true || v === "true";
203
+ const standardVerified = profile.emailVerified === true || isTrue(profile.email_verified);
204
+ const mappedEmail = str(claim(mapping.email));
205
+ const pairedFlag = mappedEmail !== void 0 || !mapping.email ? claim(mapping.emailVerified) : void 0;
206
+ let emailVerified;
207
+ if (pairedFlag !== void 0 && pairedFlag !== null) emailVerified = isTrue(pairedFlag);
208
+ else if (mappedEmail !== void 0) emailVerified = mappedEmail === profile.email && standardVerified;
209
+ else emailVerified = standardVerified;
210
+ return {
211
+ email: mappedEmail ?? profile.email,
212
+ name: str(claim(mapping.name)) ?? (profile.name || str(profile.preferred_username)),
213
+ image: str(claim(mapping.image)) ?? str(profile.picture) ?? profile.image,
214
+ emailVerified
215
+ };
216
+ }
217
+ function oidcProviderConfig(oidcConfig) {
218
+ return {
219
+ providerId: oidcConfig.providerId || "oidc",
220
+ clientId: oidcConfig.clientId,
221
+ clientSecret: oidcConfig.clientSecret,
222
+ authorizationUrl: oidcConfig.authorizationEndpoint || void 0,
223
+ tokenUrl: oidcConfig.tokenEndpoint || void 0,
224
+ userInfoUrl: oidcConfig.userinfoEndpoint || void 0,
225
+ discoveryUrl: oidcConfig.discoveryEndpoint || `${oidcConfig.issuer}/.well-known/openid-configuration`,
226
+ scopes: oidcConfig.scopes || ["openid", "email", "profile"],
227
+ // Secure default: PKCE on. Disabling exposes auth-code
228
+ // interception/injection and requires an explicit false.
229
+ pkce: oidcConfig.pkce !== void 0 ? oidcConfig.pkce : true,
230
+ mapProfileToUser: (profile) => mapOidcProfile(profile, oidcConfig.mapping)
231
+ };
232
+ }
157
233
  function createBetterAuth(options) {
158
234
  const {
159
235
  db,
160
236
  adapterType,
161
237
  secret,
162
- baseURL = "http://localhost:3000",
163
238
  basePath = "/api/auth",
164
239
  trustedOrigins = [],
165
240
  enableEmailPassword = true,
241
+ disableSignUp = false,
166
242
  disableCSRFCheck = false,
167
243
  cookieCacheMaxAge = 5 * 60,
168
244
  socialProviders,
169
- oidcConfig
245
+ oidcConfig,
246
+ rateLimit,
247
+ ipAddressHeaders
170
248
  } = options;
171
249
  if (!secret || secret.length < MIN_SECRET_LENGTH) {
172
250
  throw new Error(
173
251
  `auth secret must be at least ${MIN_SECRET_LENGTH} characters; received ${secret ? secret.length : 0}`
174
252
  );
175
253
  }
254
+ const marker = isProductionEnv() ? placeholderMarker(secret) : void 0;
255
+ if (marker) {
256
+ throw new Error(
257
+ `auth secret looks like a placeholder (it contains "${marker}"); in production set a random secret of at least ${MIN_SECRET_LENGTH} characters, e.g. from \`openssl rand -base64 32\``
258
+ );
259
+ }
260
+ const baseURL = resolveAuthBaseURL(options.baseURL);
176
261
  const baseOrigin = new URL(baseURL).origin;
177
262
  const allTrustedOrigins = trustedOrigins.includes(baseOrigin) ? trustedOrigins : [baseOrigin, ...trustedOrigins];
178
263
  let schema;
@@ -199,37 +284,7 @@ function createBetterAuth(options) {
199
284
  });
200
285
  const plugins = [];
201
286
  if (oidcConfig) {
202
- const authorizationUrl = oidcConfig.authorizationEndpoint || `${oidcConfig.issuer}/protocol/openid-connect/auth`;
203
- const tokenUrl = oidcConfig.tokenEndpoint || `${oidcConfig.issuer}/protocol/openid-connect/token`;
204
- const userInfoUrl = oidcConfig.userinfoEndpoint || `${oidcConfig.issuer}/protocol/openid-connect/userinfo`;
205
- plugins.push(
206
- genericOAuth({
207
- config: [
208
- {
209
- providerId: oidcConfig.providerId || "oidc",
210
- clientId: oidcConfig.clientId,
211
- clientSecret: oidcConfig.clientSecret,
212
- authorizationUrl,
213
- tokenUrl,
214
- userInfoUrl,
215
- discoveryUrl: oidcConfig.discoveryEndpoint || `${oidcConfig.issuer}/.well-known/openid-configuration`,
216
- scopes: oidcConfig.scopes || ["openid", "email", "profile"],
217
- // Secure default: PKCE on. Disabling exposes auth-code
218
- // interception/injection and requires an explicit false.
219
- pkce: oidcConfig.pkce !== void 0 ? oidcConfig.pkce : true,
220
- mapProfileToUser: (profile) => {
221
- return {
222
- id: profile.sub || profile.id,
223
- email: profile.email,
224
- name: profile.name || profile.preferred_username,
225
- image: profile.picture || profile.image,
226
- emailVerified: profile.email_verified || false
227
- };
228
- }
229
- }
230
- ]
231
- })
232
- );
287
+ plugins.push(genericOAuth({ config: [oidcProviderConfig(oidcConfig)] }));
233
288
  }
234
289
  return betterAuth({
235
290
  database,
@@ -239,7 +294,8 @@ function createBetterAuth(options) {
239
294
  trustedOrigins: allTrustedOrigins,
240
295
  emailAndPassword: enableEmailPassword ? {
241
296
  enabled: true,
242
- autoSignIn: true
297
+ autoSignIn: true,
298
+ disableSignUp
243
299
  } : void 0,
244
300
  socialProviders: Object.keys(socialProviders || {}).length > 0 ? socialProviders : void 0,
245
301
  plugins,
@@ -251,24 +307,34 @@ function createBetterAuth(options) {
251
307
  maxAge: cookieCacheMaxAge
252
308
  }
253
309
  },
310
+ ...rateLimit === false ? { rateLimit: { enabled: false } } : {},
254
311
  advanced: {
255
312
  disableCSRFCheck,
256
- generateId: () => crypto.randomUUID().replace(/-/g, "")
313
+ // Pinned: left unset, better-auth skips its Origin check (CSRF on
314
+ // cookie requests) and its callbackURL/redirectTo validation (open
315
+ // redirects) whenever it thinks it runs under test: NODE_ENV=test,
316
+ // or any TEST variable other than "false" (TEST=0 included).
317
+ disableOriginCheck: false,
318
+ generateId: () => crypto.randomUUID().replace(/-/g, ""),
319
+ ...ipAddressHeaders ? { ipAddress: { ipAddressHeaders } } : {}
257
320
  }
258
321
  });
259
322
  }
260
323
  export {
261
324
  createBetterAuth,
325
+ mapOidcProfile,
262
326
  mysqlAccount,
263
327
  mysqlSchema,
264
328
  mysqlSession,
265
329
  mysqlUser,
266
330
  mysqlVerification,
331
+ oidcProviderConfig,
267
332
  pgAccount,
268
333
  pgSchema,
269
334
  pgSession,
270
335
  pgUser,
271
336
  pgVerification,
337
+ resolveAuthBaseURL,
272
338
  sqliteAccount,
273
339
  sqliteSchema,
274
340
  sqliteSession,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/better-auth-config.ts","../src/schema.ts"],"sourcesContent":["import { betterAuth, type Auth as BetterAuthInstance } from \"better-auth\";\nimport { drizzleAdapter, type DB as DrizzleAdapterDb } from \"better-auth/adapters/drizzle\";\nimport { genericOAuth } from \"better-auth/plugins/generic-oauth\";\nimport type { PgDatabase, PgQueryResultHKT } from \"drizzle-orm/pg-core\";\nimport type { MySqlDatabase, MySqlQueryResultHKT, PreparedQueryHKTBase } from \"drizzle-orm/mysql-core\";\nimport type { BaseSQLiteDatabase } from \"drizzle-orm/sqlite-core\";\nimport { pgSchema, mysqlSchema, sqliteSchema } from \"./schema\";\n\n/**\n * The Drizzle database handle auth-kit accepts. A union of the supported dialect\n * databases (mirrors web-kit's `WebKitDrizzleDb`) so the public input is a real\n * Drizzle instance rather than `any` leaking into callers. The dialect-core base\n * classes are part of `drizzle-orm` itself, so no driver dependency is required.\n */\nexport type AuthKitDrizzleDb =\n | PgDatabase<PgQueryResultHKT, Record<string, unknown>>\n | MySqlDatabase<MySqlQueryResultHKT, PreparedQueryHKTBase, Record<string, unknown>>\n | BaseSQLiteDatabase<\"sync\" | \"async\", unknown, Record<string, unknown>>;\n\n/** Minimum length, in characters, for the session-signing secret. */\nconst MIN_SECRET_LENGTH = 32;\n\nexport interface BetterAuthConfigOptions {\n db: AuthKitDrizzleDb;\n adapterType: \"postgres\" | \"mysql\" | \"sqlite\";\n secret: string;\n baseURL?: string;\n basePath?: string;\n trustedOrigins?: string[];\n enableEmailPassword?: boolean;\n disableCSRFCheck?: boolean;\n /**\n * Cookie-cache lifetime in seconds. This is the session-revocation lag: a\n * revoked session keeps passing cached cookie checks until the cache entry\n * expires. Lower it to tighten the revocation window (at the cost of more\n * frequent DB lookups). Defaults to 300 (5 minutes).\n */\n cookieCacheMaxAge?: number;\n // deno-lint-ignore no-explicit-any\n socialProviders?: Record<string, any>;\n oidcConfig?: {\n clientId: string;\n clientSecret: string;\n issuer: string;\n providerId?: string;\n authorizationEndpoint?: string;\n tokenEndpoint?: string;\n userinfoEndpoint?: string;\n jwksEndpoint?: string;\n discoveryEndpoint?: string;\n scopes?: string[];\n pkce?: boolean;\n mapping?: {\n id?: string;\n email?: string;\n emailVerified?: string;\n name?: string;\n image?: string;\n extraFields?: Record<string, string>;\n };\n };\n}\n\nexport function createBetterAuth(options: BetterAuthConfigOptions): BetterAuthInstance {\n const {\n db,\n adapterType,\n secret,\n baseURL = \"http://localhost:3000\",\n basePath = \"/api/auth\",\n trustedOrigins = [],\n enableEmailPassword = true,\n disableCSRFCheck = false,\n cookieCacheMaxAge = 5 * 60,\n socialProviders,\n oidcConfig,\n } = options;\n\n // A weak or empty secret signs forgeable sessions, so reject it before\n // betterAuth() ever sees it rather than silently building an insecure auth.\n if (!secret || secret.length < MIN_SECRET_LENGTH) {\n throw new Error(\n `auth secret must be at least ${MIN_SECRET_LENGTH} characters; received ${secret ? secret.length : 0}`,\n );\n }\n\n const baseOrigin = new URL(baseURL).origin;\n const allTrustedOrigins = trustedOrigins.includes(baseOrigin)\n ? trustedOrigins\n : [baseOrigin, ...trustedOrigins];\n\n let schema;\n let provider: \"pg\" | \"mysql\" | \"sqlite\";\n\n switch (adapterType) {\n case \"postgres\":\n schema = pgSchema;\n provider = \"pg\";\n break;\n case \"mysql\":\n schema = mysqlSchema;\n provider = \"mysql\";\n break;\n case \"sqlite\":\n schema = sqliteSchema;\n provider = \"sqlite\";\n break;\n default:\n throw new Error(`Unsupported adapter type: ${adapterType}`);\n }\n\n const database = drizzleAdapter(db as unknown as DrizzleAdapterDb, {\n provider,\n schema\n });\n\n const plugins = [];\n if (oidcConfig) {\n const authorizationUrl = oidcConfig.authorizationEndpoint ||\n `${oidcConfig.issuer}/protocol/openid-connect/auth`;\n const tokenUrl = oidcConfig.tokenEndpoint ||\n `${oidcConfig.issuer}/protocol/openid-connect/token`;\n const userInfoUrl = oidcConfig.userinfoEndpoint ||\n `${oidcConfig.issuer}/protocol/openid-connect/userinfo`;\n\n plugins.push(\n genericOAuth({\n config: [\n {\n providerId: oidcConfig.providerId || \"oidc\",\n clientId: oidcConfig.clientId,\n clientSecret: oidcConfig.clientSecret,\n authorizationUrl,\n tokenUrl,\n userInfoUrl,\n discoveryUrl: oidcConfig.discoveryEndpoint ||\n `${oidcConfig.issuer}/.well-known/openid-configuration`,\n scopes: oidcConfig.scopes || [\"openid\", \"email\", \"profile\"],\n // Secure default: PKCE on. Disabling exposes auth-code\n // interception/injection and requires an explicit false.\n pkce: oidcConfig.pkce !== undefined ? oidcConfig.pkce : true,\n mapProfileToUser: (profile: any) => {\n return {\n id: profile.sub || profile.id,\n email: profile.email,\n name: profile.name || profile.preferred_username,\n image: profile.picture || profile.image,\n emailVerified: profile.email_verified || false,\n };\n },\n },\n ],\n }),\n );\n }\n\n return betterAuth({\n database,\n secret,\n baseURL,\n basePath,\n trustedOrigins: allTrustedOrigins,\n emailAndPassword: enableEmailPassword\n ? {\n enabled: true,\n autoSignIn: true,\n }\n : undefined,\n socialProviders: Object.keys(socialProviders || {}).length > 0 ? socialProviders : undefined,\n plugins,\n session: {\n expiresIn: 60 * 60 * 24 * 7,\n updateAge: 60 * 60 * 24,\n cookieCache: {\n enabled: true,\n maxAge: cookieCacheMaxAge,\n },\n },\n advanced: {\n disableCSRFCheck,\n generateId: () => crypto.randomUUID().replace(/-/g, \"\"),\n },\n }) as unknown as BetterAuthInstance;\n}\n\nexport type Auth = ReturnType<typeof createBetterAuth>;\n","import { pgTable, text, timestamp, boolean } from \"drizzle-orm/pg-core\";\nimport { mysqlTable, varchar, timestamp as mysqlTimestamp, boolean as mysqlBoolean, text as mysqlText } from \"drizzle-orm/mysql-core\";\nimport { sqliteTable, text as sqliteText, integer } from \"drizzle-orm/sqlite-core\";\n\n// ==========================================\n// PostgreSQL Schema\n// ==========================================\n\nexport const pgUser = pgTable(\"user\", {\n id: text(\"id\").primaryKey(),\n name: text(\"name\"),\n email: text(\"email\").notNull().unique(),\n emailVerified: boolean(\"emailVerified\").notNull(),\n image: text(\"image\"),\n createdAt: timestamp(\"createdAt\").notNull(),\n updatedAt: timestamp(\"updatedAt\").notNull()\n});\n\nexport const pgSession = pgTable(\"session\", {\n id: text(\"id\").primaryKey(),\n expiresAt: timestamp(\"expiresAt\").notNull(),\n token: text(\"token\").notNull().unique(),\n createdAt: timestamp(\"createdAt\").notNull(),\n updatedAt: timestamp(\"updatedAt\").notNull(),\n ipAddress: text(\"ipAddress\"),\n userAgent: text(\"userAgent\"),\n userId: text(\"userId\").notNull().references(() => pgUser.id)\n});\n\nexport const pgAccount = pgTable(\"account\", {\n id: text(\"id\").primaryKey(),\n accountId: text(\"accountId\").notNull(),\n providerId: text(\"providerId\").notNull(),\n userId: text(\"userId\").notNull().references(() => pgUser.id),\n accessToken: text(\"accessToken\"),\n refreshToken: text(\"refreshToken\"),\n idToken: text(\"idToken\"),\n accessTokenExpiresAt: timestamp(\"accessTokenExpiresAt\"),\n refreshTokenExpiresAt: timestamp(\"refreshTokenExpiresAt\"),\n scope: text(\"scope\"),\n password: text(\"password\"),\n createdAt: timestamp(\"createdAt\").notNull(),\n updatedAt: timestamp(\"updatedAt\").notNull()\n});\n\nexport const pgVerification = pgTable(\"verification\", {\n id: text(\"id\").primaryKey(),\n identifier: text(\"identifier\").notNull(),\n value: text(\"value\").notNull(),\n expiresAt: timestamp(\"expiresAt\").notNull(),\n createdAt: timestamp(\"createdAt\"),\n updatedAt: timestamp(\"updatedAt\")\n});\n\nexport const pgSchema = {\n user: pgUser,\n session: pgSession,\n account: pgAccount,\n verification: pgVerification\n};\n\n// ==========================================\n// MySQL Schema\n// ==========================================\n\nexport const mysqlUser = mysqlTable(\"user\", {\n id: varchar(\"id\", { length: 36 }).primaryKey(),\n name: varchar(\"name\", { length: 255 }),\n email: varchar(\"email\", { length: 255 }).notNull().unique(),\n emailVerified: mysqlBoolean(\"emailVerified\").notNull(),\n image: varchar(\"image\", { length: 255 }),\n createdAt: mysqlTimestamp(\"createdAt\").notNull(),\n updatedAt: mysqlTimestamp(\"updatedAt\").notNull()\n});\n\nexport const mysqlSession = mysqlTable(\"session\", {\n id: varchar(\"id\", { length: 36 }).primaryKey(),\n expiresAt: mysqlTimestamp(\"expiresAt\").notNull(),\n token: varchar(\"token\", { length: 255 }).notNull().unique(),\n createdAt: mysqlTimestamp(\"createdAt\").notNull(),\n updatedAt: mysqlTimestamp(\"updatedAt\").notNull(),\n ipAddress: varchar(\"ipAddress\", { length: 45 }),\n userAgent: mysqlText(\"userAgent\"),\n userId: varchar(\"userId\", { length: 36 }).notNull().references(() => mysqlUser.id)\n});\n\nexport const mysqlAccount = mysqlTable(\"account\", {\n id: varchar(\"id\", { length: 36 }).primaryKey(),\n accountId: varchar(\"accountId\", { length: 255 }).notNull(),\n providerId: varchar(\"providerId\", { length: 255 }).notNull(),\n userId: varchar(\"userId\", { length: 36 }).notNull().references(() => mysqlUser.id),\n accessToken: mysqlText(\"accessToken\"),\n refreshToken: mysqlText(\"refreshToken\"),\n idToken: mysqlText(\"idToken\"),\n accessTokenExpiresAt: mysqlTimestamp(\"accessTokenExpiresAt\"),\n refreshTokenExpiresAt: mysqlTimestamp(\"refreshTokenExpiresAt\"),\n scope: mysqlText(\"scope\"),\n password: varchar(\"password\", { length: 255 }),\n createdAt: mysqlTimestamp(\"createdAt\").notNull(),\n updatedAt: mysqlTimestamp(\"updatedAt\").notNull()\n});\n\nexport const mysqlVerification = mysqlTable(\"verification\", {\n id: varchar(\"id\", { length: 36 }).primaryKey(),\n identifier: varchar(\"identifier\", { length: 255 }).notNull(),\n value: varchar(\"value\", { length: 255 }).notNull(),\n expiresAt: mysqlTimestamp(\"expiresAt\").notNull(),\n createdAt: mysqlTimestamp(\"createdAt\"),\n updatedAt: mysqlTimestamp(\"updatedAt\")\n});\n\nexport const mysqlSchema = {\n user: mysqlUser,\n session: mysqlSession,\n account: mysqlAccount,\n verification: mysqlVerification\n};\n\n// ==========================================\n// SQLite Schema\n// ==========================================\n\nexport const sqliteUser = sqliteTable(\"user\", {\n id: sqliteText(\"id\").primaryKey(),\n name: sqliteText(\"name\"),\n email: sqliteText(\"email\").notNull().unique(),\n emailVerified: integer(\"emailVerified\", { mode: \"boolean\" }).notNull(),\n image: sqliteText(\"image\"),\n createdAt: integer(\"createdAt\", { mode: \"timestamp\" }).notNull(),\n updatedAt: integer(\"updatedAt\", { mode: \"timestamp\" }).notNull()\n});\n\nexport const sqliteSession = sqliteTable(\"session\", {\n id: sqliteText(\"id\").primaryKey(),\n expiresAt: integer(\"expiresAt\", { mode: \"timestamp\" }).notNull(),\n token: sqliteText(\"token\").notNull().unique(),\n createdAt: integer(\"createdAt\", { mode: \"timestamp\" }).notNull(),\n updatedAt: integer(\"updatedAt\", { mode: \"timestamp\" }).notNull(),\n ipAddress: sqliteText(\"ipAddress\"),\n userAgent: sqliteText(\"userAgent\"),\n userId: sqliteText(\"userId\").notNull().references(() => sqliteUser.id)\n});\n\nexport const sqliteAccount = sqliteTable(\"account\", {\n id: sqliteText(\"id\").primaryKey(),\n accountId: sqliteText(\"accountId\").notNull(),\n providerId: sqliteText(\"providerId\").notNull(),\n userId: sqliteText(\"userId\").notNull().references(() => sqliteUser.id),\n accessToken: sqliteText(\"accessToken\"),\n refreshToken: sqliteText(\"refreshToken\"),\n idToken: sqliteText(\"idToken\"),\n accessTokenExpiresAt: integer(\"accessTokenExpiresAt\", { mode: \"timestamp\" }),\n refreshTokenExpiresAt: integer(\"refreshTokenExpiresAt\", { mode: \"timestamp\" }),\n scope: sqliteText(\"scope\"),\n password: sqliteText(\"password\"),\n createdAt: integer(\"createdAt\", { mode: \"timestamp\" }).notNull(),\n updatedAt: integer(\"updatedAt\", { mode: \"timestamp\" }).notNull()\n});\n\nexport const sqliteVerification = sqliteTable(\"verification\", {\n id: sqliteText(\"id\").primaryKey(),\n identifier: sqliteText(\"identifier\").notNull(),\n value: sqliteText(\"value\").notNull(),\n expiresAt: integer(\"expiresAt\", { mode: \"timestamp\" }).notNull(),\n createdAt: integer(\"createdAt\", { mode: \"timestamp\" }),\n updatedAt: integer(\"updatedAt\", { mode: \"timestamp\" })\n});\n\nexport const sqliteSchema = {\n user: sqliteUser,\n session: sqliteSession,\n account: sqliteAccount,\n verification: sqliteVerification\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/better-auth-config.ts","../src/schema.ts"],"sourcesContent":["import { betterAuth, type Auth as BetterAuthInstance, type BetterAuthOptions } from 'better-auth';\nimport { drizzleAdapter, type DB as DrizzleAdapterDb } from 'better-auth/adapters/drizzle';\nimport { genericOAuth, type GenericOAuthUserInfo } from 'better-auth/plugins/generic-oauth';\nimport type { PgDatabase, PgQueryResultHKT } from 'drizzle-orm/pg-core';\nimport type { MySqlDatabase, MySqlQueryResultHKT, PreparedQueryHKTBase } from 'drizzle-orm/mysql-core';\nimport type { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core';\nimport { pgSchema, mysqlSchema, sqliteSchema } from './schema';\nimport { isProductionEnv } from '@iskra-bun/core';\n\n/**\n * The Drizzle database handle auth-kit accepts. A union of the supported dialect\n * databases (mirrors web-kit's `WebKitDrizzleDb`) so the public input is a real\n * Drizzle instance rather than `any` leaking into callers. The dialect-core base\n * classes are part of `drizzle-orm` itself, so no driver dependency is required.\n */\nexport type AuthKitDrizzleDb =\n | PgDatabase<PgQueryResultHKT, Record<string, unknown>>\n | MySqlDatabase<MySqlQueryResultHKT, PreparedQueryHKTBase, Record<string, unknown>>\n | BaseSQLiteDatabase<'sync' | 'async', unknown, Record<string, unknown>>;\n\n/** Minimum length, in characters, for the session-signing secret. */\nconst MIN_SECRET_LENGTH = 32;\n\n/**\n * Pieces of the sample secrets docs and `.env.example` files ship. Compared\n * without case, `-`, `_`, `.` or spaces, so `change-me` also matches\n * `changeme` and `CHANGE_ME`.\n */\nconst PLACEHOLDER_SECRET_MARKERS = ['change-me', 'dev-secret', 'dev-only', 'your-secret', 'placeholder'];\n\nconst normalizeSecret = (value: string) => value.toLowerCase().replace(/[-_.\\s]/g, '');\n\n/** The placeholder marker `secret` contains, if any. */\nfunction placeholderMarker(secret: string): string | undefined {\n const normalized = normalizeSecret(secret);\n return PLACEHOLDER_SECRET_MARKERS.find((marker) => normalized.includes(normalizeSecret(marker)));\n}\n\n/** Hosts a production baseURL may reach over plain http (e.g. docker compose on one machine). */\nconst LOCAL_HOSTNAMES = new Set(['localhost', '127.0.0.1', '[::1]']);\n\n/**\n * The origin better-auth runs on: `baseURL`, else `BETTER_AUTH_URL`, else\n * `http://localhost:3000` outside production. It decides the cookies'\n * `Secure` flag and is a trusted origin, so production requires one and it\n * must be https (plain http only for localhost, 127.0.0.1 and [::1]). `who`\n * prefixes the error messages.\n */\nexport function resolveAuthBaseURL(baseURL?: string, who = 'createBetterAuth'): string {\n const resolved = baseURL || process.env.BETTER_AUTH_URL;\n if (resolved) {\n assertHttpsInProduction(resolved, who);\n return resolved;\n }\n if (isProductionEnv()) {\n throw new Error(\n `${who}: set baseURL (or BETTER_AUTH_URL) to the app's public origin in production, ` +\n 'e.g. \"https://app.example.com\"; without it cookies are sent without Secure.',\n );\n }\n return 'http://localhost:3000';\n}\n\n/**\n * better-auth marks the session cookies Secure only for an https baseURL, so\n * an http:// one in production sent them over plain HTTP as well.\n */\nfunction assertHttpsInProduction(baseURL: string, who: string): void {\n if (!isProductionEnv()) return;\n let url: URL;\n try {\n url = new URL(baseURL);\n } catch {\n return; // an invalid URL is reported by the caller\n }\n if (url.protocol === 'https:' || LOCAL_HOSTNAMES.has(url.hostname)) return;\n throw new Error(\n `${who}: baseURL \"${baseURL}\" must use https in production: better-auth marks the session cookies ` +\n 'Secure only for an https baseURL. Plain http is allowed only for localhost, 127.0.0.1 and [::1].',\n );\n}\n\nexport interface BetterAuthConfigOptions {\n db: AuthKitDrizzleDb;\n adapterType: 'postgres' | 'mysql' | 'sqlite';\n secret: string;\n /**\n * The app's public origin. Defaults to `BETTER_AUTH_URL`, then (outside\n * production only) `http://localhost:3000`; must be https in production\n * unless it is localhost. See `resolveAuthBaseURL`.\n */\n baseURL?: string;\n basePath?: string;\n trustedOrigins?: string[];\n enableEmailPassword?: boolean;\n /** Reject `/sign-up/email` (accounts are provisioned another way). Default false. */\n disableSignUp?: boolean;\n disableCSRFCheck?: boolean;\n /**\n * Cookie-cache lifetime in seconds. This is the session-revocation lag: a\n * revoked session keeps passing cached cookie checks until the cache entry\n * expires. Lower it to tighten the revocation window (at the cost of more\n * frequent DB lookups). Defaults to 300 (5 minutes).\n */\n cookieCacheMaxAge?: number;\n /**\n * `false` turns off better-auth's own rate limiter (on by default in\n * production), e.g. when the app limits the auth routes itself.\n */\n rateLimit?: false;\n /**\n * Request headers better-auth reads the client IP from, for its rate\n * limiter and the sessions' `ipAddress` (default `x-forwarded-for`, first\n * entry). Without a usable one, every client shares one rate-limit bucket.\n */\n ipAddressHeaders?: string[];\n /** better-auth's socialProviders option, as is. */\n socialProviders?: BetterAuthOptions['socialProviders'];\n oidcConfig?: {\n clientId: string;\n clientSecret: string;\n issuer: string;\n providerId?: string;\n authorizationEndpoint?: string;\n tokenEndpoint?: string;\n userinfoEndpoint?: string;\n /**\n * @deprecated Ignored: better-auth takes the JWKS only from the\n * discovery document's `jwks_uri`; point `discoveryEndpoint` at a\n * document that has the right one instead.\n */\n jwksEndpoint?: string;\n discoveryEndpoint?: string;\n scopes?: string[];\n pkce?: boolean;\n /** Claim names to read the user's fields from, instead of the standard ones. */\n mapping?: OidcClaimMapping;\n };\n}\n\n/** Claim names `mapOidcProfile` reads the user's fields from. */\nexport interface OidcClaimMapping {\n /**\n * @deprecated Ignored: better-auth always takes the account's identity\n * from the verified `sub` claim.\n */\n id?: string;\n email?: string;\n /** The claim is read as verified when it is `true` or `\"true\"`. */\n emailVerified?: string;\n name?: string;\n image?: string;\n /**\n * @deprecated Ignored: extra user fields need better-auth\n * `user.additionalFields`, which `createBetterAuth` does not declare.\n */\n extraFields?: Record<string, string>;\n}\n\n/**\n * The local user fields for an OIDC login (standard claims, with the common\n * non-standard fallbacks). A claim named in `mapping` is read instead of the\n * standard one when the profile has it. No `id`: better-auth takes the\n * account's identity from the verified `sub` (accountSubject) and ignores one\n * returned here.\n */\nexport function mapOidcProfile(profile: GenericOAuthUserInfo, mapping: OidcClaimMapping = {}) {\n const str = (v: unknown) => (typeof v === 'string' && v !== '' ? v : undefined);\n const claim = (name: string | undefined) => (name ? profile[name] : undefined);\n const isTrue = (v: unknown) => v === true || v === 'true';\n const standardVerified = profile.emailVerified === true || isTrue(profile.email_verified);\n const mappedEmail = str(claim(mapping.email));\n // better-auth links a login to the local user with the same email when it\n // is verified, so a flag must vouch for the address actually returned.\n // A mapped flag pairs with the mapped email (or with the standard one when\n // mapping.email is not set); the standard flag only vouches for the\n // standard email.\n const pairedFlag = mappedEmail !== undefined || !mapping.email ? claim(mapping.emailVerified) : undefined;\n let emailVerified: boolean;\n if (pairedFlag !== undefined && pairedFlag !== null) emailVerified = isTrue(pairedFlag);\n else if (mappedEmail !== undefined) emailVerified = mappedEmail === profile.email && standardVerified;\n else emailVerified = standardVerified;\n return {\n email: mappedEmail ?? profile.email,\n name: str(claim(mapping.name)) ?? (profile.name || str(profile.preferred_username)),\n image: str(claim(mapping.image)) ?? str(profile.picture) ?? profile.image,\n emailVerified,\n };\n}\n\n/**\n * The generic-oauth provider config for `oidcConfig`. The endpoints left\n * unset come from the issuer's discovery document: better-auth fills only\n * the ones not given, so a default here (e.g. Keycloak's\n * `/protocol/openid-connect/*` paths) would override discovery for every\n * other provider.\n */\nexport function oidcProviderConfig(oidcConfig: NonNullable<BetterAuthConfigOptions['oidcConfig']>) {\n return {\n providerId: oidcConfig.providerId || 'oidc',\n clientId: oidcConfig.clientId,\n clientSecret: oidcConfig.clientSecret,\n authorizationUrl: oidcConfig.authorizationEndpoint || undefined,\n tokenUrl: oidcConfig.tokenEndpoint || undefined,\n userInfoUrl: oidcConfig.userinfoEndpoint || undefined,\n discoveryUrl: oidcConfig.discoveryEndpoint || `${oidcConfig.issuer}/.well-known/openid-configuration`,\n scopes: oidcConfig.scopes || ['openid', 'email', 'profile'],\n // Secure default: PKCE on. Disabling exposes auth-code\n // interception/injection and requires an explicit false.\n pkce: oidcConfig.pkce !== undefined ? oidcConfig.pkce : true,\n mapProfileToUser: (profile: GenericOAuthUserInfo) => mapOidcProfile(profile, oidcConfig.mapping),\n };\n}\n\nexport function createBetterAuth(options: BetterAuthConfigOptions): BetterAuthInstance {\n const {\n db,\n adapterType,\n secret,\n basePath = '/api/auth',\n trustedOrigins = [],\n enableEmailPassword = true,\n disableSignUp = false,\n disableCSRFCheck = false,\n cookieCacheMaxAge = 5 * 60,\n socialProviders,\n oidcConfig,\n rateLimit,\n ipAddressHeaders,\n } = options;\n\n // A weak or empty secret signs forgeable sessions, so reject it before\n // betterAuth() ever sees it rather than silently building an insecure auth.\n if (!secret || secret.length < MIN_SECRET_LENGTH) {\n throw new Error(\n `auth secret must be at least ${MIN_SECRET_LENGTH} characters; received ${secret ? secret.length : 0}`,\n );\n }\n // A sample secret left in production is public: with it anyone can sign\n // the session cookie cache, which is trusted without a database lookup,\n // and so forge a session for any user.\n const marker = isProductionEnv() ? placeholderMarker(secret) : undefined;\n if (marker) {\n throw new Error(\n `auth secret looks like a placeholder (it contains \"${marker}\"); in production set a random secret ` +\n `of at least ${MIN_SECRET_LENGTH} characters, e.g. from \\`openssl rand -base64 32\\``,\n );\n }\n\n const baseURL = resolveAuthBaseURL(options.baseURL);\n const baseOrigin = new URL(baseURL).origin;\n const allTrustedOrigins = trustedOrigins.includes(baseOrigin) ? trustedOrigins : [baseOrigin, ...trustedOrigins];\n\n let schema;\n let provider: 'pg' | 'mysql' | 'sqlite';\n\n switch (adapterType) {\n case 'postgres':\n schema = pgSchema;\n provider = 'pg';\n break;\n case 'mysql':\n schema = mysqlSchema;\n provider = 'mysql';\n break;\n case 'sqlite':\n schema = sqliteSchema;\n provider = 'sqlite';\n break;\n default:\n throw new Error(`Unsupported adapter type: ${adapterType}`);\n }\n\n const database = drizzleAdapter(db as unknown as DrizzleAdapterDb, {\n provider,\n schema,\n });\n\n const plugins = [];\n if (oidcConfig) {\n plugins.push(genericOAuth({ config: [oidcProviderConfig(oidcConfig)] }));\n }\n\n return betterAuth({\n database,\n secret,\n baseURL,\n basePath,\n trustedOrigins: allTrustedOrigins,\n emailAndPassword: enableEmailPassword\n ? {\n enabled: true,\n autoSignIn: true,\n disableSignUp,\n }\n : undefined,\n socialProviders: Object.keys(socialProviders || {}).length > 0 ? socialProviders : undefined,\n plugins,\n session: {\n expiresIn: 60 * 60 * 24 * 7,\n updateAge: 60 * 60 * 24,\n cookieCache: {\n enabled: true,\n maxAge: cookieCacheMaxAge,\n },\n },\n ...(rateLimit === false ? { rateLimit: { enabled: false } } : {}),\n advanced: {\n disableCSRFCheck,\n // Pinned: left unset, better-auth skips its Origin check (CSRF on\n // cookie requests) and its callbackURL/redirectTo validation (open\n // redirects) whenever it thinks it runs under test: NODE_ENV=test,\n // or any TEST variable other than \"false\" (TEST=0 included).\n disableOriginCheck: false,\n generateId: () => crypto.randomUUID().replace(/-/g, ''),\n ...(ipAddressHeaders ? { ipAddress: { ipAddressHeaders } } : {}),\n },\n }) as unknown as BetterAuthInstance;\n}\n\nexport type Auth = ReturnType<typeof createBetterAuth>;\n","import { pgTable, text, timestamp, boolean } from 'drizzle-orm/pg-core';\nimport {\n mysqlTable,\n varchar,\n timestamp as mysqlTimestamp,\n boolean as mysqlBoolean,\n text as mysqlText,\n} from 'drizzle-orm/mysql-core';\nimport { sqliteTable, text as sqliteText, integer } from 'drizzle-orm/sqlite-core';\n\n// ==========================================\n// PostgreSQL Schema\n// ==========================================\n\nexport const pgUser = pgTable('user', {\n id: text('id').primaryKey(),\n name: text('name'),\n email: text('email').notNull().unique(),\n emailVerified: boolean('emailVerified').notNull(),\n image: text('image'),\n createdAt: timestamp('createdAt').notNull(),\n updatedAt: timestamp('updatedAt').notNull(),\n});\n\nexport const pgSession = pgTable('session', {\n id: text('id').primaryKey(),\n expiresAt: timestamp('expiresAt').notNull(),\n token: text('token').notNull().unique(),\n createdAt: timestamp('createdAt').notNull(),\n updatedAt: timestamp('updatedAt').notNull(),\n ipAddress: text('ipAddress'),\n userAgent: text('userAgent'),\n userId: text('userId')\n .notNull()\n .references(() => pgUser.id),\n});\n\nexport const pgAccount = pgTable('account', {\n id: text('id').primaryKey(),\n accountId: text('accountId').notNull(),\n providerId: text('providerId').notNull(),\n userId: text('userId')\n .notNull()\n .references(() => pgUser.id),\n accessToken: text('accessToken'),\n refreshToken: text('refreshToken'),\n idToken: text('idToken'),\n accessTokenExpiresAt: timestamp('accessTokenExpiresAt'),\n refreshTokenExpiresAt: timestamp('refreshTokenExpiresAt'),\n scope: text('scope'),\n password: text('password'),\n createdAt: timestamp('createdAt').notNull(),\n updatedAt: timestamp('updatedAt').notNull(),\n});\n\nexport const pgVerification = pgTable('verification', {\n id: text('id').primaryKey(),\n identifier: text('identifier').notNull(),\n value: text('value').notNull(),\n expiresAt: timestamp('expiresAt').notNull(),\n createdAt: timestamp('createdAt'),\n updatedAt: timestamp('updatedAt'),\n});\n\nexport const pgSchema = {\n user: pgUser,\n session: pgSession,\n account: pgAccount,\n verification: pgVerification,\n};\n\n// ==========================================\n// MySQL Schema\n// ==========================================\n\nexport const mysqlUser = mysqlTable('user', {\n id: varchar('id', { length: 36 }).primaryKey(),\n name: varchar('name', { length: 255 }),\n email: varchar('email', { length: 255 }).notNull().unique(),\n emailVerified: mysqlBoolean('emailVerified').notNull(),\n image: varchar('image', { length: 255 }),\n createdAt: mysqlTimestamp('createdAt').notNull(),\n updatedAt: mysqlTimestamp('updatedAt').notNull(),\n});\n\nexport const mysqlSession = mysqlTable('session', {\n id: varchar('id', { length: 36 }).primaryKey(),\n expiresAt: mysqlTimestamp('expiresAt').notNull(),\n token: varchar('token', { length: 255 }).notNull().unique(),\n createdAt: mysqlTimestamp('createdAt').notNull(),\n updatedAt: mysqlTimestamp('updatedAt').notNull(),\n ipAddress: varchar('ipAddress', { length: 45 }),\n userAgent: mysqlText('userAgent'),\n userId: varchar('userId', { length: 36 })\n .notNull()\n .references(() => mysqlUser.id),\n});\n\nexport const mysqlAccount = mysqlTable('account', {\n id: varchar('id', { length: 36 }).primaryKey(),\n accountId: varchar('accountId', { length: 255 }).notNull(),\n providerId: varchar('providerId', { length: 255 }).notNull(),\n userId: varchar('userId', { length: 36 })\n .notNull()\n .references(() => mysqlUser.id),\n accessToken: mysqlText('accessToken'),\n refreshToken: mysqlText('refreshToken'),\n idToken: mysqlText('idToken'),\n accessTokenExpiresAt: mysqlTimestamp('accessTokenExpiresAt'),\n refreshTokenExpiresAt: mysqlTimestamp('refreshTokenExpiresAt'),\n scope: mysqlText('scope'),\n password: varchar('password', { length: 255 }),\n createdAt: mysqlTimestamp('createdAt').notNull(),\n updatedAt: mysqlTimestamp('updatedAt').notNull(),\n});\n\nexport const mysqlVerification = mysqlTable('verification', {\n id: varchar('id', { length: 36 }).primaryKey(),\n identifier: varchar('identifier', { length: 255 }).notNull(),\n // text: better-auth stores OAuth state here (JSON longer than 255 characters),\n // which MySQL strict mode rejected, failing every OIDC sign-in.\n value: mysqlText('value').notNull(),\n expiresAt: mysqlTimestamp('expiresAt').notNull(),\n createdAt: mysqlTimestamp('createdAt'),\n updatedAt: mysqlTimestamp('updatedAt'),\n});\n\nexport const mysqlSchema = {\n user: mysqlUser,\n session: mysqlSession,\n account: mysqlAccount,\n verification: mysqlVerification,\n};\n\n// ==========================================\n// SQLite Schema\n// ==========================================\n\nexport const sqliteUser = sqliteTable('user', {\n id: sqliteText('id').primaryKey(),\n name: sqliteText('name'),\n email: sqliteText('email').notNull().unique(),\n emailVerified: integer('emailVerified', { mode: 'boolean' }).notNull(),\n image: sqliteText('image'),\n createdAt: integer('createdAt', { mode: 'timestamp' }).notNull(),\n updatedAt: integer('updatedAt', { mode: 'timestamp' }).notNull(),\n});\n\nexport const sqliteSession = sqliteTable('session', {\n id: sqliteText('id').primaryKey(),\n expiresAt: integer('expiresAt', { mode: 'timestamp' }).notNull(),\n token: sqliteText('token').notNull().unique(),\n createdAt: integer('createdAt', { mode: 'timestamp' }).notNull(),\n updatedAt: integer('updatedAt', { mode: 'timestamp' }).notNull(),\n ipAddress: sqliteText('ipAddress'),\n userAgent: sqliteText('userAgent'),\n userId: sqliteText('userId')\n .notNull()\n .references(() => sqliteUser.id),\n});\n\nexport const sqliteAccount = sqliteTable('account', {\n id: sqliteText('id').primaryKey(),\n accountId: sqliteText('accountId').notNull(),\n providerId: sqliteText('providerId').notNull(),\n userId: sqliteText('userId')\n .notNull()\n .references(() => sqliteUser.id),\n accessToken: sqliteText('accessToken'),\n refreshToken: sqliteText('refreshToken'),\n idToken: sqliteText('idToken'),\n accessTokenExpiresAt: integer('accessTokenExpiresAt', { mode: 'timestamp' }),\n refreshTokenExpiresAt: integer('refreshTokenExpiresAt', { mode: 'timestamp' }),\n scope: sqliteText('scope'),\n password: sqliteText('password'),\n createdAt: integer('createdAt', { mode: 'timestamp' }).notNull(),\n updatedAt: integer('updatedAt', { mode: 'timestamp' }).notNull(),\n});\n\nexport const sqliteVerification = sqliteTable('verification', {\n id: sqliteText('id').primaryKey(),\n identifier: sqliteText('identifier').notNull(),\n value: sqliteText('value').notNull(),\n expiresAt: integer('expiresAt', { mode: 'timestamp' }).notNull(),\n createdAt: integer('createdAt', { mode: 'timestamp' }),\n updatedAt: integer('updatedAt', { mode: 'timestamp' }),\n});\n\nexport const sqliteSchema = {\n user: sqliteUser,\n session: sqliteSession,\n account: sqliteAccount,\n verification: sqliteVerification,\n};\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iskra-bun/auth-kit",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Integracion de autenticacion de Iskra basada en better-auth, agnostica del transporte.",
5
5
  "keywords": [
6
6
  "iskra",
@@ -19,6 +19,9 @@
19
19
  },
20
20
  "homepage": "https://github.com/fearful/iskra/tree/main/packages/auth-kit#readme",
21
21
  "bugs": "https://github.com/fearful/iskra/issues",
22
+ "engines": {
23
+ "bun": ">=1.3.0"
24
+ },
22
25
  "type": "module",
23
26
  "main": "./dist/index.js",
24
27
  "module": "./dist/index.js",
@@ -46,9 +49,9 @@
46
49
  "build": "tsup --config ../../tsup.config.ts"
47
50
  },
48
51
  "dependencies": {
49
- "@iskra-bun/core": "0.1.1",
50
- "better-auth": "^1.4.18",
51
- "drizzle-orm": "^0.45.1"
52
+ "@iskra-bun/core": "^0.2.0",
53
+ "better-auth": "^1.6.33",
54
+ "drizzle-orm": "^0.45.2"
52
55
  },
53
56
  "devDependencies": {
54
57
  "@types/bun": "^1.3.5",