@nxgt/janus 0.22.1 → 0.23.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 +96 -16
- package/dist/auth/config/janus-config.d.ts +2 -0
- package/dist/auth/config/janus-config.d.ts.map +1 -1
- package/dist/auth/config/resolved-config.d.ts +1 -0
- package/dist/auth/config/resolved-config.d.ts.map +1 -1
- package/dist/auth/config/warn-throttle-window.d.ts.map +1 -1
- package/dist/auth/email-flows/change-email-token.d.ts +42 -0
- package/dist/auth/email-flows/change-email-token.d.ts.map +1 -0
- package/dist/auth/email-flows/change-email.d.ts +11 -0
- package/dist/auth/email-flows/change-email.d.ts.map +1 -0
- package/dist/auth/email-flows/flows.d.ts +5 -5
- package/dist/auth/email-flows/flows.d.ts.map +1 -1
- package/dist/auth/events.d.ts +3 -2
- package/dist/auth/events.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/mail-requests.d.ts +6 -3
- package/dist/auth/mail-requests.d.ts.map +1 -1
- package/dist/auth/one-time/issue.d.ts +7 -1
- package/dist/auth/one-time/issue.d.ts.map +1 -1
- package/dist/auth/port/types/tokens.d.ts +10 -4
- package/dist/auth/port/types/tokens.d.ts.map +1 -1
- package/dist/auth/types/change-email.d.ts +51 -0
- package/dist/auth/types/change-email.d.ts.map +1 -0
- package/dist/auth/types/index.d.ts +1 -0
- package/dist/auth/types/index.d.ts.map +1 -1
- package/dist/auth/types/janus.d.ts +2 -1
- package/dist/auth/types/janus.d.ts.map +1 -1
- package/dist/auth/types/user-type.d.ts +3 -1
- package/dist/auth/types/user-type.d.ts.map +1 -1
- package/dist/auth/users/any-type-api.d.ts +2 -2
- package/dist/auth/users/any-type-api.d.ts.map +1 -1
- package/dist/auth/users/update.d.ts +2 -1
- package/dist/auth/users/update.d.ts.map +1 -1
- package/dist/conformance/cases/tokens/change-email.d.ts +8 -0
- package/dist/conformance/cases/tokens/change-email.d.ts.map +1 -0
- package/dist/conformance/cases/tokens/index.d.ts.map +1 -1
- package/dist/conformance/cases/tokens/kinds.d.ts.map +1 -1
- package/dist/conformance/index.js +92 -57
- package/dist/conformance/index.js.map +6 -5
- package/dist/errors/janus-error/codes.d.ts +7 -3
- package/dist/errors/janus-error/codes.d.ts.map +1 -1
- package/dist/index.js +134 -31
- package/dist/index.js.map +13 -11
- package/docs/README.md +1 -1
- package/docs/guide/adapters.md +13 -7
- package/docs/guide/email-flows.md +90 -10
- package/docs/guide/errors.md +3 -3
- package/docs/guide/events.md +5 -4
- package/docs/guide/users.md +10 -8
- package/docs/guide/vocabulary.md +3 -3
- package/docs/roadmap.md +13 -10
- package/docs/troubleshooting.md +32 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -322,6 +322,9 @@ await auth.signOut(request);
|
|
|
322
322
|
await auth.verifyEmail.send(user); // { token, email, expiresAt } — sending it is yours
|
|
323
323
|
await auth.verifyEmail.confirm(token);
|
|
324
324
|
await auth.verifyEmail.proveFirst(user); // privileged: FirstProof — { user, proved }; drops a squatter's password and factor
|
|
325
|
+
// { token, email, expiresAt } — email is the NEW address; gate it behind a fresh sign-in
|
|
326
|
+
await auth.changeEmail.send(user, newEmail);
|
|
327
|
+
await auth.changeEmail.confirm(token); // the user, moved to the new address and verified
|
|
325
328
|
await auth.resetPassword.request(email); // … | null
|
|
326
329
|
await auth.resetPassword.confirm(token, newPassword);
|
|
327
330
|
await auth.signInCode.request(email); // { code, challenge, email, expiresAt, user } | null
|
|
@@ -379,8 +382,10 @@ else reaches the store and is asynchronous.
|
|
|
379
382
|
meant. It is normalised with `'lowercaseTrim'` unless you say otherwise.
|
|
380
383
|
- **`email`** defaults to the field named `email`. A type without one has no
|
|
381
384
|
`findByEmail`, no `verifyEmail`, no `resetPassword`, no `signInCode` and
|
|
382
|
-
no `magicLink` — they are absent from its type, not
|
|
383
|
-
Changing the e-mail
|
|
385
|
+
no `magicLink` and no `changeEmail` — they are absent from its type, not
|
|
386
|
+
failing at run time. Changing the e-mail with `update` sets `emailVerified`
|
|
387
|
+
back to `false`; to move a user to an address they have proved, use
|
|
388
|
+
[`changeEmail`](#changing-an-e-mail--changeemail).
|
|
384
389
|
- **Per type**: `create`, `find` (or `null`), `findMany`, `get` (or
|
|
385
390
|
`NOT_FOUND`), `list`, `update(user, patch)` — merged over the stored fields,
|
|
386
391
|
then validated whole — `setActive`, `delete` and `signInProven` (below);
|
|
@@ -426,7 +431,8 @@ else reaches the store and is asynchronous.
|
|
|
426
431
|
**Each flow counts on its own**: per address for
|
|
427
432
|
`magicLink.request`, `signInCode.request` and `resetPassword.request` — an
|
|
428
433
|
address nobody holds is counted and refused alike — and per user for
|
|
429
|
-
`verifyEmail.send` and for
|
|
434
|
+
`verifyEmail.send`, `changeEmail.send` (and, for its new address, per
|
|
435
|
+
address too) and for `stepUp.request` when it e-mails a code.
|
|
430
436
|
`prepare` counts as `request` does, in the same window
|
|
431
437
|
([requests in two steps](#requests-in-two-steps--prepare)).
|
|
432
438
|
`mail: { throttle: { attempts, window } }` changes it, `mail: { throttle:
|
|
@@ -545,7 +551,11 @@ A token of kind `stepUp` is that confirmation's challenge: kept apart from
|
|
|
545
551
|
`magicLink`, new in 0.15, is a sign-in link's, kept apart from `signInCode`
|
|
546
552
|
the same way: a sign-in code's challenge is held by whoever asked for it,
|
|
547
553
|
and must never sign anyone in as a link. A store that lists the kinds — a
|
|
548
|
-
`CHECK`, a validator's enum — adds `magicLink`.
|
|
554
|
+
`CHECK`, a validator's enum — adds `magicLink`. A token of kind
|
|
555
|
+
`changeEmail`, new in 0.23, is the link sent to a user's new address: its
|
|
556
|
+
`address` is that new address and its `codeHash` the address it replaces,
|
|
557
|
+
kept apart from `verifyEmail` so neither is redeemed as the other. The same
|
|
558
|
+
store adds `changeEmail`.
|
|
549
559
|
|
|
550
560
|
An adapter written against `@nxgt/janus` 0.3 does not compile against this
|
|
551
561
|
port until it implements `countAttempt`, nor one written against 0.6 until it
|
|
@@ -731,6 +741,64 @@ to type.
|
|
|
731
741
|
confirms from a `POST` so mail scanners spend nothing, every error, routes
|
|
732
742
|
and a test.
|
|
733
743
|
|
|
744
|
+
### Changing an e-mail — `changeEmail`
|
|
745
|
+
|
|
746
|
+
```ts
|
|
747
|
+
// Gate it: only a user who just proved who they are (assertFresh, or a step-up).
|
|
748
|
+
const issued = await auth.changeEmail.send(user, newEmail); // { token, email, expiresAt }
|
|
749
|
+
const link = `https://app.example/email/confirm?token=${issued.token}`;
|
|
750
|
+
await sendMail(issued.email, link); // the NEW address; say "ignore it if it was not you"
|
|
751
|
+
|
|
752
|
+
// the page's button POSTs the token back — never confirm on the link's GET
|
|
753
|
+
const changed = await auth.changeEmail.confirm(token); // now at the new address, verified
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
A link sent to the **new** address moves the user there: nothing changes
|
|
757
|
+
until it is followed, and following it proves the address.
|
|
758
|
+
|
|
759
|
+
**Confirming moves the requester's whole account to the new address** — the
|
|
760
|
+
password and the second factor go with it, so whoever holds the new inbox
|
|
761
|
+
and follows the link signs in with them. The mail to the new address should
|
|
762
|
+
say so, and say "ignore it if it was not you".
|
|
763
|
+
|
|
764
|
+
**For now, send the link to the new address with your own mailer**:
|
|
765
|
+
`@nxgt/janus-mail` has no template for it yet (it sends the notice to the
|
|
766
|
+
former address, `emailChanged`). `mail.verifyEmail(issued)` is not the
|
|
767
|
+
change-of-e-mail mail: it would tell the new address to verify, not that the
|
|
768
|
+
account moves there.
|
|
769
|
+
|
|
770
|
+
- **On every user type with an e-mail**, with a password or without one. The
|
|
771
|
+
address is validated by the type's schema as `update` would: a malformed
|
|
772
|
+
one is `USER_INVALID` at `send`, and so is the user's current address
|
|
773
|
+
(equal once normalised): a change moves to another one, and verifying the
|
|
774
|
+
current one is `verifyEmail`'s job. That refusal spends nothing.
|
|
775
|
+
- **`send(user, email)`** takes a user you hold, so it is yours to gate:
|
|
776
|
+
behind `assertFresh` or a step-up, since whoever changes the e-mail takes
|
|
777
|
+
over password resets. An inactive user is `USER_INACTIVE`. One link is
|
|
778
|
+
live per user: a new `send` spends the ones before. It lives `'1h'`
|
|
779
|
+
(`tokens.changeEmail`). Throttled per new address and per user, five per
|
|
780
|
+
10 minutes each (`MAIL_THROTTLED`, carrying the user's id), before anything
|
|
781
|
+
is issued. The user is counted first, so an account past its own count
|
|
782
|
+
exhausts no address; an address other people exhausted costs the asking
|
|
783
|
+
user one of their own.
|
|
784
|
+
- **Whether the address is taken is not asked at `send`**: it would tell who
|
|
785
|
+
has an account. `confirm` writes, and the store's own unique constraint
|
|
786
|
+
answers `LOGIN_TAKEN` — the token already spent, nothing written.
|
|
787
|
+
- **`confirm(token)`** spends the token, moves the user to the address and
|
|
788
|
+
marks it verified. The password, the second factor and the sessions are
|
|
789
|
+
untouched. A link whose e-mail is no longer the one `send` was asked from
|
|
790
|
+
is `TOKEN_SPENT` after an `update` that moved it (`update` spends the
|
|
791
|
+
links) or after a newer link; `TOKEN_STALE` comes from a write outside
|
|
792
|
+
janus, or from a `send` racing an `update`, and is checked again on the
|
|
793
|
+
record written. A write racing `confirm` is `VERSION_CONFLICT`, after the
|
|
794
|
+
token is spent.
|
|
795
|
+
- **Events**: `user.emailChanged`, carrying `formerEmail`, then
|
|
796
|
+
`user.emailVerified`. An `update` that moves the e-mail spends the
|
|
797
|
+
user's pending links, so a move back to the old address revives none.
|
|
798
|
+
|
|
799
|
+
[The e-mail flows guide](docs/guide/email-flows.md#changeemail) has a Hono
|
|
800
|
+
route for each step, with the notice to the former address.
|
|
801
|
+
|
|
734
802
|
### Requests in two steps — `prepare`
|
|
735
803
|
|
|
736
804
|
```ts
|
|
@@ -770,8 +838,8 @@ still goes out off their request.
|
|
|
770
838
|
it replaces the decoy an unknown address needed; for nobody it confirms as
|
|
771
839
|
`TOKEN_UNKNOWN`. `send()` answers the code issued under it.
|
|
772
840
|
- Typed per flow: `PreparedRequest<IssuedToken & { user }>` for a link and
|
|
773
|
-
a reset, `PreparedCode<User>` for a code. `verifyEmail.send
|
|
774
|
-
`stepUp.request` have no `prepare`: they take a user the application
|
|
841
|
+
a reset, `PreparedCode<User>` for a code. `verifyEmail.send`,
|
|
842
|
+
`changeEmail.send` and `stepUp.request` have no `prepare`: they take a user the application
|
|
775
843
|
already holds, so their time tells nothing about who has an account.
|
|
776
844
|
|
|
777
845
|
[The e-mail flows guide](docs/guide/email-flows.md#requests-in-two-steps)
|
|
@@ -1000,10 +1068,10 @@ await auth.signUp({ email, password }); // the listener has the event before thi
|
|
|
1000
1068
|
| `type` | Sent by |
|
|
1001
1069
|
| --- | --- |
|
|
1002
1070
|
| `user.created` | `create`, `signUp` |
|
|
1003
|
-
| `user.emailVerified` | `verifyEmail.confirm` and `verifyEmail.proveFirst`; `resetPassword.confirm`, `magicLink.confirm` and `signInCode.confirm`, whose link or code proves the e-mail too — never for an e-mail already verified |
|
|
1071
|
+
| `user.emailVerified` | `verifyEmail.confirm` and `verifyEmail.proveFirst`; `changeEmail.confirm`, `resetPassword.confirm`, `magicLink.confirm` and `signInCode.confirm`, whose link or code proves the e-mail too — never for an e-mail already verified |
|
|
1004
1072
|
| `user.passwordReset` | `resetPassword.confirm` |
|
|
1005
1073
|
| `user.passwordChanged` | `changePassword`, `setPassword`; `signInCode.confirm`, `magicLink.confirm` and `verifyEmail.proveFirst` when their first proof of the e-mail dropped a password — never a reset, which is `user.passwordReset` alone |
|
|
1006
|
-
| `user.emailChanged` | `update`, when
|
|
1074
|
+
| `user.emailChanged` | `update` and `changeEmail.confirm`, when they changed the e-mail — carrying `formerEmail`, the address before (`null` for none) |
|
|
1007
1075
|
| `user.secondFactorEnabled` | `secondFactor.activate`, once the factor is active — not `enroll`, which leaves it waiting |
|
|
1008
1076
|
| `user.secondFactorDisabled` | `secondFactor.disable`, when it removed an active factor; `signInCode.confirm`, `magicLink.confirm` and `verifyEmail.proveFirst` when their first proof of the e-mail removed one, after `user.emailVerified` and any `user.passwordChanged` — never for a user who had none, or one still waiting |
|
|
1009
1077
|
| `user.recoveryCodesRegenerated` | `secondFactor.regenerateRecoveryCodes` — not `activate`, whose codes come with `user.secondFactorEnabled` |
|
|
@@ -1182,7 +1250,7 @@ describeJanusStores({
|
|
|
1182
1250
|
});
|
|
1183
1251
|
```
|
|
1184
1252
|
|
|
1185
|
-
There are
|
|
1253
|
+
There are 59 cases. They cover:
|
|
1186
1254
|
- round-trip, byte for byte — including every edge character the core lets
|
|
1187
1255
|
through (control characters, U+FFFF, a surrogate pair);
|
|
1188
1256
|
- uniqueness, as a constraint: of twenty concurrent inserts of one login,
|
|
@@ -1195,9 +1263,9 @@ There are 58 cases. They cover:
|
|
|
1195
1263
|
and never brings back a revoked session, even one revoked at the same
|
|
1196
1264
|
moment;
|
|
1197
1265
|
- one-time tokens: a token of every kind the port names is stored, counted
|
|
1198
|
-
and spent — a `CHECK` or an enum that forgot `stepUp` or `
|
|
1266
|
+
and spent — a `CHECK` or an enum that forgot `stepUp`, `magicLink` or `changeEmail` fails
|
|
1199
1267
|
here — and neither a step-up nor a sign-in link is ever counted, spent nor
|
|
1200
|
-
answered as a sign-in code; of twenty
|
|
1268
|
+
answered as a sign-in code, nor an e-mail change as a verification; of twenty
|
|
1201
1269
|
concurrent redemptions, exactly one succeeds; of twenty concurrent
|
|
1202
1270
|
`countAttempt` calls, each answers a distinct count, and none is counted
|
|
1203
1271
|
once a racing redemption spent the token;
|
|
@@ -1352,7 +1420,19 @@ e-mail changed by `update` is unverified again, and its first proof by link
|
|
|
1352
1420
|
or code drops both too. **So does a user who enrolled a factor before
|
|
1353
1421
|
proving their own e-mail**: they sign in with no challenge, and enrol again
|
|
1354
1422
|
— offer `secondFactor.enroll` after such a sign-in, or send `verifyEmail`
|
|
1355
|
-
before letting anyone enrol. An e-mail already verified keeps both
|
|
1423
|
+
before letting anyone enrol. An e-mail already verified keeps both — and
|
|
1424
|
+
`changeEmail.confirm` verifies the new address itself, so the first proof
|
|
1425
|
+
afterwards drops nothing.
|
|
1426
|
+
|
|
1427
|
+
**Gate `changeEmail.send`, and tell the former address.** Whoever changes the
|
|
1428
|
+
e-mail takes over every password reset and sign-in link: call `send` behind
|
|
1429
|
+
`assertFresh` or a step-up, never on a session alone, and mail the address the
|
|
1430
|
+
user had from `user.emailChanged` (`formerEmail`) — once the change landed it
|
|
1431
|
+
is kept nowhere else.
|
|
1432
|
+
|
|
1433
|
+
**Run the adapter's migration before using `changeEmail`.** The tokens store
|
|
1434
|
+
must list the `changeEmail` kind (janus-drizzle 0.8's migration, janus-mongo
|
|
1435
|
+
0.9's `syncMongoAdapter`); until then every `send` is `STORE_FAILED`.
|
|
1356
1436
|
|
|
1357
1437
|
**Every `janus()` that signs users in needs the same `secondFactor`.** An
|
|
1358
1438
|
instance without keys never signs in a user whose factor is active: `signIn`
|
|
@@ -1507,7 +1587,7 @@ and a tokens store that cannot answer fails every password sign-in with
|
|
|
1507
1587
|
**The mail throttle counts each flow on its own, and it is not a per-client
|
|
1508
1588
|
limit.** Five requests per window for one address (`magicLink.request`,
|
|
1509
1589
|
`signInCode.request`, `resetPassword.request`) or one user
|
|
1510
|
-
(`verifyEmail.send`, and `stepUp.request` when it e-mails), then
|
|
1590
|
+
(`verifyEmail.send`, `changeEmail.send`, and `stepUp.request` when it e-mails), then
|
|
1511
1591
|
`MailThrottledError`: answer 429 with `Retry-After: retryAfter`. It is safe to
|
|
1512
1592
|
show the visitor — it reveals nothing about accounts, unlike `reason`. A refused
|
|
1513
1593
|
request is counted too, but the window is fixed and cannot be extended.
|
|
@@ -1617,7 +1697,7 @@ that sends one, since it is awaited: queue the event and return.
|
|
|
1617
1697
|
|
|
1618
1698
|
## Type safety, counted
|
|
1619
1699
|
|
|
1620
|
-
**One hundred and
|
|
1700
|
+
**One hundred and seventy-two plausible mistakes, one hundred and seventy-two refused at compile time — and
|
|
1621
1701
|
two gaps, named.**
|
|
1622
1702
|
|
|
1623
1703
|
The lists are typechecked and never run, with one `@ts-expect-error` per
|
|
@@ -1625,10 +1705,10 @@ mistake beside the shapes that must keep compiling. One is a single file:
|
|
|
1625
1705
|
`test/types/refusals.ts` (fifteen, on the shared vocabulary). The other three
|
|
1626
1706
|
are folders with one file per behaviour: `test/types/port/` (twenty-five, on
|
|
1627
1707
|
the identity stores' port, from the point of view of the person implementing
|
|
1628
|
-
it), `test/types/auth/` (eighty-
|
|
1708
|
+
it), `test/types/auth/` (eighty-four, on `janus()`, from the point of view of
|
|
1629
1709
|
the application — twelve of them on the second factor, three on sign-in codes,
|
|
1630
1710
|
five on user events, four on step-ups, six on the sign-in throttle, five on the mail throttle, four on
|
|
1631
|
-
sign-in links, six on devices, two on `findMany`, five on requests in two steps, three on signing in on the application's proof, three on finding a user by e-mail, three on proving an e-mail on the application's proof) and `test/types/permissions/` (forty-eight, on the
|
|
1711
|
+
sign-in links, six on devices, two on `findMany`, five on requests in two steps, three on signing in on the application's proof, three on finding a user by e-mail, three on proving an e-mail on the application's proof, three on changing an e-mail) and `test/types/permissions/` (forty-eight, on the
|
|
1632
1712
|
permission model and the questions asked of it). The rule comes from
|
|
1633
1713
|
`nxgt-data`, and so does the reason to distrust the claim without the files:
|
|
1634
1714
|
when it was last measured on `@nxgt/mongo`, *seven of twelve plausible
|
|
@@ -52,6 +52,8 @@ interface SharedConfig {
|
|
|
52
52
|
readonly magicLink?: Duration;
|
|
53
53
|
/** How long a step-up's challenge waits, e-mailed or not. `'10m'` when absent. */
|
|
54
54
|
readonly stepUp?: Duration;
|
|
55
|
+
/** How long the link sent to a new address waits. `'1h'` when absent. */
|
|
56
|
+
readonly changeEmail?: Duration;
|
|
55
57
|
};
|
|
56
58
|
/**
|
|
57
59
|
* How `signIn` answers password guessing. **On by default**: past ten
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"janus-config.d.ts","sourceRoot":"","sources":["../../../src/auth/config/janus-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9D,2DAA2D;AAC3D,MAAM,WAAW,YAAY;IAC5B,oFAAoF;IACpF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,yBAAyB;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,2BAA2B;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC9C,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,UAAU,YAAY;IACrB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC/C,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE;QACjB,2BAA2B;QAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC;QAChC,0BAA0B;QAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC;QAClC,oEAAoE;QACpE,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC;QAC/B,oEAAoE;QACpE,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC;QAC9B,kFAAkF;QAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"janus-config.d.ts","sourceRoot":"","sources":["../../../src/auth/config/janus-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9D,2DAA2D;AAC3D,MAAM,WAAW,YAAY;IAC5B,oFAAoF;IACpF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,yBAAyB;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,2BAA2B;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC9C,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,UAAU,YAAY;IACrB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC/C,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE;QACjB,2BAA2B;QAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC;QAChC,0BAA0B;QAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC;QAClC,oEAAoE;QACpE,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC;QAC/B,oEAAoE;QACpE,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC;QAC9B,kFAAkF;QAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC;QAC3B,yEAAyE;QACzE,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC;KAChC,CAAC;IACF;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B;;;;;;;OAOG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC;;;;;;;;OAQG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;CACpC;AAED,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,oBAAoB,GAAG,KAAK,CAAC;CACjD;AAED,8DAA8D;AAC9D,MAAM,WAAW,oBAAoB;IACpC,0FAA0F;IAC1F,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAED,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,GAAG,KAAK,CAAC;CAC/C;AAED,oFAAoF;AACpF,MAAM,WAAW,kBAAkB;IAClC,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAED,mFAAmF;AACnF,MAAM,WAAW,kBAAkB;IAClC,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,UAAU,EAAE,GAAG,UAAU,EAAE,CAAC,CAAC;IACtD,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,UAAU,EAAE,GAAG,UAAU,EAAE,CAAC,CAAC;CACtD;AAED,+DAA+D;AAC/D,MAAM,WAAW,gBAChB,SAAQ,YAAY,EACnB,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACvB;AAED,mEAAmE;AACnE,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACpD,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,CAAA;KAAE,CAAC;IAC5D,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC;CAC/B;AAED,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,eAAe,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolved-config.d.ts","sourceRoot":"","sources":["../../../src/auth/config/resolved-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,oFAAoF;AACpF,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE;QAClB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;QAC9C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;KAC3B,GAAG,IAAI,CAAC;IACT,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAClD,QAAQ,CAAC,UAAU,EAAE;QACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"resolved-config.d.ts","sourceRoot":"","sources":["../../../src/auth/config/resolved-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,oFAAoF;AACpF,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE;QAClB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;QAC9C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;KAC3B,GAAG,IAAI,CAAC;IACT,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAClD,QAAQ,CAAC,UAAU,EAAE;QACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF,gDAAgD;IAChD,QAAQ,CAAC,cAAc,EAAE;QACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;KAC1B,GAAG,IAAI,CAAC;IACT,8CAA8C;IAC9C,QAAQ,CAAC,YAAY,EAAE;QACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;KAC1B,GAAG,IAAI,CAAC;IACT,QAAQ,CAAC,YAAY,EAAE;QACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;KAChC,GAAG,IAAI,CAAC;IACT,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACrD,QAAQ,CAAC,MAAM,EAAE;QAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;QAC7C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;KACzB,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"warn-throttle-window.d.ts","sourceRoot":"","sources":["../../../src/auth/config/warn-throttle-window.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"warn-throttle-window.d.ts","sourceRoot":"","sources":["../../../src/auth/config/warn-throttle-window.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAyBxD,iFAAiF;AACjF,wBAAgB,qBAAqB,CACpC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,cAAc,GAAG,YAAY,CAAC,EAC7D,KAAK,EAAE,MAAM,GACX,MAAM,GAAG,IAAI,CAgBf;AAED,oGAAoG;AACpG,wBAAgB,kBAAkB,CACjC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,cAAc,GAAG,YAAY,CAAC,EAC7D,KAAK,EAAE,MAAM,GACX,IAAI,CAUN"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The token a change of e-mail sends and redeems: issued for the NEW
|
|
3
|
+
* address, bound to the address it replaces, and refused when the user's
|
|
4
|
+
* e-mail is no longer that one.
|
|
5
|
+
*
|
|
6
|
+
* `address` holds the new address; `codeHash` holds the former one, keyed by
|
|
7
|
+
* the token's secret (`TokenRecord.codeHash`), so the port needs no field and
|
|
8
|
+
* a dump of the store reveals neither.
|
|
9
|
+
*/
|
|
10
|
+
import { type ResolvedType } from '../config';
|
|
11
|
+
import { type Context } from '../context';
|
|
12
|
+
import type { TokenRecord, UserRecord } from '../port/types';
|
|
13
|
+
import type { IssuedToken } from '../types';
|
|
14
|
+
/** What binds a token to the address it replaces. */
|
|
15
|
+
export declare const formerHash: (secret: string, former: string | null) => string;
|
|
16
|
+
/**
|
|
17
|
+
* Validates `email` as the user's new address — by the type's own schema, the
|
|
18
|
+
* other fields as they are — and gives it back as the schema left it. An
|
|
19
|
+
* address equal to the current one once normalised is `USER_INVALID`: moving
|
|
20
|
+
* to where the user already is means nothing (`verifyEmail` proves it).
|
|
21
|
+
*/
|
|
22
|
+
export declare function newAddressOf(type: ResolvedType, user: UserRecord, email: string, where: string): Promise<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Issues the token for the validated new `address`, bound to the address the
|
|
25
|
+
* user has now, and spends the user's earlier ones.
|
|
26
|
+
*/
|
|
27
|
+
export declare function issueChangeEmailToken(context: Context, type: ResolvedType, user: UserRecord, address: string): Promise<IssuedToken>;
|
|
28
|
+
/**
|
|
29
|
+
* Refuses a token asked from an address the user has left: the link would
|
|
30
|
+
* move somebody who is no longer where the request came from.
|
|
31
|
+
*/
|
|
32
|
+
export declare function refuseMoved(type: ResolvedType, user: UserRecord, token: TokenRecord, secret: string, where: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Spends a change's token and says why it cannot be used, when it cannot. A
|
|
35
|
+
* user gone since, or of another type, is as good as no token; a user who
|
|
36
|
+
* moved since the link was asked is stale.
|
|
37
|
+
*/
|
|
38
|
+
export declare function redeemChangeEmailToken(context: Context, type: ResolvedType, secret: string, where: string): Promise<{
|
|
39
|
+
token: TokenRecord;
|
|
40
|
+
user: UserRecord;
|
|
41
|
+
}>;
|
|
42
|
+
//# sourceMappingURL=change-email-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-email-token.d.ts","sourceRoot":"","sources":["../../../src/auth/email-flows/change-email-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,KAAK,OAAO,EAAuC,MAAM,YAAY,CAAC;AAE/E,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,qDAAqD;AACrD,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,EAAE,QAAQ,MAAM,GAAG,IAAI,KAAG,MAGjE,CAAC;AAEH;;;;;GAKG;AACH,wBAAsB,YAAY,CACjC,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CA0BjB;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,CAAC,CAmBtB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAC1B,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACX,IAAI,CAQN;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC3C,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAanD"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Changing a user's e-mail: send a token to the NEW address, then redeem it
|
|
3
|
+
* to move the user there — verified, since the link reached its inbox.
|
|
4
|
+
*/
|
|
5
|
+
import type { At } from '../at';
|
|
6
|
+
import type { ResolvedType } from '../config';
|
|
7
|
+
import { type AnyUser, type Context } from '../context';
|
|
8
|
+
import type { ChangeEmailApi } from '../types';
|
|
9
|
+
/** `changeEmail` of one user type: `send` to the new address, then `confirm`. */
|
|
10
|
+
export declare function changeEmailFlows(context: Context, type: ResolvedType, at: At): ChangeEmailApi<AnyUser>['changeEmail'];
|
|
11
|
+
//# sourceMappingURL=change-email.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-email.d.ts","sourceRoot":"","sources":["../../../src/auth/email-flows/change-email.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAMZ,MAAM,YAAY,CAAC;AAIpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAe/C,iFAAiF;AACjF,wBAAgB,gBAAgB,CAC/B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,EAAE,GACJ,cAAc,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,CA4BxC"}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import type { At } from '../at';
|
|
3
3
|
import type { ResolvedType } from '../config';
|
|
4
4
|
import type { AnyUser, Context } from '../context';
|
|
5
|
-
import type { ResetPasswordApi, VerifyEmailApi } from '../types';
|
|
5
|
+
import type { ChangeEmailApi, ResetPasswordApi, VerifyEmailApi } from '../types';
|
|
6
6
|
/**
|
|
7
7
|
* The e-mail flows: send a one-time token by e-mail, then confirm it —
|
|
8
|
-
* verifying the address,
|
|
9
|
-
* way: spend the token, read the user, and check
|
|
10
|
-
* very record the write replaces.
|
|
8
|
+
* verifying the address, resetting the password, or moving to a new address.
|
|
9
|
+
* All three confirm the same way: spend the token, read the user, and check
|
|
10
|
+
* the address again on the very record the write replaces.
|
|
11
11
|
*/
|
|
12
|
-
export declare function emailFlows(context: Context, type: ResolvedType, at: At): VerifyEmailApi<AnyUser> & ResetPasswordApi<AnyUser>;
|
|
12
|
+
export declare function emailFlows(context: Context, type: ResolvedType, at: At): VerifyEmailApi<AnyUser> & ResetPasswordApi<AnyUser> & ChangeEmailApi<AnyUser>;
|
|
13
13
|
//# sourceMappingURL=flows.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flows.d.ts","sourceRoot":"","sources":["../../../src/auth/email-flows/flows.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAEnF,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"flows.d.ts","sourceRoot":"","sources":["../../../src/auth/email-flows/flows.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAEnF,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EACX,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,MAAM,UAAU,CAAC;AAKlB;;;;;GAKG;AACH,wBAAgB,UAAU,CACzB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,EAAE,GACJ,cAAc,CAAC,OAAO,CAAC,GACzB,gBAAgB,CAAC,OAAO,CAAC,GACzB,cAAc,CAAC,OAAO,CAAC,CAMvB"}
|
package/dist/auth/events.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { Context } from './context';
|
|
|
5
5
|
*
|
|
6
6
|
* - `user.created` — by `create` or `signUp`;
|
|
7
7
|
* - `user.emailVerified` — by `verifyEmail.confirm`, or by the link of
|
|
8
|
-
* `resetPassword.confirm` or `
|
|
8
|
+
* `resetPassword.confirm`, `magicLink.confirm` or `changeEmail.confirm`, or the code of
|
|
9
9
|
* `signInCode.confirm`, which prove the e-mail too; never for an e-mail
|
|
10
10
|
* already verified;
|
|
11
11
|
* - `user.passwordReset` — by `resetPassword.confirm`;
|
|
@@ -13,7 +13,8 @@ import type { Context } from './context';
|
|
|
13
13
|
* `signInCode.confirm` and `magicLink.confirm` when their first proof of
|
|
14
14
|
* the e-mail dropped a password, after `user.emailVerified`; never by a
|
|
15
15
|
* reset, which is `user.passwordReset` alone;
|
|
16
|
-
* - `user.emailChanged` — by `update`, when
|
|
16
|
+
* - `user.emailChanged` — by `update` and `changeEmail.confirm`, when they
|
|
17
|
+
* changed the e-mail — compared
|
|
17
18
|
* normalised, the same test that makes the new one unverified. The one
|
|
18
19
|
* event that carries more than the user: `formerEmail`;
|
|
19
20
|
* - `user.secondFactorEnabled` — by `secondFactor.activate`, once the factor
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/auth/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,EAAU,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/auth/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,EAAU,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,MAAM,aAAa,GACtB,cAAc,GACd,oBAAoB,GACpB,oBAAoB,GACpB,sBAAsB,GACtB,mBAAmB,GACnB,0BAA0B,GAC1B,2BAA2B,GAC3B,+BAA+B,GAC/B,uBAAuB,GACvB,wBAAwB,GACxB,cAAc,CAAC;AAElB;;;;;;;GAOG;AACH,MAAM,WAAW,SAAS;IACzB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,uEAAuE;AACvE,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,aAAa,GAAG,WAAW,CAAC,CAAC;AAEvE;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE3E,oFAAoF;AACpF,wBAAgB,aAAa,CAC5B,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,MAAM,GACX,iBAAiB,GAAG,IAAI,CAQ1B;AAED;;;;;;GAMG;AACH,wBAAsB,IAAI,CACzB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAChD,UAAU,EAAE,IAAI,EAChB,MAAM,GAAE,WAAgB,GACtB,OAAO,CAAC,IAAI,CAAC,CAqBf"}
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -8,5 +8,5 @@ export type { JanusStores, Json, JsonObject, PasswordRecord, SecondFactorRecord,
|
|
|
8
8
|
export type { SealingKey } from './sealing';
|
|
9
9
|
export { assertFresh } from './sessions/fresh';
|
|
10
10
|
export type { StandardSchemaV1 } from './standard-schema';
|
|
11
|
-
export type { Authenticated, Checked, EmailOf, FindByEmailApi, FirstProof, HeaderRecord, IssuedCode, IssuedToken, Janus, LoginOf, MagicLinkApi, PasswordApi, PreparedCode, PreparedRequest, ProvenSignInApi, RecoveredSignIn, RecoveryCodesIssued, RequestLike, RequiredStringKeys, ResetPasswordApi, SecondFactorApi, SecondFactorEnrolment, SecondFactorRequired, Session, SharedApi, SignedIn, SignInCodeApi, SignInOptions, SignInResult, StepUpApi, StepUpByApp, StepUpByEmail, TypeApi, TypesOf, User, UserBase, UserOf, UserRef, UserTypeApi, VerifyEmailApi, WriteOptions, } from './types';
|
|
11
|
+
export type { Authenticated, ChangeEmailApi, Checked, EmailOf, FindByEmailApi, FirstProof, HeaderRecord, IssuedCode, IssuedToken, Janus, LoginOf, MagicLinkApi, PasswordApi, PreparedCode, PreparedRequest, ProvenSignInApi, RecoveredSignIn, RecoveryCodesIssued, RequestLike, RequiredStringKeys, ResetPasswordApi, SecondFactorApi, SecondFactorEnrolment, SecondFactorRequired, Session, SharedApi, SignedIn, SignInCodeApi, SignInOptions, SignInResult, StepUpApi, StepUpByApp, StepUpByEmail, TypeApi, TypesOf, User, UserBase, UserOf, UserRef, UserTypeApi, VerifyEmailApi, WriteOptions, } from './types';
|
|
12
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/auth/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,YAAY,EACZ,aAAa,EACb,UAAU,EACV,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,EACV,cAAc,GACd,MAAM,UAAU,CAAC;AAClB,YAAY,EACX,SAAS,EACT,iBAAiB,EACjB,aAAa,GACb,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,YAAY,EACX,WAAW,EACX,IAAI,EACJ,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,SAAS,EACT,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,UAAU,EACV,eAAe,EACf,SAAS,EACT,UAAU,EACV,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,YAAY,EACX,aAAa,EACb,OAAO,EACP,OAAO,EACP,cAAc,EACd,UAAU,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,KAAK,EACL,OAAO,EACP,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,eAAe,EACf,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,OAAO,EACP,SAAS,EACT,QAAQ,EACR,aAAa,EACb,aAAa,EACb,YAAY,EACZ,SAAS,EACT,WAAW,EACX,aAAa,EACb,OAAO,EACP,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,OAAO,EACP,WAAW,EACX,cAAc,EACd,YAAY,GACZ,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,YAAY,EACZ,aAAa,EACb,UAAU,EACV,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,EACV,cAAc,GACd,MAAM,UAAU,CAAC;AAClB,YAAY,EACX,SAAS,EACT,iBAAiB,EACjB,aAAa,GACb,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,YAAY,EACX,WAAW,EACX,IAAI,EACJ,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,SAAS,EACT,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,UAAU,EACV,eAAe,EACf,SAAS,EACT,UAAU,EACV,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,YAAY,EACX,aAAa,EACb,cAAc,EACd,OAAO,EACP,OAAO,EACP,cAAc,EACd,UAAU,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,KAAK,EACL,OAAO,EACP,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,eAAe,EACf,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,OAAO,EACP,SAAS,EACT,QAAQ,EACR,aAAa,EACb,aAAa,EACb,YAAY,EACZ,SAAS,EACT,WAAW,EACX,aAAa,EACb,OAAO,EACP,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,OAAO,EACP,WAAW,EACX,cAAc,EACd,YAAY,GACZ,MAAM,SAAS,CAAC"}
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
* past the limit, as a registered one is, so being throttled never tells
|
|
23
23
|
* who has an account;
|
|
24
24
|
* - **per user**, for the requests the application makes for a user it
|
|
25
|
-
* knows — `verifyEmail.send`,
|
|
25
|
+
* knows — `verifyEmail.send`, `changeEmail.send` (and, for the address it
|
|
26
|
+
* names, per address too), and `stepUp.request` when it e-mails a code.
|
|
26
27
|
* Nobody without the user's session or the application's call can spend
|
|
27
28
|
* that count, so a loop on their address leaves their own requests alone;
|
|
28
29
|
* and whatever addresses one user moves through, they are sent at most as
|
|
@@ -40,12 +41,14 @@
|
|
|
40
41
|
import { type ResolvedType } from './config';
|
|
41
42
|
import type { Context } from './context';
|
|
42
43
|
/** The flows that hand out something to e-mail, each counted on its own. */
|
|
43
|
-
export type MailFlow = 'magicLink' | 'signInCode' | 'resetPassword' | 'verifyEmail' | 'stepUp';
|
|
44
|
+
export type MailFlow = 'magicLink' | 'signInCode' | 'resetPassword' | 'verifyEmail' | 'stepUp' | 'changeEmail';
|
|
44
45
|
/**
|
|
45
46
|
* Counts one request of `flow` for `email` — before it is looked up — and
|
|
46
47
|
* refuses past the last one, whether anybody holds the address or not.
|
|
48
|
+
* `userId`, for a request made for a user (`changeEmail.send`), is only
|
|
49
|
+
* carried by the refusal; the count stays the address's.
|
|
47
50
|
*/
|
|
48
|
-
export declare function countMailByAddress(context: Context, type: ResolvedType, flow: MailFlow, email: string, where: string): Promise<void>;
|
|
51
|
+
export declare function countMailByAddress(context: Context, type: ResolvedType, flow: MailFlow, email: string, where: string, userId?: string): Promise<void>;
|
|
49
52
|
/** Counts one request of `flow` for the user `userId`, and refuses past the last one. */
|
|
50
53
|
export declare function countMailByUser(context: Context, type: ResolvedType, flow: MailFlow, userId: string, where: string): Promise<void>;
|
|
51
54
|
//# sourceMappingURL=mail-requests.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mail-requests.d.ts","sourceRoot":"","sources":["../../src/auth/mail-requests.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"mail-requests.d.ts","sourceRoot":"","sources":["../../src/auth/mail-requests.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQzC,4EAA4E;AAC5E,MAAM,MAAM,QAAQ,GACjB,WAAW,GACX,YAAY,GACZ,eAAe,GACf,aAAa,GACb,QAAQ,GACR,aAAa,CAAC;AAUjB;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,yFAAyF;AACzF,wBAAsB,eAAe,CACpC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAEf"}
|
|
@@ -20,7 +20,13 @@ interface OneTimeRequest {
|
|
|
20
20
|
* Issues a one-time token: 32 random bytes, given back once, and only their
|
|
21
21
|
* hash stored.
|
|
22
22
|
*/
|
|
23
|
-
export declare function issueOneTime(context: Context, token: OneTimeRequest
|
|
23
|
+
export declare function issueOneTime(context: Context, token: OneTimeRequest & {
|
|
24
|
+
/**
|
|
25
|
+
* What the token is bound to, stored as its `codeHash`: `changeEmail`
|
|
26
|
+
* binds the address it replaces. `null` by default.
|
|
27
|
+
*/
|
|
28
|
+
readonly boundHash?: string;
|
|
29
|
+
}): Promise<{
|
|
24
30
|
readonly secret: string;
|
|
25
31
|
readonly expiresAt: Date;
|
|
26
32
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue.d.ts","sourceRoot":"","sources":["../../../src/auth/one-time/issue.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C,UAAU,cAAc;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CACjC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"issue.d.ts","sourceRoot":"","sources":["../../../src/auth/one-time/issue.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C,UAAU,cAAc;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CACjC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,cAAc,GAAG;IACvB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B,GACC,OAAO,CAAC;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAA;CAAE,CAAC,CAEhE;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC9B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,cAAc,GACnB,OAAO,CAAC;IACV,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB,CAAC,CAGD"}
|
|
@@ -23,8 +23,12 @@ import type { Id } from '../../../ids/id';
|
|
|
23
23
|
* sent by e-mail, or, with an active second factor, a code from their app.
|
|
24
24
|
* A kind of its own, so a sign-in code never confirms an action nor an
|
|
25
25
|
* action's code signs anyone in.
|
|
26
|
+
* - `changeEmail`: a link sent by e-mail to a user's new address, to confirm
|
|
27
|
+
* it. A kind of its own, so a verification link — which proves the address
|
|
28
|
+
* the user already holds — never changes an address, nor this one verifies
|
|
29
|
+
* the current one.
|
|
26
30
|
*/
|
|
27
|
-
export type TokenKind = 'verifyEmail' | 'resetPassword' | 'secondFactor' | 'signInCode' | 'magicLink' | 'stepUp';
|
|
31
|
+
export type TokenKind = 'verifyEmail' | 'resetPassword' | 'secondFactor' | 'signInCode' | 'magicLink' | 'stepUp' | 'changeEmail';
|
|
28
32
|
/** A one-time token, as a store holds it: its hash, never its secret. */
|
|
29
33
|
export interface TokenRecord {
|
|
30
34
|
/** `sha256` of the token's secret, hex. Unique across the store. */
|
|
@@ -33,14 +37,16 @@ export interface TokenRecord {
|
|
|
33
37
|
readonly userId: Id;
|
|
34
38
|
/**
|
|
35
39
|
* The e-mail the token was sent to — the one a verification marks
|
|
36
|
-
* verified
|
|
40
|
+
* verified; for `changeEmail`, the new address the user will hold.
|
|
41
|
+
* `''` for a second-factor challenge, which nothing was sent for.
|
|
37
42
|
*/
|
|
38
43
|
readonly address: string;
|
|
39
44
|
/**
|
|
40
45
|
* For a token redeemed with an e-mailed code — `signInCode`, and a
|
|
41
46
|
* `stepUp` sent by e-mail — the code's hash, keyed
|
|
42
|
-
* by the token's secret, so the tokens alone do not reveal it.
|
|
43
|
-
*
|
|
47
|
+
* by the token's secret, so the tokens alone do not reveal it. For
|
|
48
|
+
* `changeEmail`, the address it replaces, keyed by the secret the same way.
|
|
49
|
+
* `null` for every other kind: the core writes it so, and a store keeps what it is
|
|
44
50
|
* given.
|
|
45
51
|
*/
|
|
46
52
|
readonly codeHash: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../../../src/auth/port/types/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAE1C
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../../../src/auth/port/types/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAE1C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,SAAS,GAClB,aAAa,GACb,eAAe,GACf,cAAc,GACd,YAAY,GACZ,WAAW,GACX,QAAQ,GACR,aAAa,CAAC;AAEjB,yEAAyE;AACzE,MAAM,WAAW,WAAW;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CACzB;AAED,kDAAkD;AAClD,MAAM,WAAW,UAAU;IAC1B;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD;;;;;;;;;;;;;;;;;;OAkBG;IACH,YAAY,CACX,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,IAAI,GACN,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE/B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE9E;;;;;;;;;;;;;;;;;OAiBG;IACH,eAAe,CACd,MAAM,EAAE,EAAE,EACV,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,IAAI,EACR,MAAM,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB;;;;OAIG;IACH,gBAAgB,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a user type with an e-mail answers besides: moving the user to a new
|
|
3
|
+
* address, by a link sent to it.
|
|
4
|
+
*
|
|
5
|
+
* Part of what `janus()` hands back; `./index` gathers it.
|
|
6
|
+
*/
|
|
7
|
+
import type { IssuedToken } from './email-flows';
|
|
8
|
+
import type { UserRef } from './user';
|
|
9
|
+
/**
|
|
10
|
+
* Changing a user's e-mail, proved: a link is sent to the **new** address,
|
|
11
|
+
* and following it moves the user there.
|
|
12
|
+
*/
|
|
13
|
+
export interface ChangeEmailApi<U> {
|
|
14
|
+
readonly changeEmail: {
|
|
15
|
+
/**
|
|
16
|
+
* Issues a link's token for the new address `email`. `email` is the
|
|
17
|
+
* `email` field's value, validated by the type's schema as `update`
|
|
18
|
+
* would — a malformed one is `USER_INVALID` — and the answer's `email`
|
|
19
|
+
* is the address to send the link to. Nothing changes until `confirm`.
|
|
20
|
+
*
|
|
21
|
+
* **Gate it**: behind a fresh sign-in (`assertFresh`) or a step-up, since
|
|
22
|
+
* whoever changes the e-mail takes over password resets. Put `token` in
|
|
23
|
+
* a link to a page of yours, and **only in the e-mail** to the new
|
|
24
|
+
* address. Tell the former address from `user.emailChanged`.
|
|
25
|
+
*
|
|
26
|
+
* Whether somebody already holds the new address is **not** checked here
|
|
27
|
+
* — it would tell who has an account; `confirm` refuses `LOGIN_TAKEN`.
|
|
28
|
+
* The user's earlier links are spent: only the last one sent works.
|
|
29
|
+
* **Throttled** per user and per new address (`janus({ mail: { throttle } })`):
|
|
30
|
+
* `MAIL_THROTTLED` with `retryAfter`, and no token. An unknown user is
|
|
31
|
+
* `NOT_FOUND`, an inactive one `USER_INACTIVE`.
|
|
32
|
+
*/
|
|
33
|
+
send(user: UserRef, email: string): Promise<IssuedToken>;
|
|
34
|
+
/**
|
|
35
|
+
* Spends the link's token, moves the user to the address it was sent to
|
|
36
|
+
* and marks it verified — the link reached its inbox. Password, second
|
|
37
|
+
* factor and sessions are untouched. Emits `user.emailChanged` (with
|
|
38
|
+
* `formerEmail`) and `user.emailVerified`.
|
|
39
|
+
*
|
|
40
|
+
* **Call it from a `POST`**, never from the `GET` of the link. An
|
|
41
|
+
* unknown, spent or lapsed token is `TOKEN_UNKNOWN`, `TOKEN_SPENT` or
|
|
42
|
+
* `TOKEN_EXPIRED`; a user whose e-mail is no longer the one the link
|
|
43
|
+
* was asked from is `TOKEN_STALE`; an address another user of the type
|
|
44
|
+
* holds is `LOGIN_TAKEN` — the token already spent; an inactive user
|
|
45
|
+
* is `USER_INACTIVE`. A user written in between is `VERSION_CONFLICT`,
|
|
46
|
+
* also after the token is spent.
|
|
47
|
+
*/
|
|
48
|
+
confirm(token: string): Promise<U>;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=change-email.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-email.d.ts","sourceRoot":"","sources":["../../../src/auth/types/change-email.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC;;;GAGG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE;QACrB;;;;;;;;;;;;;;;;;WAiBG;QACH,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QACzD;;;;;;;;;;;;;WAaG;QACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;KACnC,CAAC;CACF"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* keeps each schema's type travelling through every public method without
|
|
8
8
|
* dragging a type parameter through every internal function.
|
|
9
9
|
*/
|
|
10
|
+
export type { ChangeEmailApi } from './change-email';
|
|
10
11
|
export type { Checked } from './checks';
|
|
11
12
|
export type { FirstProof, IssuedCode, IssuedToken, ResetPasswordApi, SignInCodeApi, VerifyEmailApi, } from './email-flows';
|
|
12
13
|
export type { FindByEmailApi } from './find-by-email';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EACX,UAAU,EACV,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,cAAc,GACd,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,YAAY,EACX,OAAO,EACP,OAAO,EACP,kBAAkB,EAClB,OAAO,EACP,MAAM,GACN,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAChE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,YAAY,EACX,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,qBAAqB,GACrB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACX,aAAa,EACb,YAAY,EACZ,WAAW,EACX,OAAO,GACP,MAAM,WAAW,CAAC;AACnB,YAAY,EACX,oBAAoB,EACpB,QAAQ,EACR,aAAa,EACb,YAAY,GACZ,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACvE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EACX,UAAU,EACV,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,cAAc,GACd,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,YAAY,EACX,OAAO,EACP,OAAO,EACP,kBAAkB,EAClB,OAAO,EACP,MAAM,GACN,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAChE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,YAAY,EACX,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,qBAAqB,GACrB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACX,aAAa,EACb,YAAY,EACZ,WAAW,EACX,OAAO,GACP,MAAM,WAAW,CAAC;AACnB,YAAY,EACX,oBAAoB,EACpB,QAAQ,EACR,aAAa,EACb,YAAY,GACZ,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACvE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Part of what `janus()` hands back; `./index` gathers it.
|
|
6
6
|
*/
|
|
7
7
|
import type { JanusConfig, MultiTypeConfig, SingleTypeConfig } from '../config';
|
|
8
|
+
import type { ChangeEmailApi } from './change-email';
|
|
8
9
|
import type { ResetPasswordApi, SignInCodeApi, VerifyEmailApi } from './email-flows';
|
|
9
10
|
import type { FindByEmailApi } from './find-by-email';
|
|
10
11
|
import type { EmailOf, FieldsInput, LoginOf, SingleAsType, UserOf, UserOfType } from './inference';
|
|
@@ -28,7 +29,7 @@ type SignInAnswer<Name extends string, Def, TwoFactor extends boolean> = TwoFact
|
|
|
28
29
|
* The whole surface of one user type, with only the flows its configuration
|
|
29
30
|
* allows. `TwoFactor` is whether `janus()` was given a `secondFactor`.
|
|
30
31
|
*/
|
|
31
|
-
export type TypeApi<Name extends string, Def, TwoFactor extends boolean = false> = UserTypeApi<UserOfType<Name, Def>, FieldsInput<Def>> & ProvenSignInApi<UserOfType<Name, Def>, SignInAnswer<Name, Def, TwoFactor>> & ([LoginOf<Def>] extends [never] ? unknown : TwoFactor extends true ? PasswordApi<UserOfType<Name, Def>, FieldsInput<Def>, LoginOf<Def>, SignInResult<UserOfType<Name, Def>>> & SecondFactorApi<UserOfType<Name, Def>> : PasswordApi<UserOfType<Name, Def>, FieldsInput<Def>, LoginOf<Def>>) & ([EmailOf<Def>] extends [never] ? unknown : FindByEmailApi<UserOfType<Name, Def>> & VerifyEmailApi<UserOfType<Name, Def>> & SignInCodeApi<UserOfType<Name, Def>, SignInAnswer<Name, Def, TwoFactor>> & MagicLinkApi<UserOfType<Name, Def>, SignInAnswer<Name, Def, TwoFactor>> & StepUpApi<UserOfType<Name, Def>, TwoFactor extends true ? [LoginOf<Def>] extends [never] ? StepUpByEmail<UserOfType<Name, Def>> : StepUpByEmail<UserOfType<Name, Def>> | StepUpByApp<UserOfType<Name, Def>> : StepUpByEmail<UserOfType<Name, Def>>>) & ([LoginOf<Def>] extends [never] ? unknown : [EmailOf<Def>] extends [never] ? unknown : ResetPasswordApi<UserOfType<Name, Def>>);
|
|
32
|
+
export type TypeApi<Name extends string, Def, TwoFactor extends boolean = false> = UserTypeApi<UserOfType<Name, Def>, FieldsInput<Def>> & ProvenSignInApi<UserOfType<Name, Def>, SignInAnswer<Name, Def, TwoFactor>> & ([LoginOf<Def>] extends [never] ? unknown : TwoFactor extends true ? PasswordApi<UserOfType<Name, Def>, FieldsInput<Def>, LoginOf<Def>, SignInResult<UserOfType<Name, Def>>> & SecondFactorApi<UserOfType<Name, Def>> : PasswordApi<UserOfType<Name, Def>, FieldsInput<Def>, LoginOf<Def>>) & ([EmailOf<Def>] extends [never] ? unknown : FindByEmailApi<UserOfType<Name, Def>> & VerifyEmailApi<UserOfType<Name, Def>> & ChangeEmailApi<UserOfType<Name, Def>> & SignInCodeApi<UserOfType<Name, Def>, SignInAnswer<Name, Def, TwoFactor>> & MagicLinkApi<UserOfType<Name, Def>, SignInAnswer<Name, Def, TwoFactor>> & StepUpApi<UserOfType<Name, Def>, TwoFactor extends true ? [LoginOf<Def>] extends [never] ? StepUpByEmail<UserOfType<Name, Def>> : StepUpByEmail<UserOfType<Name, Def>> | StepUpByApp<UserOfType<Name, Def>> : StepUpByEmail<UserOfType<Name, Def>>>) & ([LoginOf<Def>] extends [never] ? unknown : [EmailOf<Def>] extends [never] ? unknown : ResetPasswordApi<UserOfType<Name, Def>>);
|
|
32
33
|
/** What every configuration answers, whatever its user types. */
|
|
33
34
|
export interface SharedApi<U extends {
|
|
34
35
|
readonly type: string;
|