@gauts/auth 0.9.0 → 0.10.1

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.
Files changed (45) hide show
  1. package/README.md +91 -80
  2. package/SECURITY.md +8 -4
  3. package/dist/adapters/express/index.d.ts +7 -13
  4. package/dist/adapters/express/index.d.ts.map +1 -1
  5. package/dist/adapters/express/index.js +6 -6
  6. package/dist/adapters/express/index.js.map +1 -1
  7. package/dist/adapters/fastify/index.d.ts +7 -13
  8. package/dist/adapters/fastify/index.d.ts.map +1 -1
  9. package/dist/adapters/fastify/index.js +5 -5
  10. package/dist/adapters/fastify/index.js.map +1 -1
  11. package/dist/adapters/hono/index.d.ts +7 -13
  12. package/dist/adapters/hono/index.d.ts.map +1 -1
  13. package/dist/adapters/hono/index.js +5 -5
  14. package/dist/adapters/hono/index.js.map +1 -1
  15. package/dist/adapters/next/index.d.ts +2 -7
  16. package/dist/adapters/next/index.d.ts.map +1 -1
  17. package/dist/adapters/next/index.js +9 -39
  18. package/dist/adapters/next/index.js.map +1 -1
  19. package/dist/adapters/utils/session.d.ts.map +1 -1
  20. package/dist/adapters/utils/session.js +70 -78
  21. package/dist/adapters/utils/session.js.map +1 -1
  22. package/dist/adapters/utils/types.d.ts +3 -9
  23. package/dist/adapters/utils/types.d.ts.map +1 -1
  24. package/dist/config.d.ts +1 -2
  25. package/dist/config.d.ts.map +1 -1
  26. package/dist/config.js +1 -2
  27. package/dist/config.js.map +1 -1
  28. package/dist/headers/index.d.ts +7 -0
  29. package/dist/headers/index.d.ts.map +1 -0
  30. package/dist/headers/index.js +37 -0
  31. package/dist/headers/index.js.map +1 -0
  32. package/dist/index.d.ts +1 -1
  33. package/dist/session/cookie.d.ts +6 -8
  34. package/dist/session/cookie.d.ts.map +1 -1
  35. package/dist/session/cookie.js +7 -24
  36. package/dist/session/cookie.js.map +1 -1
  37. package/dist/session/state.d.ts +41 -0
  38. package/dist/session/state.d.ts.map +1 -0
  39. package/dist/session/state.js +192 -0
  40. package/dist/session/state.js.map +1 -0
  41. package/package.json +5 -1
  42. package/dist/session/cache.d.ts +0 -32
  43. package/dist/session/cache.d.ts.map +0 -1
  44. package/dist/session/cache.js +0 -138
  45. package/dist/session/cache.js.map +0 -1
package/README.md CHANGED
@@ -12,7 +12,7 @@ Database-backed password authentication, opaque browser sessions, and optional s
12
12
  | bcrypt password hashing | ✅ | Opt-in |
13
13
  | Opaque server-side sessions | ✅ | Enabled |
14
14
  | Database-backed validation | ✅ | Enabled |
15
- | Sliding session renewal | ✅ | Every 24 hours |
15
+ | Automatic sliding renewal | ✅ | Every 24 hours |
16
16
  | Absolute session lifetime | ✅ | 30 days |
17
17
  | Signed browser cache | ✅ | Disabled |
18
18
  | Full User-Agent validation | ✅ | Enabled |
@@ -35,11 +35,11 @@ Database-backed password authentication, opaque browser sessions, and optional s
35
35
  | OTP and transactional email | ❌ | Application-owned |
36
36
  | Route roles and permissions | ❌ | Application-owned |
37
37
 
38
- “Session renewal” extends the existing session expiry when activity continues. It is not a refresh-token flow and does not rotate the opaque browser token.
38
+ “Session renewal” extends the existing session expiry when authenticated activity continues. Framework middleware performs it inline when due. It is not a refresh-token flow and does not rotate the opaque browser token.
39
39
 
40
40
  ## Quick start
41
41
 
42
- The application defines its credential login, renewal, logout, and protected endpoints. Optional addons are configured separately after this base setup.
42
+ The application defines its credential login, logout, protected endpoints, and the optional explicit renewal endpoint used by server-rendered frontends. Optional addons are configured separately after this base setup.
43
43
 
44
44
  ### 1. Install the package
45
45
 
