@nxgt/janus 0.23.0 → 0.23.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 +6 -5
- package/docs/guide/email-flows.md +14 -8
- package/docs/guide/vocabulary.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -761,11 +761,12 @@ password and the second factor go with it, so whoever holds the new inbox
|
|
|
761
761
|
and follows the link signs in with them. The mail to the new address should
|
|
762
762
|
say so, and say "ignore it if it was not you".
|
|
763
763
|
|
|
764
|
-
**
|
|
765
|
-
|
|
766
|
-
former address, `emailChanged
|
|
767
|
-
|
|
768
|
-
account moves
|
|
764
|
+
**Send the link to the new address with `@nxgt/janus-mail` 0.10.0 or later**:
|
|
765
|
+
`mail.changeEmail(issued, { name })` (its `links.changeEmail` is the page
|
|
766
|
+
above), and it sends the notice to the former address, `emailChanged`, once
|
|
767
|
+
the link is redeemed. `mail.verifyEmail(issued)` is not the change-of-e-mail
|
|
768
|
+
mail: it would tell the new address to verify, not that the account moves
|
|
769
|
+
there. Without janus-mail, send it with your own mailer.
|
|
769
770
|
|
|
770
771
|
- **On every user type with an e-mail**, with a password or without one. The
|
|
771
772
|
address is validated by the type's schema as `update` would: a malformed
|
|
@@ -37,15 +37,17 @@ writes it: it takes what `send` and `request` answer, as they answer it, and
|
|
|
37
37
|
sends the verification, reset, sign-in code and sign-in link e-mails — with the notices
|
|
38
38
|
of a password, an e-mail or a second factor changed, and a welcome on
|
|
39
39
|
`user.created` — in English and French, over any `@nxgt/mail` transport.
|
|
40
|
-
Every link is required but
|
|
41
|
-
where the welcome's **Get started** button leads; `recoveryCodes
|
|
40
|
+
Every link is required but three: `getStarted`, since janus-mail 0.4.0, is
|
|
41
|
+
where the welcome's **Get started** button leads; `recoveryCodes`,
|
|
42
42
|
`magicLink` — the page a [sign-in link](magic-link.md) opens, since
|
|
43
|
-
janus-mail 0.7.0 —
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
janus-mail 0.7.0 — and `changeEmail`, the page that confirms a new address,
|
|
44
|
+
since janus-mail 0.10.0, are optional. **`changeEmail.send`'s link has its
|
|
45
|
+
own e-mail**: `mail.changeEmail(issued, { name })` sends it to
|
|
46
|
+
`issued.email`, the new address, and janus-mail sends the notice to the
|
|
47
|
+
former address (`emailChanged`) once the link is redeemed. It needs
|
|
48
|
+
`@nxgt/janus-mail` 0.10.0 or later; `mail.verifyEmail(issued)` is not the
|
|
49
|
+
change-of-e-mail mail: it would ask the new address to verify, not say the
|
|
50
|
+
account moves there.
|
|
49
51
|
|
|
50
52
|
```ts
|
|
51
53
|
import { janusMail } from '@nxgt/janus-mail';
|
|
@@ -59,11 +61,15 @@ const mail = janusMail({
|
|
|
59
61
|
resetPassword: (token) => `https://app.example/reset?token=${token}`,
|
|
60
62
|
secureAccount: () => 'https://app.example/account/security',
|
|
61
63
|
getStarted: () => 'https://app.example/',
|
|
64
|
+
changeEmail: (token) => `https://app.example/email/confirm?token=${token}`, // optional
|
|
62
65
|
},
|
|
63
66
|
});
|
|
64
67
|
|
|
65
68
|
await mail.verifyEmail(await auth.verifyEmail.send(user), { name: user.name });
|
|
66
69
|
|
|
70
|
+
// to the NEW address; the account moves when changeEmail.confirm(token) redeems the link
|
|
71
|
+
await mail.changeEmail(await auth.changeEmail.send(user, newEmail), { name: user.name });
|
|
72
|
+
|
|
67
73
|
const issued = await auth.resetPassword.request(email);
|
|
68
74
|
if (issued !== null) await mail.resetPassword(issued, { name: issued.user.name });
|
|
69
75
|
```
|
package/docs/guide/vocabulary.md
CHANGED
|
@@ -59,7 +59,7 @@ either finds this row.
|
|
|
59
59
|
| **device**, **device token** | A device is a browser or an app a user signs in from, as the client's long-lived cookie — or a bearer client's storage — tells it. A **device token** is what janus signs for it with `devices.keys`, answers as `deviceToken`, and takes back as `device`: `d1.<key id>.<device id>.<mac>`, bound to one user, stored nowhere. A sign-in from a **new device** — one whose token did not prove this user signed in there — answers `newDevice: true` and sends `user.newDeviceSignedIn`. See [devices](devices.md) | "fingerprint", "trusted device", "remembered browser"; "token" alone |
|
|
60
60
|
| **token** | Never alone in prose: a *session token*, a *one-time token* or a *device token*. The `tokens` store and the `TOKEN_*` codes are one-time tokens only | |
|
|
61
61
|
| **e-mail flow** | `verifyEmail`, `resetPassword` or `changeEmail`: send a one-time token, then confirm it. `magicLink` sends one too, to sign in; `signInCode` sends a one-time code instead | |
|
|
62
|
-
| **issued** | What a flow answers for the application to send: an `IssuedToken` from `verifyEmail.send`, `changeEmail.send`, `resetPassword.request` or `magicLink.request`, an `IssuedCode` from `signInCode.request` — the address with it. `@nxgt/janus-mail` takes it as it is,
|
|
62
|
+
| **issued** | What a flow answers for the application to send: an `IssuedToken` from `verifyEmail.send`, `changeEmail.send`, `resetPassword.request` or `magicLink.request`, an `IssuedCode` from `signInCode.request` — the address with it. `@nxgt/janus-mail` takes it as it is — `mail.changeEmail(issued, to)` for `changeEmail.send`'s, sent to the new address (janus-mail 0.10.0 or later) | "result", "payload" |
|
|
63
63
|
| **notice** | An e-mail that tells a user of a change and asks for nothing: *password changed*, *e-mail changed* — the latter sent to the former address — *two-factor enabled*, *two-factor disabled*, *recovery code used* and *new sign-in*. `@nxgt/janus-mail` sends all six | "alert", "notification" |
|
|
64
64
|
| **user event** | What happened to a user, once it is written: `user.created`, `user.emailVerified`, `user.passwordReset`, `user.passwordChanged`, `user.emailChanged`, `user.secondFactorEnabled`, `user.secondFactorDisabled`, `user.recoveryCodesRegenerated`, `user.recoveryCodeUsed`, `user.newDeviceSignedIn`, `user.deleted` — a `UserEvent`, naming the user by id alone — `user.emailChanged` adds `formerEmail`, `user.newDeviceSignedIn` adds `sessionId` — with an `id` of its own. See [user events](events.md) | "webhook" — a webhook is one way to deliver it; "event" alone where it could be read as `@nxgt/janus-telemetry`'s audit log record — on a page about user events, "the event" is fine |
|
|
65
65
|
| **step-up**, **fresh** | A step-up is a signed-in user proving again who they are before a sensitive action — `stepUp.request`, then `stepUp.confirm`, with an e-mailed code or, when their second factor is active, their app's — which moves the session's `authenticatedAt` to now and opens no session. A session is **fresh** for `maxAge` after it proved who it is, at the sign-in or by a step-up; `assertFresh` refuses an older one with `STEP_UP_REQUIRED`. See [step-up](step-up.md) | "re-authentication", "sudo mode", "elevated session"; "recent sign-in" once a step-up counts too |
|