@nxgt/janus 0.25.0 → 0.26.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/README.md +16 -3
- package/dist/auth/config/reserved.d.ts +1 -1
- package/dist/auth/config/reserved.d.ts.map +1 -1
- package/dist/auth/email-flows/any-type-change-email.d.ts +18 -0
- package/dist/auth/email-flows/any-type-change-email.d.ts.map +1 -0
- package/dist/auth/email-flows/change-email-token.d.ts +6 -1
- package/dist/auth/email-flows/change-email-token.d.ts.map +1 -1
- package/dist/auth/email-flows/change-email.d.ts +6 -0
- package/dist/auth/email-flows/change-email.d.ts.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/janus.d.ts.map +1 -1
- package/dist/auth/types/change-email.d.ts +31 -0
- package/dist/auth/types/change-email.d.ts.map +1 -1
- package/dist/auth/types/index.d.ts +1 -1
- package/dist/auth/types/index.d.ts.map +1 -1
- package/dist/auth/types/janus.d.ts +9 -2
- package/dist/auth/types/janus.d.ts.map +1 -1
- package/dist/index.js +525 -510
- package/dist/index.js.map +18 -17
- package/docs/guide/email-flows.md +14 -0
- package/docs/guide/users.md +1 -1
- package/docs/roadmap.md +6 -12
- package/docs/troubleshooting.md +6 -4
- package/package.json +1 -1
|
@@ -265,6 +265,20 @@ is no longer the one it was asked from although nothing spent it: a write
|
|
|
265
265
|
outside janus, or a `send` racing an `update`. `confirm` sends `user.emailChanged` (with
|
|
266
266
|
`formerEmail`) and `user.emailVerified`.
|
|
267
267
|
|
|
268
|
+
**With several user types**, a type's own `confirm` answers `TOKEN_UNKNOWN`
|
|
269
|
+
for a token issued to another type's user, and spends it — a later
|
|
270
|
+
confirmation through the right type is then `TOKEN_SPENT`. A page that does
|
|
271
|
+
not know the type calls the root's `confirm`, which reads the user the token
|
|
272
|
+
was issued to and confirms as their type does: same move, same events, same
|
|
273
|
+
errors, and `type` in the answer says which type it was. `send` stays on each
|
|
274
|
+
type. The root's exists when one type has an e-mail, which is why no type may
|
|
275
|
+
be named `changeEmail`.
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
// one anonymous page for every type
|
|
279
|
+
const changed = await auth.changeEmail.confirm(token); // changed.type: 'admin' | 'member'
|
|
280
|
+
```
|
|
281
|
+
|
|
268
282
|
**Gate `send`, and tell the former address.** Whoever changes the e-mail
|
|
269
283
|
takes over every reset: call `send` behind a fresh sign-in or a step-up.
|
|
270
284
|
|
package/docs/guide/users.md
CHANGED
|
@@ -168,7 +168,7 @@ and `schemaVersion`, with the defaults above. A login is unique **per type**:
|
|
|
168
168
|
the same e-mail may hold a patient user and a staff user. A type name is
|
|
169
169
|
camelCase, and may not be one of `janus()`'s own methods (`authenticate`,
|
|
170
170
|
`signOut`, `signOutEverywhere`, `findUser`, `getUser`, `cookie`,
|
|
171
|
-
`collectExpired`, `types`) — a compile error, and a `TypeError` for a
|
|
171
|
+
`collectExpired`, `types`, `changeEmail`) — a compile error, and a `TypeError` for a
|
|
172
172
|
JavaScript caller.
|
|
173
173
|
|
|
174
174
|
## What each user type answers
|
package/docs/roadmap.md
CHANGED
|
@@ -69,6 +69,12 @@ Nothing yet.
|
|
|
69
69
|
The last ten, newest first, each with the version it came in. Everything
|
|
70
70
|
before is in the [CHANGELOG](../CHANGELOG.md).
|
|
71
71
|
|
|
72
|
+
- **Root `changeEmail.confirm` for instances with several user types, v0.26.0** —
|
|
73
|
+
`auth.changeEmail.confirm(token)` confirms a change of e-mail for a page that
|
|
74
|
+
does not know the user's type: it reads the user the link was issued to and
|
|
75
|
+
confirms as their type does. A type's own `confirm` still answers
|
|
76
|
+
`TOKEN_UNKNOWN`, and spends the token, for another type's link; no user type
|
|
77
|
+
may be named `changeEmail`.
|
|
72
78
|
- **Collecting lapsed one-time tokens, v0.25.0** — `collectExpired()` deletes
|
|
73
79
|
lapsed sessions and, through a new optional `TokenStore.deleteExpiredTokens`,
|
|
74
80
|
lapsed one-time tokens too: the sign-in and mail throttles' counts
|
|
@@ -153,15 +159,3 @@ before is in the [CHANGELOG](../CHANGELOG.md).
|
|
|
153
159
|
optional `findUsers`, implemented by the reference store,
|
|
154
160
|
`@nxgt/janus-drizzle` 0.7.0 and `@nxgt/janus-mongo` 0.8.0; a store without it
|
|
155
161
|
is read with `findUser`, ten at a time, so third-party adapters keep working.
|
|
156
|
-
- **Requests that send e-mail are throttled, v0.18.0** —
|
|
157
|
-
`janus({ mail: { throttle: { attempts, window } } })`, five per ten
|
|
158
|
-
minutes by default and `false` to turn it off. `magicLink.request`,
|
|
159
|
-
`signInCode.request` and `resetPassword.request` count per address;
|
|
160
|
-
`verifyEmail.send` and an e-mailed `stepUp.request` count per user; each
|
|
161
|
-
flow on its own. Past the limit a request throws `MailThrottledError`
|
|
162
|
-
(`MAIL_THROTTLED`, 429) with `retryAfter` and issues, spends and rotates
|
|
163
|
-
nothing: the last link or code sent still works, so a loop on an address
|
|
164
|
-
cannot lock its owner out.
|
|
165
|
-
The window is no longer than the shortest default token lifetime. The counts
|
|
166
|
-
live in the tokens store, with no port change. `MailConfig` and
|
|
167
|
-
`MailThrottleConfig` are exported.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -366,8 +366,8 @@ janus({ user: z.object({ username: z.string() }), password: { login: 'username'
|
|
|
366
366
|
Also `janus: "<name>" cannot name a user type — janus() answers a method of that name` and `janus: users declares no user type`.
|
|
367
367
|
|
|
368
368
|
**When:** `janus({ users: {...} })`.
|
|
369
|
-
**Why:** each type becomes a property of what `janus()` answers — `auth.staff` — so it must be a name, and not one of the shared methods (`authenticate`, `signOut`, `signOutEverywhere`, `findUser`, `getUser`, `cookie`, `collectExpired`, `types`).
|
|
370
|
-
**Fix:** `users: { staffMember: {...} }`, not `'staff-member'` or `
|
|
369
|
+
**Why:** each type becomes a property of what `janus()` answers — `auth.staff` — so it must be a name, and not one of the shared methods (`authenticate`, `signOut`, `signOutEverywhere`, `findUser`, `getUser`, `cookie`, `collectExpired`, `types`, `changeEmail`).
|
|
370
|
+
**Fix:** `users: { staffMember: {...} }`, not `'staff-member'`, `cookie` or `changeEmail`.
|
|
371
371
|
|
|
372
372
|
### `janus: session.lifespan: "<value>" is not a duration; write a number followed by ms, s, m, h or d — for example "15m" or "720h"`
|
|
373
373
|
|
|
@@ -949,7 +949,7 @@ janus({ ..., hasher: scryptHasher(), verifiers: [bcryptVerifier] }); // a Passwo
|
|
|
949
949
|
`TokenError`: `<call>: no such token`, `<call>: the token was already used`, `<call>: the token has expired`.
|
|
950
950
|
|
|
951
951
|
**When:** `verifyEmail.confirm`, `resetPassword.confirm`, `changeEmail.confirm`.
|
|
952
|
-
**Why:** a token is spent by its first use, and an expired one is spent too. `TOKEN_UNKNOWN` also covers a token whose user was deleted, and a change link confirmed through another user type's `changeEmail` or passed to another flow. The defaults are 24 h for `verifyEmail`, 1 h for `resetPassword` and for `changeEmail`. A change link is also spent by a newer `changeEmail.send` for the same user (only the last one works), and by an `update` that changes the user's e-mail.
|
|
952
|
+
**Why:** a token is spent by its first use, and an expired one is spent too. `TOKEN_UNKNOWN` also covers a token whose user was deleted, and a change link confirmed through another user type's `changeEmail` (which spends it, so the right type then answers `TOKEN_SPENT`) or passed to another flow. The defaults are 24 h for `verifyEmail`, 1 h for `resetPassword` and for `changeEmail`. A change link is also spent by a newer `changeEmail.send` for the same user (only the last one works), and by an `update` that changes the user's e-mail.
|
|
953
953
|
A reset link answers `resetPassword.confirm: the token was already used` in
|
|
954
954
|
two more cases: a newer `resetPassword.request` for the same user spent it —
|
|
955
955
|
only the last link sent works, so a visitor who asked twice and clicked the
|
|
@@ -958,7 +958,9 @@ sent, by another link's `confirm`, `changePassword` or `setPassword`. When two
|
|
|
958
958
|
requests race, even the last link can be spent: at most one survives,
|
|
959
959
|
sometimes none.
|
|
960
960
|
**Fix:** answer 400 and offer to send a new link — and tell the visitor to use
|
|
961
|
-
the latest e-mail.
|
|
961
|
+
the latest e-mail. With several user types, confirm a change link from a page
|
|
962
|
+
that does not know the type with the root's `auth.changeEmail.confirm(token)`,
|
|
963
|
+
never through a guessed type. To change the lifetimes:
|
|
962
964
|
|
|
963
965
|
```ts
|
|
964
966
|
janus({ ..., tokens: { verifyEmail: '72h', resetPassword: '2h' } });
|