@ingram-tech/nk-auth 0.12.0 → 0.12.3
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 +15 -12
- package/dist/jwt.d.ts.map +1 -1
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +8 -5
- package/dist/middleware.js.map +1 -1
- package/dist/options.d.ts +8 -0
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +8 -0
- package/dist/options.js.map +1 -1
- package/dist/organization.d.ts +1 -1
- package/dist/organization.d.ts.map +1 -1
- package/dist/password.js.map +1 -1
- package/dist/pool.d.ts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +19 -7
- package/dist/server.js.map +1 -1
- package/package.json +9 -9
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
|
|
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
|
-
|
|
353
|
-
|
|
354
|
-
|
|
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
|
-
|
|
358
|
-
rehash-on-login and no "must reset" gate, so bcrypt hashes only upgrade when
|
|
359
|
-
|
|
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,
|
|
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"}
|
package/dist/middleware.d.ts.map
CHANGED
|
@@ -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,
|
|
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,aAiC5B,WAAW,KAAG,YAAY,CA6D9D"}
|
package/dist/middleware.js
CHANGED
|
@@ -32,11 +32,17 @@ export function createAuthMiddleware(config) {
|
|
|
32
32
|
const signInPath = config.signInPath ?? "/login";
|
|
33
33
|
const frontDoorPaths = config.frontDoorPaths ?? [];
|
|
34
34
|
const cookiePrefix = config.sessionCookiePrefix ?? "better-auth";
|
|
35
|
+
// Segment-boundary match: "/app" gates "/app" and "/app/x" but not
|
|
36
|
+
// "/application". Used for both the construction-time loop check and the
|
|
37
|
+
// per-request gate, so the two can't drift (a broader construction check
|
|
38
|
+
// would reject safe configs like protectedPaths ["/log"] + signInPath
|
|
39
|
+
// "/login", where "/login" is never actually gated).
|
|
40
|
+
const isProtected = (path) => config.protectedPaths.some((p) => path === p || path.startsWith(`${p}/`));
|
|
35
41
|
// Loop-safety, enforced once at construction rather than hoped-for per
|
|
36
42
|
// request. The sign-in path is where the validated guard parks an
|
|
37
43
|
// invalid-but-present session; it must never be the target of an optimistic
|
|
38
44
|
// redirect, or a stale cookie loops.
|
|
39
|
-
if (
|
|
45
|
+
if (isProtected(signInPath)) {
|
|
40
46
|
throw new Error(`@ingram-tech/nk-auth: signInPath "${signInPath}" must not fall under protectedPaths — a cookie-less visit would redirect to itself forever.`);
|
|
41
47
|
}
|
|
42
48
|
if (frontDoorPaths.includes(signInPath)) {
|
|
@@ -74,10 +80,7 @@ export function createAuthMiddleware(config) {
|
|
|
74
80
|
const hasSessionCookie = !!getSessionCookie(request);
|
|
75
81
|
// 2. Unauthenticated (no cookie) on a protected path -> sign in, and
|
|
76
82
|
// remember where they were going.
|
|
77
|
-
if (!hasSessionCookie &&
|
|
78
|
-
// Segment-boundary match: "/app" must gate "/app" and "/app/x" but not
|
|
79
|
-
// "/application".
|
|
80
|
-
config.protectedPaths.some((p) => path === p || path.startsWith(`${p}/`))) {
|
|
83
|
+
if (!hasSessionCookie && isProtected(path)) {
|
|
81
84
|
const original = request.nextUrl.pathname + request.nextUrl.search;
|
|
82
85
|
const to = request.nextUrl.clone();
|
|
83
86
|
to.pathname = signInPath;
|
package/dist/middleware.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAoB,YAAY,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AA0B3E,MAAM,UAAU,oBAAoB,CAAC,MAA4B;IAChE,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,QAAQ,CAAC;IACjD,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;IACnD,MAAM,YAAY,GAAG,MAAM,CAAC,mBAAmB,IAAI,aAAa,CAAC;IAEjE,
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
|
package/dist/options.d.ts
CHANGED
|
@@ -17,6 +17,14 @@ export { uuidGenerateId } from "./id.js";
|
|
|
17
17
|
* Better Auth's default is scrypt — new sites should omit this and use that
|
|
18
18
|
* default. Sites still on bcrypt should migrate hashes to scrypt and drop this;
|
|
19
19
|
* see the nk-auth README (§"Migrating bcrypt passwords to scrypt") for the path.
|
|
20
|
+
*
|
|
21
|
+
* NOTE: bcrypt silently truncates the password at **72 bytes**, so two passwords
|
|
22
|
+
* sharing their first 72 bytes verify as equal — even though the password policy
|
|
23
|
+
* allows up to {@link DEFAULT_MAX_PASSWORD_LENGTH} (128) characters. This is a
|
|
24
|
+
* property of bcrypt, not a bug here, and it's deliberately not length-guarded:
|
|
25
|
+
* a guard would break verification of the legacy long-password hashes this
|
|
26
|
+
* preset exists to support (bcrypt already truncated them at hash time). It is
|
|
27
|
+
* one more reason to migrate off bcrypt — scrypt has no such ceiling.
|
|
20
28
|
*/
|
|
21
29
|
export declare const bcryptPassword: {
|
|
22
30
|
hash: (password: string) => Promise<string>;
|
package/dist/options.d.ts.map
CHANGED
|
@@ -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
|
|
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;;;;;;;;;;;;;;;;GAgBG;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"}
|
package/dist/options.js
CHANGED
|
@@ -20,6 +20,14 @@ export { uuidGenerateId } from "./id.js";
|
|
|
20
20
|
* Better Auth's default is scrypt — new sites should omit this and use that
|
|
21
21
|
* default. Sites still on bcrypt should migrate hashes to scrypt and drop this;
|
|
22
22
|
* see the nk-auth README (§"Migrating bcrypt passwords to scrypt") for the path.
|
|
23
|
+
*
|
|
24
|
+
* NOTE: bcrypt silently truncates the password at **72 bytes**, so two passwords
|
|
25
|
+
* sharing their first 72 bytes verify as equal — even though the password policy
|
|
26
|
+
* allows up to {@link DEFAULT_MAX_PASSWORD_LENGTH} (128) characters. This is a
|
|
27
|
+
* property of bcrypt, not a bug here, and it's deliberately not length-guarded:
|
|
28
|
+
* a guard would break verification of the legacy long-password hashes this
|
|
29
|
+
* preset exists to support (bcrypt already truncated them at hash time). It is
|
|
30
|
+
* one more reason to migrate off bcrypt — scrypt has no such ceiling.
|
|
23
31
|
*/
|
|
24
32
|
export const bcryptPassword = {
|
|
25
33
|
hash: (password) => bcrypt.hash(password, 10),
|
package/dist/options.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,iFAAiF;AACjF,kFAAkF;AAClF,iEAAiE;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC;;;;;;;;GAQG;AAEH
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,iFAAiF;AACjF,kFAAkF;AAClF,iEAAiE;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC7B,IAAI,EAAE,CAAC,QAAgB,EAAmB,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;IACtE,MAAM,EAAE,CAAC,EACR,IAAI,EACJ,QAAQ,GAIR,EAAoB,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC;CACtD,CAAC;AAWF,iFAAiF;AACjF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAkB,EAAkB,EAAE,CAAC,CAAC;IAC1E,IAAI,EAAE,GAAG,CAAC,IAAI;IACd,MAAM,EAAE,GAAG,CAAC,MAAM;IAClB,MAAM,EAAE,GAAG,CAAC,MAAM;CAClB,CAAC,CAAC;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACvC,OAAe,EACf,MAAc,EACG,EAAE,CACnB,kBAAkB,CAAC;IAClB,IAAI,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ;IAC/B,MAAM;IACN,MAAM,EAAE,OAAO;CACf,CAAC,CAAC;AASJ;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAe,EAAE,EAAE,CAAC,CAAC;IACrD,iBAAiB,EAAE,KAAK,EAAE,EACzB,IAAI,EACJ,GAAG,GAIH,EAAiB,EAAE;QACnB,MAAM,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,qBAAqB,EAAE,KAAK,EAAE,EAC7B,IAAI,EACJ,GAAG,GAIH,EAAiB,EAAE;QACnB,MAAM,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAE,CAAC,CAAC;IACnE,CAAC;CACD,CAAC,CAAC"}
|
package/dist/organization.d.ts
CHANGED
|
@@ -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
|
|
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"}
|
package/dist/password.js.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/pool.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"
|
|
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:
|
|
14
|
-
* which checks the session against the database — not
|
|
15
|
-
*
|
|
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
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
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();
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA
|
|
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.
|
|
3
|
+
"version": "0.12.3",
|
|
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.
|
|
68
|
+
"@ingram-tech/nk-db": "^1.4.0",
|
|
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.
|
|
96
|
-
"@ingram-tech/nk-dev": "0.
|
|
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.
|
|
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.
|
|
102
|
-
"next": "^16.2.
|
|
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": "^
|
|
106
|
-
"vitest": "^4.1.
|
|
105
|
+
"typescript": "^7.0.2",
|
|
106
|
+
"vitest": "^4.1.10"
|
|
107
107
|
}
|
|
108
108
|
}
|