@ingram-tech/nk-auth 0.12.0 → 0.12.2

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/README.md CHANGED
@@ -17,7 +17,7 @@ exactly one Better Auth copy in the app.
17
17
  | `createAuthPool` (`./pool`) | **deprecated** — alias of `createPool` from [`@ingram-tech/nk-db`](../nk-db); inject the site's shared pool instead |
18
18
  | `makeEmailSenders`, `makePasskeyOptions`, `passkeyOptionsForBaseUrl`, `uuidGenerateId` (`./`) | email hooks, passkeys (`passkeyOptionsForBaseUrl` derives `rpID`/`origin` from a single base URL), UUID ids |
19
19
  | `bcryptPassword` (`./`) | **legacy only** — bcrypt verifier for sites with pre-existing bcrypt hashes. New sites omit it (Better Auth defaults to scrypt). See [Migrating bcrypt passwords to scrypt](#migrating-bcrypt-passwords-to-scrypt) |
20
- | `createAuthHelpers`, `safeNext` (`./server`) | validated App Router session helpers (`getSession` / `getUser` / `requireSession` / `requireUser` / `redirectIfAuthenticated`) with automatic `next` + stale-cookie signalling; `safeNext` validates a `?next=` param |
20
+ | `createAuthHelpers`, `safeNext` (`./server`) | validated App Router session helpers (`getSession` / `getUser` / `requireSession` / `requireUser` / `redirectIfAuthenticated`), request-memoized via React `cache()`, with automatic `next` + stale-cookie signalling; `safeNext` validates a `?next=` param |
21
21
  | `createAuthMiddleware` (`./middleware`) | loop-safe edge middleware: gates unauthenticated users off protected paths, preserves `next`, and clears a stale session cookie so a bad session self-heals |
22
22
 
23
23
  > **Data access + RLS** is owned by [`@ingram-tech/nk-db`](../nk-db): query over a
@@ -252,7 +252,8 @@ export const config = {
252
252
 
253
253
  Why the split: middleware runs before render and can't afford a DB lookup, so it
254
254
  can only trust the cookie *exists*. The server helpers hit `auth.api.getSession`
255
- and check the session *contents*. When those disagree (revoked session, rotated
255
+ and check the session *contents* (once per request the read is memoized with
256
+ React `cache()`). When those disagree (revoked session, rotated
256
257
  secret, wiped DB) the validated layer wins and parks the user on `/login` — and
257
258
  because middleware refuses to bounce `/login`, the form renders instead of
258
259
  ping-ponging.
@@ -348,14 +349,16 @@ async redirects() {
348
349
  ## Migrating bcrypt passwords to scrypt
349
350
 
350
351
  `bcryptPassword` is **legacy support only** (see its `@deprecated` note). It
351
- exists so sites whose `account.password` hashes are bcrypt keep verifying.
352
- Better Auth's default hasher is **scrypt** (`<salt-hex>:<key-hex>`), and bcrypt
353
- hashes are trivially distinguishable (they start with `$2a$`/`$2b$`/`$2y$`), so
354
- the migration path is a **dual-format verifier**: override only
352
+ exists so sites whose `account.password` hashes are bcrypt keep verifying
353
+ that is all nk-auth ships for the bcrypt case.
354
+
355
+ The path to move a site fully onto scrypt is a **dual-format verifier**, wired
356
+ in the site (nk-auth does not ship it). Better Auth's default hasher is scrypt
357
+ (`<salt-hex>:<key-hex>`) and bcrypt hashes are trivially distinguishable (they
358
+ start with `$2a$`/`$2b$`/`$2y$`), so override only
355
359
  `emailAndPassword.password.verify` to branch on `hash.startsWith("$2")` →
356
- bcrypt compare, else Better Auth's scrypt verify. Old hashes keep working;
357
- every new signup, password change, and reset writes scrypt. (Better Auth has no
358
- rehash-on-login and no "must reset" gate, so bcrypt hashes only upgrade when
359
- the user resets — or via a sign-in wrapper that persists a re-hash with
360
- `internalAdapter.updatePassword`.)
361
- **Status: proposed** — not yet shipped; `bcryptPassword` remains the stopgap.
360
+ bcrypt compare, else Better Auth's scrypt verify. Old hashes keep working; every
361
+ new signup, password change, and reset writes scrypt. Better Auth has no
362
+ rehash-on-login and no "must reset" gate, so bcrypt hashes only upgrade when the
363
+ user resets — or via a sign-in wrapper that persists a re-hash with
364
+ `internalAdapter.updatePassword`.
package/dist/jwt.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAGN,KAAK,UAAU,EAEf,MAAM,MAAM,CAAC;AAEd;;;;;GAKG;AAEH,MAAM,WAAW,gBAAgB;IAChC,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,sEAAsE;AACtE,eAAO,MAAM,iBAAiB,GAAI,QAAQ,gBAAgB,KAAG,UAM3D,CAAC;AAWH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,GAAU,QAAQ;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf,KAAG,OAAO,CAAC,UAAU,CAmCrB,CAAC"}
1
+ {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAGN,KAAK,UAAU,EAEf,MAAM,MAAM,CAAC;AAEd;;;;;GAKG;AAEH,MAAM,WAAW,gBAAgB;IAChC,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,sEAAsE;AACtE,eAAO,MAAM,iBAAiB,WAAY,gBAAgB,KAAG,UAM3D,CAAC;AAWH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,WAAkB;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf,KAAG,OAAO,CAAC,UAAU,CAmCrB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,KAAK,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG7D,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,sFAAsF;IACtF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,IAyBrC,SAAS,WAAW,KAAG,YAAY,CAkE9D"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,KAAK,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG7D,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,sFAAsF;IACtF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,aAyB5B,WAAW,KAAG,YAAY,CAkE9D"}
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAM3D,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC;;;;;;;;GAQG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc;qBACT,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;kCAItC;QACF,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KACjB,KAAG,OAAO,CAAC,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,WAAW,aAAa;IAC7B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC1B;AAED,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,GAAI,KAAK,aAAa,KAAG,cAItD,CAAC;AAEH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,GACpC,SAAS,MAAM,EACf,QAAQ,MAAM,KACZ,cAKA,CAAC;AAEJ,oFAAoF;AACpF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACZ,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEvB;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,SAAS;wCAI5C;QACF,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC;KACZ,KAAG,OAAO,CAAC,IAAI,CAAC;4CAMd;QACF,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC;KACZ,KAAG,OAAO,CAAC,IAAI,CAAC;CAGhB,CAAC"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAM3D,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC;;;;;;;;GAQG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc;IAC1B,IAAI,aAAa,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;IACzC,MAAM,wBAGH;QACF,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KACjB,KAAG,OAAO,CAAC,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,WAAW,aAAa;IAC7B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC1B;AAED,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,QAAS,aAAa,KAAG,cAItD,CAAC;AAEH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,YAC3B,MAAM,UACP,MAAM,KACZ,cAKA,CAAC;AAEJ,oFAAoF;AACpF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACZ,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEvB;;;GAGG;AACH,eAAO,MAAM,gBAAgB,SAAU,SAAS;IAC/C,iBAAiB,mBAGd;QACF,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC;KACZ,KAAG,OAAO,CAAC,IAAI,CAAC;IAGjB,qBAAqB,mBAGlB;QACF,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC;KACZ,KAAG,OAAO,CAAC,IAAI,CAAC;CAGhB,CAAC"}
@@ -38,8 +38,8 @@ export declare const lastActiveOrganizationHooks: (pool: Pool) => {
38
38
  create: {
39
39
  before: (session: SessionLike) => Promise<{
40
40
  data: {
41
- activeOrganizationId: string;
42
41
  userId: string;
42
+ activeOrganizationId: string;
43
43
  };
44
44
  } | undefined>;
45
45
  };
@@ -1 +1 @@
1
- {"version":3,"file":"organization.d.ts","sourceRoot":"","sources":["../src/organization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE/B;;;;GAIG;AAEH,2EAA2E;AAC3E,eAAO,MAAM,sBAAsB;IAClC,sCAAsC;;IAEtC,gDAAgD;;CAEvC,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,+BAA+B;;;;;;;CAOlC,CAAC;AAEX,UAAU,WAAW;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,GAAI,MAAM,IAAI;;;8BAG3B,WAAW;;;4BAb7B,MAAM;;;;;6BAqCW,WAAW;;;CAYnC,CAAC"}
1
+ {"version":3,"file":"organization.d.ts","sourceRoot":"","sources":["../src/organization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE/B;;;;GAIG;AAEH,2EAA2E;AAC3E,eAAO,MAAM,sBAAsB;IAClC,sCAAsC;aACtC,mBAAmB;IACnB,gDAAgD;aAChD,WAAW,EAAE,OAAO;CACX,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,+BAA+B;aAC3C,wBAAwB;iBACvB,IAAI,EAAE,QAAQ;iBACd,QAAQ;iBACR,KAAK;iBACL,QAAQ;;CAEA,CAAC;AAEX,UAAU,WAAW;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,SAAU,IAAI;IACrD,OAAO;QACN,MAAM;YACL,MAAM,YAAkB,WAAW;;4BAb7B,MAAM;;;;;QAoCb,MAAM;YACL,KAAK,YAAkB,WAAW;;;CAYnC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"password.js","sourceRoot":"","sources":["../src/password.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,YAAY,CAAC;AAEnD,kEAAkE;AAClE,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAE7C,kEAAkE;AAClE,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAS/C;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,SAAyB,EAAE;IACzD,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,2BAA2B,CAAC;IAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,2BAA2B,CAAC;IAC5D,OAAO,CAAC;SACN,MAAM,EAAE;SACR,GAAG,CAAC,GAAG,EAAE,6BAA6B,GAAG,cAAc,CAAC;SACxD,GAAG,CAAC,GAAG,EAAE,4BAA4B,GAAG,cAAc,CAAC,CAAC;AAC3D,CAAC;AAsBD;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAClC,WAAmB,EACnB,eAAuB,EACvB,SAAyB,EAAE;IAE3B,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,2BAA2B,CAAC;IAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,2BAA2B,CAAC;IAC5D,IAAI,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC9B,OAAO;YACN,IAAI,EAAE,oBAAoB;YAC1B,OAAO,EAAE,6BAA6B,GAAG,cAAc;YACvD,SAAS,EAAE,GAAG;SACd,CAAC;IACH,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC9B,OAAO;YACN,IAAI,EAAE,mBAAmB;YACzB,OAAO,EAAE,4BAA4B,GAAG,cAAc;YACtD,SAAS,EAAE,GAAG;SACd,CAAC;IACH,CAAC;IACD,IAAI,WAAW,KAAK,eAAe,EAAE,CAAC;QACrC,OAAO;YACN,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,yBAAyB;SAClC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"password.js","sourceRoot":"","sources":["../src/password.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,YAAY,CAAC;AAEnD,kEAAkE;AAClE,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAE7C,kEAAkE;AAClE,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAS/C;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,MAAM,GAAmB,EAAE;IACzD,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,2BAA2B,CAAC;IAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,2BAA2B,CAAC;IAC5D,OAAO,CAAC;SACN,MAAM,EAAE;SACR,GAAG,CAAC,GAAG,EAAE,6BAA6B,GAAG,cAAc,CAAC;SACxD,GAAG,CAAC,GAAG,EAAE,4BAA4B,GAAG,cAAc,CAAC,CAAC;AAC3D,CAAC;AAsBD;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAClC,WAAmB,EACnB,eAAuB,EACvB,MAAM,GAAmB,EAAE;IAE3B,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,2BAA2B,CAAC;IAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,2BAA2B,CAAC;IAC5D,IAAI,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC9B,OAAO;YACN,IAAI,EAAE,oBAAoB;YAC1B,OAAO,EAAE,6BAA6B,GAAG,cAAc;YACvD,SAAS,EAAE,GAAG;SACd,CAAC;IACH,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC9B,OAAO;YACN,IAAI,EAAE,mBAAmB;YACzB,OAAO,EAAE,4BAA4B,GAAG,cAAc;YACtD,SAAS,EAAE,GAAG;SACd,CAAC;IACH,CAAC;IACD,IAAI,WAAW,KAAK,eAAe,EAAE,CAAC;QACrC,OAAO;YACN,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,yBAAyB;SAClC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE/B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ;IACtC,gBAAgB,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,KAAG,IAID,CAAC"}
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE/B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,WAAY;IACtC,gBAAgB,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,KAAG,IAID,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AA6BA;;;;GAIG;AACH,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAElE,oEAAoE;AACpE,UAAU,WAAW;IACpB,IAAI,EAAE,OAAO,CAAC;CACd;AAED;;;;GAIG;AACH,UAAU,QAAQ,CAAC,CAAC,SAAS,WAAW;IACvC,GAAG,EAAE;QACJ,UAAU,EAAE,CAAC,KAAK,EAAE;YAAE,OAAO,EAAE,OAAO,CAAA;SAAE,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC/D;;;;;WAKG;QACH,gBAAgB,EAAE,CAAC,KAAK,EAAE;YACzB,OAAO,EAAE,OAAO,CAAC;SACjB,KAAK,OAAO,CAAC,KAAK,CAAC;YAAE,UAAU,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC,CAAC;KAC7C,CAAC;CACF;AAED,MAAM,WAAW,kBAAkB;IAClC,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,WAAW,EACtD,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EACjB,OAAO,GAAE,kBAAuB;sBAMH,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;mBAKpB,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;0BAkClB,OAAO,CAAC,CAAC,CAAC;uBAXb,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;kCAuBL,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;8BAU5B,OAAO,CAAC,MAAM,EAAE,CAAC;gCAcf,OAAO,CAAC,OAAO,CAAC;EAcvD"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAgCA;;;;GAIG;AACH,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAElE,oEAAoE;AACpE,UAAU,WAAW;IACpB,IAAI,EAAE,OAAO,CAAC;CACd;AAED;;;;GAIG;AACH,UAAU,QAAQ,CAAC,CAAC,SAAS,WAAW;IACvC,GAAG,EAAE;QACJ,UAAU,EAAE,CAAC,KAAK,EAAE;YAAE,OAAO,EAAE,OAAO,CAAA;SAAE,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC/D;;;;;WAKG;QACH,gBAAgB,EAAE,CAAC,KAAK,EAAE;YACzB,OAAO,EAAE,OAAO,CAAC;SACjB,KAAK,OAAO,CAAC,KAAK,CAAC;YAAE,UAAU,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC,CAAC;KAC7C,CAAC;CACF;AAED,MAAM,WAAW,kBAAkB;IAClC,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,WAAW,EACtD,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EACjB,OAAO,GAAE,kBAAuB;sBAkBrB,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;mBAKF,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;0BAkClB,OAAO,CAAC,CAAC,CAAC;uBAXb,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;kCAuBL,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;8BAU5B,OAAO,CAAC,MAAM,EAAE,CAAC;gCAcf,OAAO,CAAC,OAAO,CAAC;EAcvD"}
package/dist/server.js CHANGED
@@ -10,9 +10,11 @@
10
10
  * export const { getSession, getUser, requireSession, requireUser,
11
11
  * redirectIfAuthenticated } = createAuthHelpers(auth);
12
12
  *
13
- * These are the **validated** authority: every call hits `auth.api.getSession`,
14
- * which checks the session against the database — not merely the presence of a
15
- * cookie. When a guard finds no valid session it redirects to the sign-in page,
13
+ * These are the **validated** authority: they resolve through
14
+ * `auth.api.getSession`, which checks the session against the database — not
15
+ * merely the presence of a cookie. The read is memoized per request with React
16
+ * `cache()`, so a render fanning out many `getUser()` calls validates once,
17
+ * not once per call. When a guard finds no valid session it redirects to the sign-in page,
16
18
  * preserving the requested path as `next` (read from the header the middleware
17
19
  * injects) and, when a session cookie is present-but-invalid, adding `stale=1`
18
20
  * so the middleware clears the dead cookie. The optimistic, cookie-presence
@@ -24,6 +26,7 @@
24
26
  */
25
27
  import { cookies, headers } from "next/headers";
26
28
  import { redirect } from "next/navigation";
29
+ import { cache } from "react";
27
30
  import { NK_AUTH_PATH_HEADER, signInUrl } from "./gating-internals.js";
28
31
  import { CREDENTIAL_PROVIDER_ID } from "./password.js";
29
32
  /**
@@ -35,10 +38,19 @@ export { safeNextParam as safeNext } from "./gating-internals.js";
35
38
  export function createAuthHelpers(auth, options = {}) {
36
39
  const signInPath = options.signInPath ?? "/login";
37
40
  const cookiePrefix = options.sessionCookiePrefix ?? "better-auth";
38
- /** The validated session ({ user, session, … }) or null. */
39
- async function getSession() {
40
- return auth.api.getSession({ headers: await headers() });
41
- }
41
+ /**
42
+ * The validated session ({ user, session, … }) or null. Memoized per request
43
+ * via React `cache()`: the session cookie is constant within a request, so
44
+ * every helper (and every component calling one) shares a single database
45
+ * validation. Outside a request scope (scripts, tests) `cache()` degrades to
46
+ * an uncached call.
47
+ *
48
+ * Caveat: code that mutates the session mid-request (e.g. a server action
49
+ * updating the user) and then re-reads it through these helpers sees the
50
+ * pre-mutation snapshot; re-read through `auth.api.getSession` directly if
51
+ * that ever matters.
52
+ */
53
+ const getSession = cache(async () => auth.api.getSession({ headers: await headers() }));
42
54
  /** The authenticated user, or null. */
43
55
  async function getUser() {
44
56
  const session = await getSession();
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingram-tech/nk-auth",
3
- "version": "0.12.0",
3
+ "version": "0.12.2",
4
4
  "description": "The Ingram Better Auth foundation: composable presets (org, dual-shape JWT, active-org hooks, pg pool) for Next.js sites.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -65,7 +65,7 @@
65
65
  "test": "vitest run"
66
66
  },
67
67
  "dependencies": {
68
- "@ingram-tech/nk-db": "^1.2.0",
68
+ "@ingram-tech/nk-db": "^1.3.1",
69
69
  "bcrypt": "^6.0.0",
70
70
  "jose": "^6.2.3",
71
71
  "zod": "^4.4.3"
@@ -92,17 +92,17 @@
92
92
  }
93
93
  },
94
94
  "devDependencies": {
95
- "@better-auth/passkey": "^1.6.22",
96
- "@ingram-tech/nk-dev": "0.2.5",
95
+ "@better-auth/passkey": "^1.6.23",
96
+ "@ingram-tech/nk-dev": "0.5.0",
97
97
  "@types/bcrypt": "^6.0.0",
98
- "@types/node": "^26.0.1",
98
+ "@types/node": "^26.1.1",
99
99
  "@types/pg": "^8.20.0",
100
100
  "@types/react": "^19.2.17",
101
- "better-auth": "^1.6.22",
102
- "next": "^16.2.9",
101
+ "better-auth": "^1.6.23",
102
+ "next": "^16.2.10",
103
103
  "pg": "^8.22.0",
104
104
  "react": "^19.2.7",
105
- "typescript": "^6.0.3",
106
- "vitest": "^4.1.9"
105
+ "typescript": "^7.0.2",
106
+ "vitest": "^4.1.10"
107
107
  }
108
108
  }