@@ -147,6 +147,14 @@ export const authDb = createDrizzleAdapter({
147
147
 
148
148
  This Hono example is identical for Prisma and Drizzle:
149
149
 
150
+ Generate one high-entropy API secret and keep it server-side:
151
+
152
+ ```bash
153
+ openssl rand -base64 48
154
+ ```
155
+
156
+ Store the result as `AUTH_SECRET` in the API environment. Do not expose it through a public frontend variable.
157
+
150
158
  ```ts
151
159
  import { createHonoAuth } from "@gauts/auth/hono";
152
160
 
@@ -154,6 +162,7 @@ import { authDb } from "./authDb.js";
154
162
 
155
163
  export const auth = createHonoAuth({
156
164
  db: authDb,
165
+ secret: process.env.AUTH_SECRET!,
157
166
  });
158
167
  ```
159
168
 
@@ -166,7 +175,7 @@ renewal every 24 hours
166
175
  max lifetime 30 days
167
176
  validation User-Agent
168
177
  cache disabled
169
- cookies __ses, __cac, __ren
178
+ cookies __ses, __ctx
170
179
  ```
171
180
 
172
181
  Mount the application-owned login routes and the package middleware:
@@ -274,7 +283,7 @@ export const proxy = async (request: NextRequest) => {
274
283
  };
275
284
  ```
276
285
 
277
- The application owns the redirect URL. When `unauthorizedUrl` is provided, the adapter creates the redirect and copies every API `Set-Cookie` header to it before returning the final response. The frontend does not receive `AUTH_SECRET`; the API remains responsible for session validation.
286
+ The application owns the redirect URL. When `unauthorizedUrl` is provided, the adapter creates the redirect and copies every API `Set-Cookie` header to it before returning the final response. The frontend does not receive `AUTH_SECRET`; it reads only untrusted scheduling dates from `__ctx`. The API verifies the signature and remains responsible for session validation.
278
287
 
279
288
  ## Requirements and package entry points
280
289
 
@@ -297,6 +306,7 @@ The application owns the redirect URL. When `unauthorizedUrl` is provided, the a
297
306
  | `@gauts/auth/express` | Express cookies, methods, and middleware. |
298
307
  | `@gauts/auth/fastify` | Fastify cookies, methods, decorators, and hooks. |
299
308
  | `@gauts/auth/next` | Next.js renewal scheduling and `Set-Cookie` forwarding. |
309
+ | `@gauts/auth/headers` | Browser-safe controlled header forwarding helpers. |
300
310
  | `@gauts/auth/providers` | Google, GitHub, and X OAuth providers. |
301
311
 
302
312
  ## Configuration reference
@@ -311,7 +321,7 @@ The application owns the redirect URL. When `unauthorizedUrl` is provided, the a
311
321
  | `session` | `SessionConfig` | ❌ | Session defaults | Expiry, renewal, and client validation configuration. |
312
322
  | `cookie` | `HonoCookieConfig` | ❌ | Cookie defaults | Names, domain, path, SameSite, and Secure settings. |
313
323
  | `cache` | `{ ttl: number }` | ❌ | Disabled | Enables the short signed browser cache. |
314
- | `secret` | `string` | With `cache` or `social` | — | HMAC secret for signed authentication data. Minimum 32 UTF-8 bytes. |
324
+ | `secret` | `string` || — | HMAC secret for signed session context and optional social data. Minimum 32 UTF-8 bytes. |
315
325
  | `social` | `SocialConfig` | ❌ | Disabled | Enables configured social providers, redirects, and optional registration. |
316
326
 
317
327
  ```ts
@@ -404,17 +414,16 @@ renew_at = min((updated_at ?? created_at) + renewInterval, maxExpiresAt)
404
414
 
405
415
  ### Cookies
406
416
 
407
- | Property | Type / allowed values | Default | Description |
408
- | ------------- | ----------------------------- | ----------------- | ------------------------------------------------------------------------- |
409
- | `sessionName` | Valid cookie name | `"__ses"` | Contains the opaque token. This is the only authenticating cookie. |
410
- | `cacheName` | Valid cookie name | `"__cac"` | Contains the optional signed short cache. |
411
- | `renewName` | Valid cookie name | `"__ren"` | Contains the untrusted `renew_at` Unix timestamp. |
412
- | `domain` | `string` | Browser host only | Optional cookie domain. |
413
- | `path` | String beginning with `/` | `"/"` | Cookie path. |
414
- | `sameSite` | `"Strict" \| "Lax" \| "None"` | `"Lax"` | Browser SameSite policy. |
415
- | `secure` | `boolean` | `true` | Requires HTTPS when enabled. Set `false` only for local HTTP development. |
417
+ | Property | Type / allowed values | Default | Description |
418
+ | ------------- | ----------------------------- | ----------------- | --------------------------------------------------------------------------------------------- |
419
+ | `sessionName` | Valid cookie name | `"__ses"` | Contains the opaque token. This is the only authenticating cookie. |
420
+ | `contextName` | Valid cookie name | `"__ctx"` | Contains signed renewal scheduling and the optional short cache. It never authenticates alone. |
421
+ | `domain` | `string` | Browser host only | Optional cookie domain. |
422
+ | `path` | String beginning with `/` | `"/"` | Cookie path. |
423
+ | `sameSite` | `"Strict" \| "Lax" \| "None"` | `"Lax"` | Browser SameSite policy. |
424
+ | `secure` | `boolean` | `true` | Requires HTTPS when enabled. Set `false` only for local HTTP development. |
416
425
 
417
- All three cookies are always `HttpOnly` and expire with their respective server-side purpose. Their names must be unique.
426
+ Both cookies are always `HttpOnly`, expire with the authoritative session, and must use unique names. Deleting `__ctx` does not log the user out: the next authenticated API request validates `__ses` through the database and rebuilds the signed context. Deleting `__ses` ends browser authentication because `__ctx` is never accepted on its own.
418
427
 
419
428
  Cookie prefix rules are enforced:
420
429
 
@@ -434,53 +443,50 @@ The resolved names are available through:
434
443
 
435
444
  ```ts
436
445
  auth.cookie.sessionName; // "__ses"
437
- auth.cookie.cacheName; // "__cac"
438
- auth.cookie.renewName; // "__ren"
446
+ auth.cookie.contextName; // "__ctx"
439
447
  ```
440
448
 
441
- ### Signed cache
449
+ ### Signed session context
442
450
 
443
- | Property | Type / allowed values | Default | Description |
444
- | ----------- | ----------------------------------- | -------- | --------------------------------------------------------- |
445
- | `cache.ttl` | Integer `1` to `session.ttl` | Disabled | Maximum cache lifetime in seconds. |
446
- | `secret` | String with at least 32 UTF-8 bytes | — | Signs the cache with HMAC-SHA-256. Required with `cache`. |
451
+ | Property | Type / allowed values | Default | Description |
452
+ | ----------- | ----------------------------------- | -------- | ------------------------------------------------------------------ |
453
+ | `secret` | String with at least 32 UTF-8 bytes | Required | Signs `__ctx` with HMAC-SHA-256 and binds it to the opaque token. |
454
+ | `cache.ttl` | Integer `1` to `session.ttl` | Disabled | Enables cached account/session data for at most this many seconds. |
447
455
 
448
- The cache:
456
+ The signed context always contains the session expiry and next renewal time. When caching is configured, it may also contain the selected account and session data. The context:
449
457
 
450
- - is cryptographically bound to the opaque token and client identity;
451
- - is accepted only for `GET` and `HEAD`;
452
- - never extends the authoritative database session;
453
- - is bypassed for unsafe methods, renewal, logout, WebSockets, and core calls;
454
- - falls back to normal database authentication when absent, expired, malformed, or altered.
458
+ - is cryptographically bound to `__ses` and cannot authenticate without it;
459
+ - is verified by the API before any cached data is trusted;
460
+ - exposes untrusted `renew` and `exp` scheduling values to the Next.js adapter without exposing `AUTH_SECRET`;
461
+ - uses cached data only for `GET` and `HEAD`;
462
+ - never extends the authoritative database session by itself;
463
+ - bypasses cached data for unsafe methods, renewal, logout, WebSockets, and core calls;
464
+ - triggers normal database authentication and a fresh signed context when absent, expired, malformed, altered, or bound to another token.
455
465
 
456
- The cache is signed but not encrypted. Do not place passwords, password hashes, raw session tokens, or application secrets in account/session data.
466
+ The context is signed but not encrypted. Do not place passwords, password hashes, raw session tokens, or application secrets in selected account/session data.
457
467
 
458
468
  <details>
459
- <summary>Internal compact cache payload</summary>
469
+ <summary>Internal signed context payload</summary>
460
470
 
461
471
  ```ts
462
472
  {
463
- exp: cacheExpiresAt,
464
- acc: {
465
- id,
466
- email,
467
- name,
468
- role,
469
- status,
470
- timezone,
471
- user: { id, role, status },
472
- },
473
- ses: {
474
- id,
475
- client: { ip, agent, platform },
476
- created_at,
477
- exp: expiresAt,
478
- ren: renewAt,
479
- },
473
+ cache: {
474
+ data: {
475
+ account,
476
+ session: {
477
+ client,
478
+ created,
479
+ id,
480
+ },
481
+ },
482
+ exp: cacheExpiresAt,
483
+ } | null,
484
+ exp: sessionExpiresAt,
485
+ renew: renewAt,
480
486
  }
481
487
  ```
482
488
 
483
- `session.account_id` is reconstructed from `acc.id` after signature validation.
489
+ The payload is encoded as `base64url(payload).signature`. The Next.js adapter may decode `exp` and `renew` only as scheduling hints. The API verifies the signature against the current opaque token before using any value. `session.account_id` is reconstructed from `account.id` after verification.
484
490
 
485
491
  </details>
486
492
 
@@ -623,6 +629,7 @@ export const auth = createHonoAuth({
623
629
  users: { table: users },
624
630
  },
625
631
  }),
632
+ secret: process.env.AUTH_SECRET!,
626
633
  });
627
634
  ```
628
635
 
@@ -678,11 +685,11 @@ export const nextAuth = createNextAuth({
678
685
  });
679
686
  ```
680
687
 
681
- | Property | Type / allowed values | Required | Default | Description |
682
- | -------------------- | -------------------------------- | :------: | --------- | --------------------------------------------- |
683
- | `renewUrl` | Absolute `http:` or `https:` URL | ✅ | — | Trusted private API renewal endpoint. |
684
- | `cookie.sessionName` | Valid cookie name | ❌ | `"__ses"` | Session cookie read and forwarded to the API. |
685
- | `cookie.renewName` | Valid cookie name | ❌ | `"__ren"` | Renewal scheduling cookie read by Next.js. |
688
+ | Property | Type / allowed values | Required | Default | Description |
689
+ | -------------------- | -------------------------------- | :------: | --------- | -------------------------------------------------------- |
690
+ | `renewUrl` | Absolute `http:` or `https:` URL | ✅ | — | Trusted private API renewal endpoint. |
691
+ | `cookie.sessionName` | Valid cookie name | ❌ | `"__ses"` | Session cookie read and forwarded to the API. |
692
+ | `cookie.contextName` | Valid cookie name | ❌ | `"__ctx"` | Signed context decoded only to schedule SSR renewal. |
686
693
 
687
694
  ## Session flow
688
695
 
@@ -695,8 +702,8 @@ credentials accepted
695
702
  -> load current account and owning user
696
703
  -> apply configured account/user access rules
697
704
  -> write __ses
698
- -> write __ren
699
- -> optionally write __cac
705
+ -> write signed __ctx with renewal schedule
706
+ -> optionally include short cached data inside __ctx
700
707
  ```
701
708
 
702
709
  Only the raw browser token authenticates. The database stores only its SHA-256 hash.
@@ -704,12 +711,16 @@ Only the raw browser token authenticates. The database stores only its SHA-256 h
704
711
  ### Protected `GET` or `HEAD`
705
712
 
706
713
  ```text
707
- session token
708
- -> valid signed cache?
709
- -> yes: expose cached account and session
710
- -> no: validate through DB and create a fresh cache
714
+ __ses + __ctx
715
+ -> renewal due?
716
+ -> yes: validate and renew through DB, then write both cookies
717
+ -> no: valid signed cache?
718
+ -> yes: expose cached account and session
719
+ -> no: validate through DB and write a fresh signed context
711
720
  ```
712
721
 
722
+ Renewal happens inside the same protected API request. A client-side fetch does not need a second renewal request.
723
+
713
724
  ### Unsafe request
714
725
 
715
726
  ```text
@@ -717,22 +728,22 @@ session token
717
728
  -> SHA-256 hash
718
729
  -> indexed DB lookup
719
730
  -> validate expiry, revocation, account/user access, and client
720
- -> clear short cache
731
+ -> write signed context without cached account data
721
732
  -> continue
722
733
  ```
723
734
 
724
- ### Renewal
735
+ ### Next.js SSR renewal
725
736
 
726
737
  ```text
727
- Next reads __ren
728
- -> future timestamp: no API request
738
+ Next decodes renew and exp from __ctx as untrusted hints
739
+ -> future timestamps: no renewal request
729
740
  -> missing, invalid, or due: POST /auth/renew
730
741
  -> API validates through DB
731
742
  -> update expires_at when renewal is due
732
- -> Set-Cookie with the same token, new renewAt, and fresh cache
743
+ -> Set-Cookie with the same token and fresh signed context
733
744
  ```
734
745
 
735
- `auth.session.resolve()` is always DB-backed and read-only. Only explicit renewal updates database expiry.
746
+ `auth.session.resolve()` is always DB-backed and read-only. `auth.session.renew()` performs the authoritative renewal. Framework `requireSession` calls it automatically when the verified context says renewal is due; the explicit endpoint gives Next.js the same behavior during SSR navigation.
736
747
 
737
748
  ## Hono adapter
738
749
 
@@ -793,7 +804,7 @@ await auth.createSession({
793
804
  | Method | Purpose |
794
805
  | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
795
806
  | `auth.createSession({ account_id, context, country? })` | Creates the DB session and writes the browser cookies. `country` is optional login-time metadata. |
796
- | `auth.resolveSession(context)` | Resolves a request and returns the selected account and session. |
807
+ | `auth.resolveSession(context)` | Resolves a request, renews inline when due, and returns the selected account and session. |
797
808
  | `auth.renewSession(context)` | Performs DB validation, renews when due, and writes authoritative cookies. |
798
809
  | `auth.revokeSession(context)` | Revokes the current DB session and clears cookies. |
799
810
  | `auth.clearSession(context)` | Clears browser cookies without revoking the DB session. |
@@ -807,7 +818,7 @@ await auth.createSession({
807
818
  ```ts
808
819
  import { createExpressAuth, type ExpressAuthLocals } from "@gauts/auth/express";
809
820
 
810
- const auth = createExpressAuth({ db });
821
+ const auth = createExpressAuth({ db, secret: process.env.AUTH_SECRET! });
811
822
 
812
823
  app.get("/account", auth.requireSession, (_request, response) => {
813
824
  const { account, session, user } = response.locals as ExpressAuthLocals;
@@ -818,7 +829,7 @@ app.get("/account", auth.requireSession, (_request, response) => {
818
829
  | Method | Purpose |
819
830
  | ----------------------------------------------------------------- | ---------------------------------------------------- |
820
831
  | `auth.createSession({ account_id, request, response, country? })` | Creates the DB session and writes cookies. |
821
- | `auth.resolveSession({ request, response })` | Resolves the selected account and session. |
832
+ | `auth.resolveSession({ request, response })` | Resolves and automatically renews when due. |
822
833
  | `auth.renewSession({ request, response })` | Renews when due and writes authoritative cookies. |
823
834
  | `auth.revokeSession({ request, response })` | Revokes the current session and clears cookies. |
824
835
  | `auth.clearSession(response)` | Clears cookies without revoking the DB session. |
@@ -834,7 +845,7 @@ Register the request decorators once before declaring routes:
834
845
  ```ts
835
846
  import { createFastifyAuth } from "@gauts/auth/fastify";
836
847
 
837
- const auth = createFastifyAuth({ db });
848
+ const auth = createFastifyAuth({ db, secret: process.env.AUTH_SECRET! });
838
849
 
839
850
  auth.decorate(app);
840
851
 
@@ -849,7 +860,7 @@ app.get("/account", { preHandler: auth.requireSession }, (request) => ({
849
860
  | -------------------------------------------------------------- | -------------------------------------------------------------- |
850
861
  | `auth.decorate(app)` | Declares the native request decorators once at startup. |
851
862
  | `auth.createSession({ account_id, request, reply, country? })` | Creates the DB session and writes cookies. |
852
- | `auth.resolveSession({ request, reply })` | Resolves the selected account and session. |
863
+ | `auth.resolveSession({ request, reply })` | Resolves and automatically renews when due. |
853
864
  | `auth.renewSession({ request, reply })` | Renews when due and writes authoritative cookies. |
854
865
  | `auth.revokeSession({ request, reply })` | Revokes the current session and clears cookies. |
855
866
  | `auth.clearSession(reply)` | Clears cookies without revoking the DB session. |
@@ -1187,12 +1198,13 @@ import { createHonoAdapter } from "@gauts/auth/hono";
1187
1198
  const core = createAuth({ db });
1188
1199
  const hono = createHonoAdapter({
1189
1200
  auth: core,
1201
+ secret: process.env.AUTH_SECRET!,
1190
1202
  });
1191
1203
  ```
1192
1204
 
1193
1205
  ## Next.js adapter
1194
1206
 
1195
- The Next.js adapter schedules renewal; it does not authenticate pages or API requests.
1207
+ The Next.js adapter schedules SSR renewal; it does not authenticate pages or API requests. Normal API middleware independently verifies `__ctx` and renews inline, including requests made directly by client-side SWR or `fetch`.
1196
1208
 
1197
1209
  ```ts
1198
1210
  import type { NextRequest } from "next/server";
@@ -1218,18 +1230,18 @@ Result values:
1218
1230
 
1219
1231
  | `attempted` | `status` | Meaning |
1220
1232
  | :---------: | ----------: | --------------------------------------------------------------- |
1221
- | `false` | `null` | Session token exists and renewal is not due. |
1233
+ | `false` | `null` | Session token and context schedule exist; renewal is not due. |
1222
1234
  | `false` | `401` | Session token is missing or malformed; no API request occurred. |
1223
1235
  | `true` | HTTP status | The renewal endpoint was called and returned this status. |
1224
1236
 
1225
1237
  `unauthorizedUrl` is optional. When provided, the adapter redirects a `401` to that relative or absolute URL and transfers every returned `Set-Cookie` header to the redirect. Without it, the original response is returned with `status: 401` as before.
1226
1238
 
1227
- The adapter forwards only the session cookie and controlled client/origin headers required by the private API. Other cookies, authorization headers, and arbitrary headers are not forwarded.
1239
+ The adapter forwards only the session cookie and controlled client/origin headers required by the private API. `__ctx` is not forwarded because the API renewal endpoint always validates the opaque token through the database and returns a new signed context. Other cookies, authorization headers, and arbitrary headers are not forwarded.
1228
1240
 
1229
- `buildForwardHeaders()` and `FORWARD_HEADERS` are exported from `@gauts/auth/next` for application fetchers that need the same controlled forwarding rules:
1241
+ `buildForwardHeaders()` and `FORWARD_HEADERS` are exported from the browser-safe `@gauts/auth/headers` entrypoint for application fetchers that need the same controlled forwarding rules:
1230
1242
 
1231
1243
  ```ts
1232
- import { buildForwardHeaders } from "@gauts/auth/next";
1244
+ import { buildForwardHeaders } from "@gauts/auth/headers";
1233
1245
 
1234
1246
  const headers = buildForwardHeaders({
1235
1247
  headers: incoming,
@@ -1241,7 +1253,7 @@ Safe client and proxy metadata is copied by default. Credentials such as `cookie
1241
1253
 
1242
1254
  When `Origin` is absent and trusted `X-Forwarded-Proto` and `X-Forwarded-Host` headers exist, the adapter reconstructs the public origin from them. It never derives a public origin from the internal Next.js request URL. The deployment proxy must overwrite forwarded headers received from untrusted clients.
1243
1255
 
1244
- Apply renewal only to protected routes or skip public routes before calling `nextAuth.renew()`.
1256
+ Apply renewal only to protected routes or skip public routes before calling `nextAuth.renew()`. The adapter calls the API only when `__ctx` is missing, malformed, expired, or its decoded renewal time is due. Those decoded dates are untrusted scheduling hints; they never authenticate the request.
1245
1257
 
1246
1258
  ## Core session API
1247
1259
 
@@ -1306,9 +1318,9 @@ The Prisma and Drizzle adapters implement both `DbAdapter` and `SocialDbAdapter`
1306
1318
 
1307
1319
  The package contains no Redis or in-process cache.
1308
1320
 
1309
- Without the optional browser cache, each `requireSession` performs an indexed database lookup through `account_sessions.token_hash`.
1321
+ Without the optional browser cache, each `requireSession` performs an indexed database lookup through `account_sessions.token_hash`. When renewal is due, that same request also updates the authoritative expiry and returns refreshed cookies; there is no additional client-side API call.
1310
1322
 
1311
- With a valid cache, `GET` and `HEAD` skip the lookup until `cache.ttl` expires. Unsafe methods always use current database state.
1323
+ With valid cached data inside `__ctx`, `GET` and `HEAD` skip the lookup until `cache.ttl` expires. Unsafe methods always use current database state. Renewal still validates through the database even if cached data is present.
1312
1324
 
1313
1325
  The tradeoff is explicit: revocation and selected account or relation changes made elsewhere may remain visible to safe cached requests until the short TTL expires. A 60-second TTL limits this stale-read window to one minute. Disable cache when immediate read revocation is required.
1314
1326
 
@@ -1360,7 +1372,6 @@ The package provides authentication primitives, not a complete application secur
1360
1372
  - TLS and trusted-proxy configuration;
1361
1373
  - CSRF, CORS, host, and origin validation;
1362
1374
  - login and renewal rate limiting;
1363
- - equivalent password verification work for unknown accounts;
1364
1375
  - route roles and authorization;
1365
1376
  - re-authentication for sensitive operations;
1366
1377
  - database migrations and session cleanup;
package/SECURITY.md CHANGED
@@ -29,20 +29,24 @@ Security reports may cover the password service, session core, database adapters
29
29
 
30
30
  Application-specific authorization, rate limiting, CSRF, CORS, proxy trust, deployment, and database access policies remain the consuming application's responsibility unless the vulnerability is caused by package behavior.
31
31
 
32
- ## Signed session cache
32
+ ## Signed session context
33
33
 
34
- The optional browser cache is disabled when omitted. When configured, it is accepted only for `GET` and `HEAD` requests and is signed with HMAC-SHA-256 using an application-provided secret of at least 32 bytes.
34
+ Browser integration uses an opaque session-token cookie and a signed context cookie. The context is signed with HMAC-SHA-256 using an API-only application secret of at least 32 bytes and is cryptographically bound to the opaque token. It contains session expiry and renewal scheduling plus optional short cached account/session data. It never authenticates without the opaque token.
35
35
 
36
- The cache is bound to the opaque session token, its own expiry, the authoritative session expiry, and the configured client fields. Invalid cache data never authenticates a request; it causes normal database validation.
36
+ The API verifies the context signature before trusting any cached value. Missing, malformed, expired, altered, or incorrectly bound context data causes normal database validation and a new context cookie. It does not revoke an otherwise valid opaque session. The Next.js adapter may decode the expiry and renewal values without the secret, but treats them only as untrusted scheduling hints.
37
+
38
+ The optional browser cache is disabled when omitted. When configured, it is accepted only for `GET` and `HEAD` requests and remains bound to its own expiry, the authoritative session expiry, and the configured client fields.
37
39
 
38
40
  Cookie caching introduces a bounded consistency window. A session revoked on another device, or selected account or relation access changed in the database, may remain readable until the cache TTL expires. Unsafe methods, renewal, logout, WebSockets, and direct core calls always validate through the database. Applications requiring immediate cross-device read revocation must leave the cache disabled or provide shared server-side enforcement outside this package.
39
41
 
40
- Keep `AUTH_SECRET` in the API environment. Do not expose it to browser code or share it with a frontend merely to inspect the renewal timestamp. The timestamp is intentionally untrusted and never authenticates or renews a session by itself.
42
+ Keep `AUTH_SECRET` in the API environment. Do not expose it to browser code or share it with a frontend merely to inspect scheduling values. Those values are intentionally untrusted and never authenticate or renew a session by themselves.
41
43
 
42
44
  ## Session lifetime
43
45
 
44
46
  Sliding renewal is limited by `session.maxLifetime`, which defaults to 30 days from the original login. The maximum expiry is derived from the immutable session `created_at` value and enforced by the core during resolution and renewal. Browser cookies and cached session data never outlive the authoritative session expiry.
45
47
 
48
+ Framework middleware renews inline when the verified context says renewal is due. The explicit renewal endpoint performs the same database-backed operation for server-rendered navigation. Both paths retain the same opaque token and rewrite the session and context cookie expiries.
49
+
46
50
  Activity and possession of the session token cannot extend this absolute limit. After it is reached, the user must authenticate again and receive a new session token.
47
51
 
48
52
  ## Social authentication
@@ -1,12 +1,12 @@
1
1
  import type { Request, RequestHandler, Response } from "express";
2
2
  import { type Auth, type AuthDeps } from "../../auth.js";
3
- import type { SessionCacheConfig } from "../../session/cache.js";
4
3
  import type { SessionCookieNames } from "../../session/cookie.js";
4
+ import type { SessionCacheConfig } from "../../session/state.js";
5
5
  import type { AuthAccount, DbAdapter, ResolvedSession, Session } from "../../session/types.js";
6
6
  import type { SocialConfig, SocialDbAdapter } from "../../social/types.js";
7
7
  import type { HttpCookieConfig } from "../utils/types.js";
8
8
  import { type ExpressSocial } from "./social.js";
9
- export type { SessionCacheConfig } from "../../session/cache.js";
9
+ export type { SessionCacheConfig } from "../../session/state.js";
10
10
  export type { ExpressSocial, ExpressSocialLocals } from "./social.js";
11
11
  export type ExpressAuthLocals<TAccount extends AuthAccount = AuthAccount> = {
12
12
  account: TAccount;
@@ -15,35 +15,29 @@ export type ExpressAuthLocals<TAccount extends AuthAccount = AuthAccount> = {
15
15
  };
16
16
  export type ExpressCookieConfig = HttpCookieConfig;
17
17
  export type ExpressGetIp = (request: Request) => Promise<string | null | undefined> | string | null | undefined;
18
- type ExpressCacheOptions = {
19
- cache: SessionCacheConfig;
20
- secret: string;
21
- } | {
22
- cache?: undefined;
23
- secret?: string;
24
- };
25
18
  export type ExpressAdapterConfig<TAccount extends AuthAccount = AuthAccount> = {
26
19
  auth: Auth<TAccount>;
27
20
  cache?: SessionCacheConfig;
28
21
  cookie?: ExpressCookieConfig;
29
22
  getIp?: ExpressGetIp;
30
- secret?: string;
23
+ secret: string;
31
24
  };
32
25
  type ExpressAuthBase<TAccount extends AuthAccount> = Omit<AuthDeps<TAccount>, "db"> & {
26
+ cache?: SessionCacheConfig;
33
27
  cookie?: ExpressCookieConfig;
34
28
  db: DbAdapter<TAccount>;
35
29
  getIp?: ExpressGetIp;
30
+ secret: string;
36
31
  };
37
32
  type ExpressSocialOptions<TAccount extends AuthAccount, TData> = {
38
33
  db: DbAdapter<TAccount> & SocialDbAdapter<TAccount>;
39
- secret: string;
40
34
  social: SocialConfig<TData>;
41
35
  } | {
42
36
  db: DbAdapter<TAccount>;
43
37
  social?: undefined;
44
38
  };
45
- export type ExpressAuthConfig<TAccount extends AuthAccount = AuthAccount, TData = undefined> = Omit<ExpressAuthBase<TAccount>, "db"> & ExpressCacheOptions & ExpressSocialOptions<TAccount, TData>;
46
- type ExpressAuthOptions<TAccount extends AuthAccount> = Omit<ExpressAuthBase<TAccount>, "db"> & ExpressCacheOptions;
39
+ export type ExpressAuthConfig<TAccount extends AuthAccount = AuthAccount, TData = undefined> = Omit<ExpressAuthBase<TAccount>, "db"> & ExpressSocialOptions<TAccount, TData>;
40
+ type ExpressAuthOptions<TAccount extends AuthAccount> = Omit<ExpressAuthBase<TAccount>, "db">;
47
41
  type DbAccount<TDb> = TDb extends DbAdapter<infer TAccount> ? TAccount : never;
48
42
  type ExpressRequestInput = {
49
43
  request: Request;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/express/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/express/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAc,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC/F,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAI3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEtE,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEtE,MAAM,MAAM,iBAAiB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACxE,OAAO,EAAE,QAAQ,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,CAAC;AAEnD,MAAM,MAAM,YAAY,GAAG,CACvB,OAAO,EAAE,OAAO,KACf,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAEpE,MAAM,MAAM,oBAAoB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IAC3E,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,KAAK,eAAe,CAAC,QAAQ,SAAS,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,GAAG;IAClF,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,EAAE,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IACxB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,KAAK,oBAAoB,CAAC,QAAQ,SAAS,WAAW,EAAE,KAAK,IACvD;IACI,EAAE,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACpD,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;CAC/B,GACD;IACI,EAAE,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IACxB,MAAM,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC;AAER,MAAM,MAAM,iBAAiB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,EAAE,KAAK,GAAG,SAAS,IAAI,IAAI,CAC/F,eAAe,CAAC,QAAQ,CAAC,EACzB,IAAI,CACP,GACG,oBAAoB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AAE1C,KAAK,kBAAkB,CAAC,QAAQ,SAAS,WAAW,IAAI,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;AAE9F,KAAK,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,SAAS,CAAC,MAAM,QAAQ,CAAC,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE/E,KAAK,mBAAmB,GAAG;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;CACtB,CAAC;AAEF,KAAK,kBAAkB,GAAG,mBAAmB,GAAG;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,cAAc,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IACrE,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IACvC,MAAM,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IACrC,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IAC1C,YAAY,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/E,aAAa,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAChE,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,GAChF,cAAc,CAAC,QAAQ,CAAC,CAAC;AAE7B,MAAM,MAAM,iBAAiB,CACzB,QAAQ,SAAS,WAAW,GAAG,WAAW,EAC1C,KAAK,GAAG,SAAS,IACjB,IAAI,CAAC,QAAQ,CAAC,GACd,cAAc,CAAC,QAAQ,CAAC,GAAG;IACvB,MAAM,EAAE,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;CAC1C,CAAC;AAEN,eAAO,MAAM,oBAAoB,GAAI,QAAQ,SAAS,WAAW,EAAE,yCAMhE,oBAAoB,CAAC,QAAQ,CAAC,KAAG,cAAc,CAAC,QAAQ,CAuC1D,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACrB,CAAC,GAAG,SAAS,SAAS,EAAE,KAAK,EACzB,KAAK,EAAE,kBAAkB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG;QACxC,EAAE,EAAE,GAAG,GAAG,eAAe,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1C,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;KAC/B,GACF,iBAAiB,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC,GAAG,SAAS,SAAS,EAClB,KAAK,EAAE,kBAAkB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG;QACxC,EAAE,EAAE,GAAG,CAAC;QACR,MAAM,CAAC,EAAE,SAAS,CAAC;KACtB,GACF,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;CAClC,CAAC;AA6CF,eAAO,MAAM,iBAAiB,EAA4B,iBAAiB,CAAC"}
@@ -5,17 +5,17 @@ import { createHttpSession } from "../utils/session.js";
5
5
  import { createExpressSocial } from "./social.js";
6
6
  export const createExpressAdapter = ({ auth, cache, cookie, getIp, secret, }) => {
7
7
  const session = createHttpSession({
8
+ auth,
9
+ secret,
10
+ framework: "Express",
8
11
  appendSetCookie: ({ response, value }) => {
9
12
  response.append("Set-Cookie", value);
10
13
  },
11
- auth,
14
+ getHeader: ({ name, request }) => request.get(name),
15
+ getMethod: (request) => request.method,
12
16
  ...(cache === undefined ? {} : { cache }),
13
17
  ...(cookie === undefined ? {} : { cookie }),
14
- framework: "Express",
15
- getHeader: ({ name, request }) => request.get(name),
16
18
  ...(getIp === undefined ? {} : { getIp }),
17
- getMethod: (request) => request.method,
18
- ...(secret === undefined ? {} : { secret }),
19
19
  });
20
20
  const resolveSession = (input) => {
21
21
  return session.resolveSession(input);
@@ -47,10 +47,10 @@ const createExpressAuthImpl = ({ cache, cookie, db, getIp, password, secret, ses
47
47
  });
48
48
  const adapter = createExpressAdapter({
49
49
  auth,
50
+ secret,
50
51
  ...(cache === undefined ? {} : { cache }),
51
52
  ...(cookie === undefined ? {} : { cookie }),
52
53
  ...(getIp === undefined ? {} : { getIp }),
53
- ...(secret === undefined ? {} : { secret }),
54
54
  });
55
55
  if (social === undefined) {
56
56
  return { ...auth, ...adapter };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/express/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/express/index.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
2
2
  import { type Auth, type AuthDeps } from "../../auth.js";
3
- import type { SessionCacheConfig } from "../../session/cache.js";
4
3
  import type { SessionCookieNames } from "../../session/cookie.js";
4
+ import type { SessionCacheConfig } from "../../session/state.js";
5
5
  import type { AuthAccount, DbAdapter, ResolvedSession, Session } from "../../session/types.js";
6
6
  import type { SocialConfig, SocialDbAdapter } from "../../social/types.js";
7
7
  import type { HttpCookieConfig } from "../utils/types.js";
8
8
  import { type FastifySocial } from "./social.js";
9
- export type { SessionCacheConfig } from "../../session/cache.js";
9
+ export type { SessionCacheConfig } from "../../session/state.js";
10
10
  export type { FastifySocial, FastifySocialHandler } from "./social.js";
11
11
  export type FastifyAuthContext<TAccount extends AuthAccount = AuthAccount> = {
12
12
  account: TAccount;
@@ -15,35 +15,29 @@ export type FastifyAuthContext<TAccount extends AuthAccount = AuthAccount> = {
15
15
  };
16
16
  export type FastifyCookieConfig = HttpCookieConfig;
17
17
  export type FastifyGetIp = (request: FastifyRequest) => Promise<string | null | undefined> | string | null | undefined;
18
- type FastifyCacheOptions = {
19
- cache: SessionCacheConfig;
20
- secret: string;
21
- } | {
22
- cache?: undefined;
23
- secret?: string;
24
- };
25
18
  export type FastifyAdapterConfig<TAccount extends AuthAccount = AuthAccount> = {
26
19
  auth: Auth<TAccount>;
27
20
  cache?: SessionCacheConfig;
28
21
  cookie?: FastifyCookieConfig;
29
22
  getIp?: FastifyGetIp;
30
- secret?: string;
23
+ secret: string;
31
24
  };
32
25
  type FastifyAuthBase<TAccount extends AuthAccount> = Omit<AuthDeps<TAccount>, "db"> & {
26
+ cache?: SessionCacheConfig;
33
27
  cookie?: FastifyCookieConfig;
34
28
  db: DbAdapter<TAccount>;
35
29
  getIp?: FastifyGetIp;
30
+ secret: string;
36
31
  };
37
32
  type FastifySocialOptions<TAccount extends AuthAccount, TData> = {
38
33
  db: DbAdapter<TAccount> & SocialDbAdapter<TAccount>;
39
- secret: string;
40
34
  social: SocialConfig<TData>;
41
35
  } | {
42
36
  db: DbAdapter<TAccount>;
43
37
  social?: undefined;
44
38
  };
45
- export type FastifyAuthConfig<TAccount extends AuthAccount = AuthAccount, TData = undefined> = Omit<FastifyAuthBase<TAccount>, "db"> & FastifyCacheOptions & FastifySocialOptions<TAccount, TData>;
46
- type FastifyAuthOptions<TAccount extends AuthAccount> = Omit<FastifyAuthBase<TAccount>, "db"> & FastifyCacheOptions;
39
+ export type FastifyAuthConfig<TAccount extends AuthAccount = AuthAccount, TData = undefined> = Omit<FastifyAuthBase<TAccount>, "db"> & FastifySocialOptions<TAccount, TData>;
40
+ type FastifyAuthOptions<TAccount extends AuthAccount> = Omit<FastifyAuthBase<TAccount>, "db">;
47
41
  type DbAccount<TDb> = TDb extends DbAdapter<infer TAccount> ? TAccount : never;
48
42
  type FastifyRequestInput = {
49
43
  reply: FastifyReply;