@warlock.js/auth 5.18.0 → 5.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/esm/contracts/index.d.mts +1 -1
- package/esm/contracts/types.d.mts +23 -2
- package/esm/contracts/types.d.mts.map +1 -1
- package/esm/contracts/types.mjs.map +1 -1
- package/esm/index.d.mts +3 -2
- package/esm/index.mjs +2 -1
- package/esm/middleware/auth.middleware.d.mts +9 -6
- package/esm/middleware/auth.middleware.d.mts.map +1 -1
- package/esm/middleware/auth.middleware.mjs +101 -80
- package/esm/middleware/auth.middleware.mjs.map +1 -1
- package/esm/models/access-token/access-token.model.d.mts +31 -7
- package/esm/models/access-token/access-token.model.d.mts.map +1 -1
- package/esm/models/access-token/access-token.model.mjs +21 -1
- package/esm/models/access-token/access-token.model.mjs.map +1 -1
- package/esm/models/access-token/family-association.migration.mjs +18 -0
- package/esm/models/access-token/family-association.migration.mjs.map +1 -0
- package/esm/models/auth-token-family/auth-token-family.model.d.mts +90 -0
- package/esm/models/auth-token-family/auth-token-family.model.d.mts.map +1 -0
- package/esm/models/auth-token-family/auth-token-family.model.mjs +80 -0
- package/esm/models/auth-token-family/auth-token-family.model.mjs.map +1 -0
- package/esm/models/auth-token-family/index.d.mts +1 -0
- package/esm/models/auth-token-family/index.mjs +3 -0
- package/esm/models/auth-token-family/migration.mjs +25 -0
- package/esm/models/auth-token-family/migration.mjs.map +1 -0
- package/esm/models/index.d.mts +1 -0
- package/esm/models/index.d.mts.map +1 -1
- package/esm/models/index.mjs +8 -0
- package/esm/models/index.mjs.map +1 -1
- package/esm/models/refresh-token/refresh-token.model.d.mts +43 -0
- package/esm/models/refresh-token/refresh-token.model.d.mts.map +1 -1
- package/esm/models/refresh-token/refresh-token.model.mjs +17 -0
- package/esm/models/refresh-token/refresh-token.model.mjs.map +1 -1
- package/esm/models/refresh-token/successor-association.migration.mjs +22 -0
- package/esm/models/refresh-token/successor-association.migration.mjs.map +1 -0
- package/esm/services/auth.service.d.mts +22 -1
- package/esm/services/auth.service.d.mts.map +1 -1
- package/esm/services/auth.service.mjs +216 -32
- package/esm/services/auth.service.mjs.map +1 -1
- package/esm/services/token-family-operation.mjs +74 -0
- package/esm/services/token-family-operation.mjs.map +1 -0
- package/llms-full.txt +63 -58
- package/llms.txt +9 -9
- package/package.json +8 -8
- package/skills/auth-basics/SKILL.md +3 -2
- package/skills/customize-token-storage/SKILL.md +1 -1
- package/skills/customize-user-type/SKILL.md +1 -1
- package/skills/handle-login-and-logout/SKILL.md +1 -1
- package/skills/login-with-providers/SKILL.md +1 -1
- package/skills/manage-tokens/SKILL.md +19 -6
- package/skills/overview/SKILL.md +3 -3
- package/skills/protect-routes/SKILL.md +30 -39
- package/skills/register-user/SKILL.md +1 -1
- package/skills/run-auth-commands/SKILL.md +1 -1
- package/skills/throttle-login-attempts/SKILL.md +1 -1
- package/skills/verify-email-and-reset-password/SKILL.md +1 -1
package/llms.txt
CHANGED
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
|
|
7
7
|
## Skills
|
|
8
8
|
|
|
9
|
-
- [auth-basics](@warlock.js/auth/auth-basics/SKILL.md): Start
|
|
10
|
-
- [customize-token-storage](@warlock.js/auth/customize-token-storage/SKILL.md):
|
|
11
|
-
- [customize-user-type](@warlock.js/auth/customize-user-type/SKILL.md):
|
|
12
|
-
- [handle-login-and-logout](@warlock.js/auth/handle-login-and-logout/SKILL.md):
|
|
13
|
-
- [login-with-providers](@warlock.js/auth/login-with-providers/SKILL.md):
|
|
9
|
+
- [auth-basics](@warlock.js/auth/auth-basics/SKILL.md): Start here for @warlock.js/auth configuration, user models, credentials, and application session flows.
|
|
10
|
+
- [customize-token-storage](@warlock.js/auth/customize-token-storage/SKILL.md): Customize token storage in @warlock.js/auth; use when you need to customize token storage.
|
|
11
|
+
- [customize-user-type](@warlock.js/auth/customize-user-type/SKILL.md): Customize user type (multi-user-type auth) in @warlock.js/auth; use when you need to customize user type.
|
|
12
|
+
- [handle-login-and-logout](@warlock.js/auth/handle-login-and-logout/SKILL.md): Login + logout in @warlock.js/auth; use when you need to handle login and logout.
|
|
13
|
+
- [login-with-providers](@warlock.js/auth/login-with-providers/SKILL.md): Login with an OAuth provider, passkeys, or a phone code in @warlock.js/auth; use when you need to login with providers.
|
|
14
14
|
- [manage-tokens](@warlock.js/auth/manage-tokens/SKILL.md): (no description)
|
|
15
15
|
- [overview](@warlock.js/auth/overview/SKILL.md): (no description)
|
|
16
|
-
- [protect-routes](@warlock.js/auth/protect-routes/SKILL.md): Gate
|
|
17
|
-
- [register-user](@warlock.js/auth/register-user/SKILL.md):
|
|
18
|
-
- [run-auth-commands](@warlock.js/auth/run-auth-commands/SKILL.md):
|
|
16
|
+
- [protect-routes](@warlock.js/auth/protect-routes/SKILL.md): Gate routes with authMiddleware in @warlock.js/auth; use when you need to protect routes.
|
|
17
|
+
- [register-user](@warlock.js/auth/register-user/SKILL.md): Register-and-issue-tokens flow in @warlock.js/auth; use when you need to register user.
|
|
18
|
+
- [run-auth-commands](@warlock.js/auth/run-auth-commands/SKILL.md): Run auth commands in @warlock.js/auth; use when you need to run auth commands.
|
|
19
19
|
- [throttle-login-attempts](@warlock.js/auth/throttle-login-attempts/SKILL.md): (no description)
|
|
20
|
-
- [verify-email-and-reset-password](@warlock.js/auth/verify-email-and-reset-password/SKILL.md):
|
|
20
|
+
- [verify-email-and-reset-password](@warlock.js/auth/verify-email-and-reset-password/SKILL.md): Verify email + reset password in @warlock.js/auth; use when you need to verify email and reset password.
|
package/package.json
CHANGED
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
"ms": "^2.1.3"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"@warlock.js/fs": "5.
|
|
16
|
-
"@warlock.js/cache": "5.
|
|
17
|
-
"@warlock.js/cascade": "5.
|
|
18
|
-
"@warlock.js/core": "5.
|
|
19
|
-
"@warlock.js/logger": "5.
|
|
20
|
-
"@warlock.js/seal": "5.
|
|
21
|
-
"@warlock.js/notifications": "5.
|
|
15
|
+
"@warlock.js/fs": "5.19.0",
|
|
16
|
+
"@warlock.js/cache": "5.19.0",
|
|
17
|
+
"@warlock.js/cascade": "5.19.0",
|
|
18
|
+
"@warlock.js/core": "5.19.0",
|
|
19
|
+
"@warlock.js/logger": "5.19.0",
|
|
20
|
+
"@warlock.js/seal": "5.19.0",
|
|
21
|
+
"@warlock.js/notifications": "5.19.0",
|
|
22
22
|
"@simplewebauthn/server": "^13.1.0",
|
|
23
23
|
"jose": "^6.1.0"
|
|
24
24
|
},
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
],
|
|
48
48
|
"author": "hassanzohdy",
|
|
49
49
|
"license": "MIT",
|
|
50
|
-
"version": "5.
|
|
50
|
+
"version": "5.19.0",
|
|
51
51
|
"type": "module",
|
|
52
52
|
"main": "./esm/index.mjs",
|
|
53
53
|
"module": "./esm/index.mjs",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: auth-basics
|
|
3
|
-
description:
|
|
3
|
+
description: "Start here for @warlock.js/auth configuration, user models, credentials, and application session flows."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Auth basics
|
|
@@ -20,7 +20,7 @@ npm install @warlock.js/auth
|
|
|
20
20
|
1. **Users extend `Auth`.** Your `User`, `Admin`, etc. extend the shared base model that knows how to issue tokens and verify passwords. Multiple user types coexist (see [`@warlock.js/auth/customize-user-type/SKILL.md`](@warlock.js/auth/customize-user-type/SKILL.md)).
|
|
21
21
|
2. **`auth.userType.<name>` config maps a user-type slug to the model class.** The middleware uses this to hydrate the right model from a token.
|
|
22
22
|
3. **Tokens persist.** Both `AccessToken` and `RefreshToken` are Cascade models — issuing a token writes a row; logout / revoke deletes or marks-revoked. Stateless JWT verification + stateful revocation list.
|
|
23
|
-
4. **`authMiddleware
|
|
23
|
+
4. **`authMiddleware` gates or resolves routes.** Use `authMiddleware("user")` for a typed hard gate, `authMiddleware()` for the configured/default user type, or `authMiddleware({ source: "cookie", key: "token", optional: true })` for a public route that receives a valid user when present. The object form can set a page-local login redirect. Legacy `authMiddleware(userType, "cookie:name")` remains valid.
|
|
24
24
|
5. **`authService.login(Model, credentials, deviceInfo?)` is the full happy path.** Verifies credentials, creates token pair (access + refresh), emits events, returns `{ user, tokens }`.
|
|
25
25
|
6. **Refresh-token rotation is on by default.** Each refresh consumes the old token and issues new ones from the same "family" — replay detection revokes the family.
|
|
26
26
|
7. **JWT secret lives in the env.** Generate with `warlock jwt.generate` (see [`@warlock.js/auth/run-auth-commands/SKILL.md`](@warlock.js/auth/run-auth-commands/SKILL.md)).
|
|
@@ -71,6 +71,7 @@ export default {
|
|
|
71
71
|
user: User,
|
|
72
72
|
// admin: Admin, // for multi-user-type
|
|
73
73
|
},
|
|
74
|
+
defaultUserType: "user", // needed for authMiddleware() when multiple types exist
|
|
74
75
|
accessToken: {
|
|
75
76
|
secret: env("JWT_SECRET"),
|
|
76
77
|
expiresIn: "1h",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: customize-token-storage
|
|
3
|
-
description:
|
|
3
|
+
description: "Customize token storage in @warlock.js/auth; use when you need to customize token storage."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Customize token storage
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: customize-user-type
|
|
3
|
-
description:
|
|
3
|
+
description: "Customize user type (multi-user-type auth) in @warlock.js/auth; use when you need to customize user type."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Customize user type (multi-user-type auth)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: handle-login-and-logout
|
|
3
|
-
description:
|
|
3
|
+
description: "Login + logout in @warlock.js/auth; use when you need to handle login and logout."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Login + logout
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: login-with-providers
|
|
3
|
-
description:
|
|
3
|
+
description: "Login with an OAuth provider, passkeys, or a phone code in @warlock.js/auth; use when you need to login with providers."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Login with an OAuth provider, passkeys, or a phone code
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: manage-tokens
|
|
3
|
-
description:
|
|
3
|
+
description: "Manage tokens in @warlock.js/auth; use when you need to manage tokens."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Manage tokens
|
|
@@ -36,7 +36,20 @@ const pair = await authService.createTokenPair(user, deviceInfo);
|
|
|
36
36
|
|
|
37
37
|
`createTokenPair` is the typical issuance path. It respects `config.auth.refreshToken.enabled` — if disabled, returns only `accessToken`.
|
|
38
38
|
|
|
39
|
-
## Refresh with rotation — `refreshTokens`
|
|
39
|
+
## Refresh with rotation — `refreshTokens`
|
|
40
|
+
|
|
41
|
+
Refresh and family revocation use durable family revision checks inside a
|
|
42
|
+
serializable Cascade transaction. Run the additive `authMigrations` before
|
|
43
|
+
using the upgraded APIs. Transaction support is required: the service fails
|
|
44
|
+
rather than falling back to uncoordinated writes. MongoDB deployments therefore
|
|
45
|
+
need a transaction-capable topology.
|
|
46
|
+
|
|
47
|
+
An operation that owns its transaction retries serialization conflicts at most
|
|
48
|
+
three times. Inside an application-owned transaction it joins once and leaves
|
|
49
|
+
retry/rollback to the caller. Auth notifications from owned attempts are emitted
|
|
50
|
+
only after successful commit; notifications inside an application-owned outer
|
|
51
|
+
transaction retain their existing timing before that outer commit. Keep external
|
|
52
|
+
side effects outside such a transaction.
|
|
40
53
|
|
|
41
54
|
```ts
|
|
42
55
|
const next = await authService.refreshTokens(oldRefreshToken, deviceInfo);
|
|
@@ -69,7 +82,7 @@ refresh (B) → revokes B; creates C in family X
|
|
|
69
82
|
refresh (A again)→ A is revoked → revoke family X entirely
|
|
70
83
|
```
|
|
71
84
|
|
|
72
|
-
The family ties together "successive rotations of one session."
|
|
85
|
+
The family ties together "successive rotations of one session." In 5.19 it is also a durable `AuthTokenFamily` row: family revoke marks that family, revokes its refresh rows, and deletes its associated access rows atomically. Access rows from before family association are conservatively deleted only for the same user and user type; they are never guessed into a family.
|
|
73
86
|
|
|
74
87
|
## Listing active sessions
|
|
75
88
|
|
|
@@ -91,9 +104,8 @@ Use this for "active sessions" UIs. Revoke a specific session by calling `.revok
|
|
|
91
104
|
// Specific access token
|
|
92
105
|
await authService.removeAccessToken(user, accessTokenString);
|
|
93
106
|
|
|
94
|
-
// Specific
|
|
95
|
-
|
|
96
|
-
await rt?.revoke();
|
|
107
|
+
// Specific session/family
|
|
108
|
+
await authService.revokeTokenFamily(familyId);
|
|
97
109
|
|
|
98
110
|
// All access tokens for a user
|
|
99
111
|
await authService.removeAllAccessTokens(user);
|
|
@@ -175,6 +187,7 @@ The package signs access and refresh tokens with independent secrets — `config
|
|
|
175
187
|
- Don't disable rotation (`config.auth.refreshToken.rotation = false`) unless you genuinely understand the tradeoff — you lose replay detection.
|
|
176
188
|
- Don't increase `maxPerUser` to a huge number "to be safe." Each active refresh token is a revocation surface; fewer simultaneous tokens means less attack surface.
|
|
177
189
|
- Don't manually delete `AccessToken` rows in a service. The user might be hitting a request mid-revoke and get an inconsistent state. Use the `authService` helpers.
|
|
190
|
+
- Run the additive `authMigrations` on upgrade. Do not alter or backfill token rows yourself; legacy access tokens are handled conservatively on family revoke.
|
|
178
191
|
|
|
179
192
|
## See also
|
|
180
193
|
|
package/skills/overview/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: overview
|
|
3
|
-
description:
|
|
3
|
+
description: "@warlock.js/auth overview for orientation and choosing the focused skill for the task."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# `@warlock.js/auth` — overview
|
|
@@ -21,7 +21,7 @@ Skip if you're not on `@warlock.js/core` (the package depends on it), or if you
|
|
|
21
21
|
|
|
22
22
|
## The mental model in one paragraph
|
|
23
23
|
|
|
24
|
-
Your user model extends the `Auth` base model and declares its `userType`. A login flows through `authService.login(Model, credentials, deviceInfo?)`: it verifies the password, issues
|
|
24
|
+
Your user model extends the `Auth` base model and declares its `userType`. A login flows through `authService.login(Model, credentials, deviceInfo?)`: it verifies the password, issues a persisted access + refresh pair, and fires events. `authMiddleware("user")` is a typed hard gate; `authMiddleware()` resolves the configured default type; the object form selects header/cookie credentials, `optional`, and a page-local redirect. Refresh rotation uses a durable token family: family revocation invalidates its refresh and associated access rows. CLI commands generate the JWT secret and clean up expired tokens.
|
|
25
25
|
|
|
26
26
|
## Skills index
|
|
27
27
|
|
|
@@ -41,7 +41,7 @@ Start here. The `Auth` base model, `authMiddleware` gate, `authService` (login/l
|
|
|
41
41
|
Sign up a new user and issue the first token pair — `User.create({ ...password: await hashPassword(plain) })` then `authService.createTokenPair(user)`. For `POST /register`.
|
|
42
42
|
|
|
43
43
|
#### [`protect-routes`](@warlock.js/auth/protect-routes/SKILL.md)
|
|
44
|
-
`authMiddleware
|
|
44
|
+
`authMiddleware` object and legacy overloads: typed/default hard gates, optional resolution, credential source, and page-local redirects. Sets `request.locals.user` + `request.decodedAccessToken` when a user resolves.
|
|
45
45
|
|
|
46
46
|
### Going deeper
|
|
47
47
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: protect-routes
|
|
3
|
-
description:
|
|
3
|
+
description: "Gate routes with authMiddleware in @warlock.js/auth; use when you need to protect routes."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Gate routes with `authMiddleware`
|
|
7
7
|
|
|
8
|
-
`authMiddleware
|
|
8
|
+
`authMiddleware` returns a Warlock middleware. Attach it to routes or route groups. The legacy string overload is preserved; the object overload makes credential source, optional resolution, and a page-local redirect explicit.
|
|
9
9
|
|
|
10
10
|
```ts title="src/app/users/models/user/user.model.ts"
|
|
11
11
|
import { Auth } from "@warlock.js/auth";
|
|
@@ -33,14 +33,13 @@ const accountController: RequestHandler = async ({ response }) => response.succe
|
|
|
33
33
|
const adminController: RequestHandler = async ({ response }) => response.success({});
|
|
34
34
|
const staffController: RequestHandler = async ({ response }) => response.success({});
|
|
35
35
|
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
middleware: [authMiddleware([])], // empty array = "any logged-in user"
|
|
36
|
+
// Required default type (`auth.defaultUserType`, or the sole configured type)
|
|
37
|
+
router.get("/account", accountController, {
|
|
38
|
+
middleware: [authMiddleware()],
|
|
40
39
|
});
|
|
41
40
|
|
|
42
41
|
// Mode 2 — required, specific user type(s)
|
|
43
|
-
// Rejects with 401
|
|
42
|
+
// Rejects missing/invalid credentials with 401 and a disallowed user type with 403.
|
|
44
43
|
router.get("/admin", adminController, {
|
|
45
44
|
middleware: [authMiddleware("admin")],
|
|
46
45
|
});
|
|
@@ -69,13 +68,13 @@ A token passes three separate checks, in order — a token can fail any one of t
|
|
|
69
68
|
2. **The access-token row still exists** — deleting it (logout) invalidates the token immediately, before its JWT expiry.
|
|
70
69
|
3. **The row's own `expires_at` has not passed** (since 4.12.0). The database is the authority on the session: a row whose expiry has elapsed is rejected and deleted, even if the JWT itself is still within its lifetime. A row with a missing or unparseable `expires_at` is treated as expired, not as never-expiring.
|
|
71
70
|
|
|
72
|
-
|
|
71
|
+
Missing or invalid credentials return 401; an authenticated disallowed user type returns 403:
|
|
73
72
|
|
|
74
73
|
| Error code | When |
|
|
75
74
|
| --- | --- |
|
|
76
|
-
| `MissingAccessToken` | No
|
|
75
|
+
| `MissingAccessToken` | No credential at the configured source |
|
|
77
76
|
| `InvalidAccessToken` | Token doesn't verify (signature, missing/passed `exp`, wrong token type), has no DB row, or the row's `expires_at` has passed |
|
|
78
|
-
| `Unauthorized` | Token valid but user-type isn't in the allowed list |
|
|
77
|
+
| `Unauthorized` | Token valid but user-type isn't in the allowed list (403) |
|
|
79
78
|
|
|
80
79
|
## Page routes: redirect to login instead of the JSON 401
|
|
81
80
|
|
|
@@ -103,7 +102,7 @@ Behavior, precisely:
|
|
|
103
102
|
|
|
104
103
|
The page-vs-API signal is `request.route.isPage`. Config is typed as `PageAuthConfig` on `AuthConfigurations` (`loginPath?: string`, `returnUrlParam?: string`, default `"returnUrl"`); read at runtime through `authConfig.pageAuth`.
|
|
105
104
|
|
|
106
|
-
> `
|
|
105
|
+
> A local `redirect` object is preferred for a page that needs a different login destination; absent it, `auth.pageAuth` remains the compatibility fallback.
|
|
107
106
|
|
|
108
107
|
## Reading the user in a controller
|
|
109
108
|
|
|
@@ -142,31 +141,23 @@ router.group({ prefix: "/admin", middleware: [authMiddleware("admin")] }, () =>
|
|
|
142
141
|
|
|
143
142
|
Every route inside the group is gated — the group's `middleware` array applies to each route in the callback. Cleaner than repeating the middleware on each route.
|
|
144
143
|
|
|
145
|
-
## Optional auth
|
|
146
|
-
|
|
147
|
-
`
|
|
148
|
-
|
|
149
|
-
```ts
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
// invalid token on an optional route → treat as anonymous, don't reject
|
|
163
|
-
}
|
|
164
|
-
// returning nothing (undefined) === continue to the handler
|
|
165
|
-
};
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Wire it like any middleware (`{ middleware: [optionalAuth] }`), then branch on `request.locals.user` in the controller. Use `authMiddleware` when the route must be gated; use this when the route is public but personalizes for a signed-in user. `auth.pageAuth` (above) is the built-in **adapter** over this same "unauthenticated" outcome for the common page-redirect case — it is not a competing mechanism.
|
|
169
|
-
|
|
144
|
+
## Optional auth
|
|
145
|
+
|
|
146
|
+
Use `optional: true` in the object form when a public route should receive a verified user when one is present. Missing or invalid credentials continue anonymously; a hard gate remains the default.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
middleware: [authMiddleware({ source: "header", optional: true })]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Automatic cookie renewal
|
|
153
|
+
|
|
154
|
+
Add `refresh: { source: "cookie", key: "refresh_token", overlapMs?: 5000 }`
|
|
155
|
+
to a typed cookie middleware to renew an absent, invalid, or expired access
|
|
156
|
+
cookie before the handler. It writes the successor access and refresh cookies
|
|
157
|
+
through `authService.setAuthCookie`; it never replays a handler. `overlapMs` is
|
|
158
|
+
clamped to 0–10,000 ms (default 5,000). Only the exact immediate successor is
|
|
159
|
+
tolerated during that window. The legacy `refreshTokens` API stays strict; a
|
|
160
|
+
later old-token presentation revokes its family.
|
|
170
161
|
## Custom error responses
|
|
171
162
|
|
|
172
163
|
The middleware uses the framework's `response.unauthorized({...})` shape. To override the response globally, hook the framework's error transformer to remap `AuthErrorCodes.*` codes.
|
|
@@ -208,13 +199,13 @@ router.post("/articles", articlesController, { middleware: [authMiddleware([]),
|
|
|
208
199
|
|
|
209
200
|
Use `authMiddleware` to establish *who the caller is*, and `access` to decide *what they may do*. They compose — `access` reads the user `authMiddleware` put on the request.
|
|
210
201
|
|
|
211
|
-
## Cookie
|
|
202
|
+
## Cookie credentials
|
|
212
203
|
|
|
213
|
-
|
|
204
|
+
Use `{ source: "cookie", key: "token" }` in the object form. The same checks and `request.locals.user` outcome apply; legacy `authMiddleware("user", "cookie:token")` is also supported.
|
|
214
205
|
|
|
215
206
|
```ts
|
|
216
207
|
router.get("/browser-account", accountController, {
|
|
217
|
-
middleware: [authMiddleware(
|
|
208
|
+
middleware: [authMiddleware({ source: "cookie", key: "token" })],
|
|
218
209
|
});
|
|
219
210
|
```
|
|
220
211
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: register-user
|
|
3
|
-
description:
|
|
3
|
+
description: "Register-and-issue-tokens flow in @warlock.js/auth; use when you need to register user."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Register-and-issue-tokens flow
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: run-auth-commands
|
|
3
|
-
description:
|
|
3
|
+
description: "Run auth commands in @warlock.js/auth; use when you need to run auth commands."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Run auth commands
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: throttle-login-attempts
|
|
3
|
-
description:
|
|
3
|
+
description: "Throttle login attempts with loginThrottleMiddleware in @warlock.js/auth; use when you need to throttle login attempts."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Throttle login attempts with `loginThrottleMiddleware`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: verify-email-and-reset-password
|
|
3
|
-
description:
|
|
3
|
+
description: "Verify email + reset password in @warlock.js/auth; use when you need to verify email and reset password."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Verify email + reset password
|