@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.
- package/README.md +91 -80
- package/SECURITY.md +8 -4
- package/dist/adapters/express/index.d.ts +7 -13
- package/dist/adapters/express/index.d.ts.map +1 -1
- package/dist/adapters/express/index.js +6 -6
- package/dist/adapters/express/index.js.map +1 -1
- package/dist/adapters/fastify/index.d.ts +7 -13
- package/dist/adapters/fastify/index.d.ts.map +1 -1
- package/dist/adapters/fastify/index.js +5 -5
- package/dist/adapters/fastify/index.js.map +1 -1
- package/dist/adapters/hono/index.d.ts +7 -13
- package/dist/adapters/hono/index.d.ts.map +1 -1
- package/dist/adapters/hono/index.js +5 -5
- package/dist/adapters/hono/index.js.map +1 -1
- package/dist/adapters/next/index.d.ts +2 -7
- package/dist/adapters/next/index.d.ts.map +1 -1
- package/dist/adapters/next/index.js +9 -39
- package/dist/adapters/next/index.js.map +1 -1
- package/dist/adapters/utils/session.d.ts.map +1 -1
- package/dist/adapters/utils/session.js +70 -78
- package/dist/adapters/utils/session.js.map +1 -1
- package/dist/adapters/utils/types.d.ts +3 -9
- package/dist/adapters/utils/types.d.ts.map +1 -1
- package/dist/config.d.ts +1 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -2
- package/dist/config.js.map +1 -1
- package/dist/headers/index.d.ts +7 -0
- package/dist/headers/index.d.ts.map +1 -0
- package/dist/headers/index.js +37 -0
- package/dist/headers/index.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/session/cookie.d.ts +6 -8
- package/dist/session/cookie.d.ts.map +1 -1
- package/dist/session/cookie.js +7 -24
- package/dist/session/cookie.js.map +1 -1
- package/dist/session/state.d.ts +41 -0
- package/dist/session/state.d.ts.map +1 -0
- package/dist/session/state.js +192 -0
- package/dist/session/state.js.map +1 -0
- package/package.json +5 -1
- package/dist/session/cache.d.ts +0 -32
- package/dist/session/cache.d.ts.map +0 -1
- package/dist/session/cache.js +0 -138
- 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
|
-
|
|
|
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,
|
|
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,
|
|
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`;
|
|
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` |
|
|
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
|
-
| `
|
|
411
|
-
| `
|
|
412
|
-
| `
|
|
413
|
-
| `
|
|
414
|
-
| `
|
|
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
|
-
|
|
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.
|
|
438
|
-
auth.cookie.renewName; // "__ren"
|
|
446
|
+
auth.cookie.contextName; // "__ctx"
|
|
439
447
|
```
|
|
440
448
|
|
|
441
|
-
### Signed
|
|
449
|
+
### Signed session context
|
|
442
450
|
|
|
443
|
-
| Property | Type / allowed values | Default | Description
|
|
444
|
-
| ----------- | ----------------------------------- | -------- |
|
|
445
|
-
| `
|
|
446
|
-
| `
|
|
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
|
|
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
|
|
451
|
-
- is
|
|
452
|
-
-
|
|
453
|
-
-
|
|
454
|
-
-
|
|
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
|
|
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
|
|
469
|
+
<summary>Internal signed context payload</summary>
|
|
460
470
|
|
|
461
471
|
```ts
|
|
462
472
|
{
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
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 `
|
|
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.
|
|
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
|
|
699
|
-
-> optionally
|
|
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
|
-
|
|
708
|
-
->
|
|
709
|
-
-> yes:
|
|
710
|
-
-> no:
|
|
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
|
-
->
|
|
731
|
+
-> write signed context without cached account data
|
|
721
732
|
-> continue
|
|
722
733
|
```
|
|
723
734
|
|
|
724
|
-
###
|
|
735
|
+
### Next.js SSR renewal
|
|
725
736
|
|
|
726
737
|
```text
|
|
727
|
-
Next
|
|
728
|
-
-> future
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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/
|
|
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/
|
|
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
|
|
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
|
|
32
|
+
## Signed session context
|
|
33
33
|
|
|
34
|
-
|
|
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
|
|
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
|
|
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/
|
|
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
|
|
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"> &
|
|
46
|
-
type ExpressAuthOptions<TAccount extends AuthAccount> = Omit<ExpressAuthBase<TAccount>, "db"
|
|
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":"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,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/express/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -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
|
-
|
|
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":"AACA,OAAO,EAAE,UAAU,EAA4B,MAAM,eAAe,CAAC;AAKrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAE,mBAAmB,EAAsB,MAAM,aAAa,CAAC;
|
|
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/
|
|
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
|
|
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"> &
|
|
46
|
-
type FastifyAuthOptions<TAccount extends AuthAccount> = Omit<FastifyAuthBase<TAccount>, "db"
|
|
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;
|