@nxgt/janus 0.17.1 → 0.18.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 +72 -18
- package/dist/auth/config/index.d.ts +1 -1
- package/dist/auth/config/index.d.ts.map +1 -1
- package/dist/auth/config/janus-config.d.ts +31 -0
- package/dist/auth/config/janus-config.d.ts.map +1 -1
- package/dist/auth/config/resolve-config.d.ts.map +1 -1
- package/dist/auth/config/resolve-throttle.d.ts +30 -0
- package/dist/auth/config/resolve-throttle.d.ts.map +1 -0
- package/dist/auth/config/resolved-config.d.ts +5 -0
- package/dist/auth/config/resolved-config.d.ts.map +1 -1
- package/dist/auth/config/warn-throttle-window.d.ts +14 -0
- package/dist/auth/config/warn-throttle-window.d.ts.map +1 -0
- package/dist/auth/counter-key.d.ts +19 -0
- package/dist/auth/counter-key.d.ts.map +1 -0
- package/dist/auth/email-flows/reset-password.d.ts.map +1 -1
- package/dist/auth/email-flows/verify-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/magic-link.d.ts.map +1 -1
- package/dist/auth/mail-requests.d.ts +51 -0
- package/dist/auth/mail-requests.d.ts.map +1 -0
- package/dist/auth/sign-in-attempts.d.ts +3 -6
- package/dist/auth/sign-in-attempts.d.ts.map +1 -1
- package/dist/auth/sign-in-code.d.ts +3 -2
- package/dist/auth/sign-in-code.d.ts.map +1 -1
- package/dist/auth/step-up/request.d.ts.map +1 -1
- package/dist/auth/types/email-flows.d.ts +16 -6
- package/dist/auth/types/email-flows.d.ts.map +1 -1
- package/dist/auth/types/magic-link.d.ts +4 -2
- package/dist/auth/types/magic-link.d.ts.map +1 -1
- package/dist/auth/types/step-up.d.ts +4 -1
- package/dist/auth/types/step-up.d.ts.map +1 -1
- package/dist/chunks/{index-kj3st57z.js → index-4khsm7mw.js} +2 -2
- package/dist/chunks/{index-6c9fbtv2.js → index-cntabs9d.js} +2 -2
- package/dist/chunks/{index-hnwggyxs.js → index-kppkcbn5.js} +52 -49
- package/dist/chunks/{index-hnwggyxs.js.map → index-kppkcbn5.js.map} +4 -4
- package/dist/chunks/{index-baazjyvc.js → index-kvjj5xkp.js} +2 -2
- package/dist/conformance/index.js +3 -3
- package/dist/errors/janus-error/codes.d.ts +10 -0
- package/dist/errors/janus-error/codes.d.ts.map +1 -1
- package/dist/errors/janus-error/index.d.ts +1 -1
- package/dist/errors/janus-error/index.d.ts.map +1 -1
- package/dist/errors/janus-error/options.d.ts +4 -3
- package/dist/errors/janus-error/options.d.ts.map +1 -1
- package/dist/errors/janus-error/refusals.d.ts +8 -0
- package/dist/errors/janus-error/refusals.d.ts.map +1 -1
- package/dist/errors/janus-error/status.d.ts +1 -1
- package/dist/errors/janus-error/status.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +118 -29
- package/dist/index.js.map +18 -15
- package/dist/permissions/index.js +40 -29
- package/dist/permissions/index.js.map +6 -6
- package/docs/README.md +1 -1
- package/docs/guide/email-flows.md +164 -4
- package/docs/guide/errors.md +12 -3
- package/docs/guide/magic-link.md +41 -5
- package/docs/guide/passwords.md +2 -1
- package/docs/guide/sign-in-code.md +46 -7
- package/docs/guide/step-up.md +38 -7
- package/docs/guide/users.md +1 -0
- package/docs/roadmap.md +14 -1
- package/docs/troubleshooting.md +88 -3
- package/package.json +1 -1
- package/dist/auth/config/resolve-sign-in.d.ts +0 -5
- package/dist/auth/config/resolve-sign-in.d.ts.map +0 -1
- /package/dist/chunks/{index-kj3st57z.js.map → index-4khsm7mw.js.map} +0 -0
- /package/dist/chunks/{index-6c9fbtv2.js.map → index-cntabs9d.js.map} +0 -0
- /package/dist/chunks/{index-baazjyvc.js.map → index-kvjj5xkp.js.map} +0 -0
package/README.md
CHANGED
|
@@ -165,10 +165,10 @@ async function signIn(email: string, password: string): Promise<Response> {
|
|
|
165
165
|
```
|
|
166
166
|
|
|
167
167
|
`JanusError` is the base of everything thrown at call time. It extends `Error`,
|
|
168
|
-
so no consumer has to order their `catch` blocks. `code` is a union of twenty
|
|
168
|
+
so no consumer has to order their `catch` blocks. `code` is a union of twenty-one
|
|
169
169
|
string literals, so a `switch` over it is exhaustive and adding a code breaks the
|
|
170
170
|
compilation of callers that exhaust it. `statusOf(code)` answers the status
|
|
171
|
-
below, as `JanusErrorStatus` — a union of the
|
|
171
|
+
below, as `JanusErrorStatus` — a union of the nine literals, which a
|
|
172
172
|
framework's own status type accepts:
|
|
173
173
|
|
|
174
174
|
```ts
|
|
@@ -190,6 +190,7 @@ if (error instanceof JanusError) {
|
|
|
190
190
|
| `CODE_INVALID` | 401 — a one-time code that does not match: a second factor's, or one sent by e-mail; `attemptsLeft` from either `confirm` belongs in the body |
|
|
191
191
|
| `SECOND_FACTOR_NOT_ENROLLED`, `SECOND_FACTOR_ACTIVE` | 409 — the factor is not in the state the call needs |
|
|
192
192
|
| `USER_INACTIVE` | 403 |
|
|
193
|
+
| `MAIL_THROTTLED` | 429 — too many e-mails asked for one address or one user in the window; `retryAfter` belongs in the body and a `Retry-After` header. Tell the visitor to use the last e-mail they received (it still works) or to wait. Safe to show: it reveals nothing about accounts |
|
|
193
194
|
| `STEP_UP_REQUIRED` | 403 — the session proved who it is too long ago for this action: ask for a step-up, then send the request again |
|
|
194
195
|
| `TOKEN_UNKNOWN`, `TOKEN_SPENT`, `TOKEN_EXPIRED`, `TOKEN_STALE` | 400 |
|
|
195
196
|
| `INVALID_CURSOR` | 400 |
|
|
@@ -198,7 +199,7 @@ if (error instanceof JanusError) {
|
|
|
198
199
|
|
|
199
200
|
Each code has its class, all exported: `StoreFailure`, `StoreConflict` (`on:
|
|
200
201
|
'login' | 'version'`), `NotFoundError`, `UserInvalidError`, `CredentialError`,
|
|
201
|
-
`UserInactiveError`, `StepUpRequiredError`, `TokenError` (the `TOKEN_*` codes and `CODE_INVALID`),
|
|
202
|
+
`UserInactiveError`, `StepUpRequiredError`, `MailThrottledError`, `TokenError` (the `TOKEN_*` codes and `CODE_INVALID`),
|
|
202
203
|
`SecondFactorError`, `InvalidCursorError`, `UnsupportedError` and
|
|
203
204
|
`PermissionDepthError`. `StoreFailure` and `StoreConflict` are exported
|
|
204
205
|
**because an adapter throws them**. An adapter defines no error class of its own, so `instanceof` holds
|
|
@@ -400,6 +401,22 @@ else reaches the store and is asynchronous.
|
|
|
400
401
|
```ts
|
|
401
402
|
janus({ user, password: { login: 'email' }, store, hasher, signIn: { throttle: { attempts: 5, window: '1h' } } });
|
|
402
403
|
```
|
|
404
|
+
- **Requests that send e-mail are throttled**, on by default: past five
|
|
405
|
+
e-mails asked in a 10-minute window, a request refuses with
|
|
406
|
+
`MailThrottledError` (`MAIL_THROTTLED`, 429) and `retryAfter`, and issues,
|
|
407
|
+
spends and rotates nothing: the last link or code sent still works.
|
|
408
|
+
**Each flow counts on its own**: per address for
|
|
409
|
+
`magicLink.request`, `signInCode.request` and `resetPassword.request` — an
|
|
410
|
+
address nobody holds is counted and refused alike — and per user for
|
|
411
|
+
`verifyEmail.send` and for `stepUp.request` when it e-mails a code.
|
|
412
|
+
`mail: { throttle: { attempts, window } }` changes it, `mail: { throttle:
|
|
413
|
+
false }` turns it off; a store that cannot count throws `STORE_FAILED` and
|
|
414
|
+
nothing is issued
|
|
415
|
+
([e-mail flows](docs/guide/email-flows.md#requests-that-send-e-mail-are-throttled)).
|
|
416
|
+
|
|
417
|
+
```ts
|
|
418
|
+
janus({ user, store, mail: { throttle: { attempts: 3, window: '1h' } } });
|
|
419
|
+
```
|
|
403
420
|
- **Sessions** last `'7d'` and slide: `authenticate` renews one once `renewAfter`
|
|
404
421
|
(`'1d'`) has passed, writing at most once per period, and says so with
|
|
405
422
|
`renewed`. The token is handed back once; the store only holds its `sha256`.
|
|
@@ -685,8 +702,10 @@ to type.
|
|
|
685
702
|
password and the second factor dropped, every session signed out** — are
|
|
686
703
|
handled as for a code.
|
|
687
704
|
- **Not ended by a password write, nor limited by the sign-in throttle**:
|
|
688
|
-
the password proves nothing a link does, and
|
|
689
|
-
passwords.
|
|
705
|
+
the password proves nothing a link does, and that throttle counts
|
|
706
|
+
passwords. The mail throttle counts `request` per address, five per
|
|
707
|
+
10 minutes (`MAIL_THROTTLED`); the last link sent still works. Limit it per
|
|
708
|
+
client yourself.
|
|
690
709
|
|
|
691
710
|
[The sign-in link guide](docs/guide/magic-link.md) has the page that
|
|
692
711
|
confirms from a `POST` so mail scanners spend nothing, every error, routes
|
|
@@ -1067,20 +1086,25 @@ after a sign-out, is `TOKEN_UNKNOWN`. Its challenge is a secret like
|
|
|
1067
1086
|
`signInCode`'s — and check freshness on the server with `assertFresh`, never
|
|
1068
1087
|
from a flag the client keeps.
|
|
1069
1088
|
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1089
|
+
**`stepUp.request` is throttled per user, only when it e-mails.** An
|
|
1090
|
+
e-mailed code gets five guesses per challenge and a new challenge takes only
|
|
1091
|
+
a new `request`, so a stolen session could keep asking and fill the user's
|
|
1092
|
+
inbox: the mail throttle refuses the sixth in a window with `MAIL_THROTTLED`; the code
|
|
1093
|
+
last sent still works.
|
|
1094
|
+
A step-up confirmed with the app (`via: 'secondFactor'`) sends nothing and is
|
|
1095
|
+
not counted.
|
|
1074
1096
|
|
|
1075
1097
|
**Answer `signInCode.request` the same whether it issued a code or not** —
|
|
1076
1098
|
the same status, body and cookie: set a random challenge when it answered
|
|
1077
1099
|
`null`. The code route then still tells a decoy (`TOKEN_UNKNOWN`) from a
|
|
1078
1100
|
real challenge (`CODE_INVALID`, `attemptsLeft`, or `TOKEN_SPENT` once a later
|
|
1079
1101
|
request spent it): answer its refusals alike
|
|
1080
|
-
where addresses must stay secret.
|
|
1081
|
-
address
|
|
1082
|
-
|
|
1083
|
-
|
|
1102
|
+
where addresses must stay secret. The request is throttled **per
|
|
1103
|
+
address**, counted before anything is looked up, so an unknown address is
|
|
1104
|
+
refused past the limit as a registered one is. At most one code is live per
|
|
1105
|
+
user — a new `request` spends the one before — so the throttle bounds how
|
|
1106
|
+
often anyone who knows an address can fill its inbox or cancel its owner's
|
|
1107
|
+
code; it does not stop it.
|
|
1084
1108
|
|
|
1085
1109
|
**Confirm a sign-in link from a `POST`, never from its `GET`.** Mail
|
|
1086
1110
|
scanners open every link in an e-mail before the user does: a route that
|
|
@@ -1229,8 +1253,9 @@ your policy. A password refused for its length does not spend the token.
|
|
|
1229
1253
|
`resetPassword.request` spends the user's earlier links, and any password
|
|
1230
1254
|
written — by a link, `changePassword` or `setPassword` — spends every link
|
|
1231
1255
|
still live, so an older e-mail's link answers `TOKEN_SPENT`. Tell the visitor
|
|
1232
|
-
to use the latest e-mail
|
|
1233
|
-
|
|
1256
|
+
to use the latest e-mail. Each request cancels the link before it, so the
|
|
1257
|
+
mail throttle bounds `resetPassword.request` per address, five per 10
|
|
1258
|
+
minutes.
|
|
1234
1259
|
|
|
1235
1260
|
**`signIn` throttles each login, not each client.** Ten passwords per login
|
|
1236
1261
|
per 15 minutes, then `CREDENTIALS_INVALID` with `retryAfter` until the window
|
|
@@ -1249,6 +1274,35 @@ counts live in the tokens store: a flushed or evicting Redis forgets them,
|
|
|
1249
1274
|
and a tokens store that cannot answer fails every password sign-in with
|
|
1250
1275
|
`STORE_FAILED`.
|
|
1251
1276
|
|
|
1277
|
+
**The mail throttle counts each flow on its own, and it is not a per-client
|
|
1278
|
+
limit.** Five requests per window for one address (`magicLink.request`,
|
|
1279
|
+
`signInCode.request`, `resetPassword.request`) or one user
|
|
1280
|
+
(`verifyEmail.send`, and `stepUp.request` when it e-mails), then
|
|
1281
|
+
`MailThrottledError`: answer 429 with `Retry-After: retryAfter`. It is safe to
|
|
1282
|
+
show the visitor — it reveals nothing about accounts, unlike `reason`. A refused
|
|
1283
|
+
request is counted too, but the window is fixed and cannot be extended.
|
|
1284
|
+
**A refused request spends, invalidates and rotates nothing**: the last link or
|
|
1285
|
+
code sent, by anyone's request, still confirms until it expires, so somebody
|
|
1286
|
+
who knows an address cannot shut its e-mailed sign-in or reset — at most they
|
|
1287
|
+
fill the inbox, five e-mails per window per flow. Tell the visitor to use the
|
|
1288
|
+
last e-mail they received, or to wait `retryAfter` seconds. The default window
|
|
1289
|
+
(`'10m'`) is no longer than the shortest default token lifetime; if you set a
|
|
1290
|
+
`tokens.*` lifetime shorter than `mail.throttle.window`, the last code can
|
|
1291
|
+
expire first, so keep the window no longer than the shortest you use — `janus()` warns for
|
|
1292
|
+
it, once per call, through `process.emitWarning` with the code
|
|
1293
|
+
`JANUS_THROTTLE_WINDOW` ([troubleshooting](docs/troubleshooting.md#janus-tokensflow-is-5m-shorter-than-mailthrottlewindow-10m-)). `janus`
|
|
1294
|
+
never sees IP addresses, so one client asking for many addresses is not
|
|
1295
|
+
counted: add a per-IP ceiling with `@nxgt/redis` rate limits
|
|
1296
|
+
(`defineRateLimit`, `bindRateLimit`; `enforce()` throws `GuardError`
|
|
1297
|
+
`RATE_LIMITED`, `retryAfter` in milliseconds —
|
|
1298
|
+
[example](docs/guide/email-flows.md#requests-that-send-e-mail-are-throttled)). A test suite that requests more than five of
|
|
1299
|
+
one flow for one address or user over a `fixedClock` is throttled: advance the
|
|
1300
|
+
clock past `retryAfter`, or wire `mail: { throttle: false }`. The counts live
|
|
1301
|
+
in the tokens store, so on PostgreSQL schedule the delete of lapsed tokens, a
|
|
1302
|
+
flushed or evicting Redis forgets them, and a tokens store that cannot count
|
|
1303
|
+
throws `STORE_FAILED` with nothing issued
|
|
1304
|
+
([e-mail flows](docs/guide/email-flows.md#requests-that-send-e-mail-are-throttled)).
|
|
1305
|
+
|
|
1252
1306
|
**A sign-in can move a user's `version`.** Rewriting a stale hash is a write. A
|
|
1253
1307
|
user object read before that sign-in, and then passed as `ifVersion`, gets
|
|
1254
1308
|
`VERSION_CONFLICT`. That is the conflict doing its job: read the user again.
|
|
@@ -1327,7 +1381,7 @@ that sends one, since it is awaited: queue the event and return.
|
|
|
1327
1381
|
|
|
1328
1382
|
## Type safety, counted
|
|
1329
1383
|
|
|
1330
|
-
**One hundred and
|
|
1384
|
+
**One hundred and fifty-two plausible mistakes, one hundred and fifty-two refused at compile time — and
|
|
1331
1385
|
two gaps, named.**
|
|
1332
1386
|
|
|
1333
1387
|
The lists are typechecked and never run, with one `@ts-expect-error` per
|
|
@@ -1335,9 +1389,9 @@ mistake beside the shapes that must keep compiling. One is a single file:
|
|
|
1335
1389
|
`test/types/refusals.ts` (fifteen, on the shared vocabulary). The other three
|
|
1336
1390
|
are folders with one file per behaviour: `test/types/port/` (twenty-four, on
|
|
1337
1391
|
the identity stores' port, from the point of view of the person implementing
|
|
1338
|
-
it), `test/types/auth/` (sixty, on `janus()`, from the point of view of
|
|
1392
|
+
it), `test/types/auth/` (sixty-five, on `janus()`, from the point of view of
|
|
1339
1393
|
the application — twelve of them on the second factor, three on sign-in codes,
|
|
1340
|
-
five on user events, four on step-ups, six on the sign-in throttle, four on
|
|
1394
|
+
five on user events, four on step-ups, six on the sign-in throttle, five on the mail throttle, four on
|
|
1341
1395
|
sign-in links, six on devices) and `test/types/permissions/` (forty-eight, on the
|
|
1342
1396
|
permission model and the questions asked of it). The rule comes from
|
|
1343
1397
|
`nxgt-data`, and so does the reason to distrust the claim without the files:
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Gathered here from the files beside this one.
|
|
10
10
|
*/
|
|
11
11
|
export type { PasswordHasher } from './hasher';
|
|
12
|
-
export type { CookieConfig, DevicesConfig, JanusConfig, MultiTypeConfig, SecondFactorConfig, SignInConfig, SignInThrottleConfig, SingleTypeConfig, } from './janus-config';
|
|
12
|
+
export type { CookieConfig, DevicesConfig, JanusConfig, MailConfig, MailThrottleConfig, MultiTypeConfig, SecondFactorConfig, SignInConfig, SignInThrottleConfig, SingleTypeConfig, } from './janus-config';
|
|
13
13
|
export { type Normalize, normalizeEmail } from './normalize';
|
|
14
14
|
export type { PasswordConfig } from './password-config';
|
|
15
15
|
export { RESERVED_FIELDS, RESERVED_TYPES, SINGLE_TYPE } from './reserved';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/config/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,YAAY,EACX,YAAY,EACZ,aAAa,EACb,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtE,YAAY,EACX,UAAU,EACV,aAAa,EACb,UAAU,EACV,cAAc,GACd,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/config/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,YAAY,EACX,YAAY,EACZ,aAAa,EACb,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtE,YAAY,EACX,UAAU,EACV,aAAa,EACb,UAAU,EACV,cAAc,GACd,MAAM,aAAa,CAAC"}
|
|
@@ -60,6 +60,15 @@ interface SharedConfig {
|
|
|
60
60
|
* until the next window. Nothing locks: the next window signs in.
|
|
61
61
|
*/
|
|
62
62
|
readonly signIn?: SignInConfig;
|
|
63
|
+
/**
|
|
64
|
+
* How the requests that hand out something to e-mail answer a loop. **On
|
|
65
|
+
* by default**: past five requests of one flow for one address — or one
|
|
66
|
+
* user, once signed in — in a 10-minute window, the request answers
|
|
67
|
+
* `MAIL_THROTTLED` with `retryAfter`, and issues nothing, until the next
|
|
68
|
+
* window. A refused request spends nothing: the last link or code sent
|
|
69
|
+
* still works.
|
|
70
|
+
*/
|
|
71
|
+
readonly mail?: MailConfig;
|
|
63
72
|
/**
|
|
64
73
|
* A TOTP second factor, for every user type with a password. Absent, no
|
|
65
74
|
* `secondFactor` flows exist and `signIn` answers a session directly.
|
|
@@ -98,6 +107,28 @@ export interface SignInThrottleConfig {
|
|
|
98
107
|
/** How long one window lasts. `'15m'` when absent. */
|
|
99
108
|
readonly window?: Duration;
|
|
100
109
|
}
|
|
110
|
+
/** What the requests that hand out something to e-mail do with a loop. */
|
|
111
|
+
export interface MailConfig {
|
|
112
|
+
/**
|
|
113
|
+
* The requests one address — or one user — may make per flow and per
|
|
114
|
+
* window: `magicLink.request`, `signInCode.request` and
|
|
115
|
+
* `resetPassword.request` per address, `verifyEmail.send` and an e-mailed
|
|
116
|
+
* `stepUp.request` per user. `{ attempts: 5, window: '10m' }` when absent;
|
|
117
|
+
* `false` counts nothing — rate-limit those requests yourself then.
|
|
118
|
+
*/
|
|
119
|
+
readonly throttle?: MailThrottleConfig | false;
|
|
120
|
+
}
|
|
121
|
+
/** How many requests of one flow one address or user may make, and per how long. */
|
|
122
|
+
export interface MailThrottleConfig {
|
|
123
|
+
/** Requests per flow, per address or user, and per window. `5` when absent. */
|
|
124
|
+
readonly attempts?: number;
|
|
125
|
+
/**
|
|
126
|
+
* How long one window lasts. `'10m'` when absent: no longer than the
|
|
127
|
+
* shortest default token lifetime, so the last link or code sent outlives
|
|
128
|
+
* the refusal. A window longer than a token's lifetime leaves a gap.
|
|
129
|
+
*/
|
|
130
|
+
readonly window?: Duration;
|
|
131
|
+
}
|
|
101
132
|
/** What a TOTP second factor needs: a name for the app, and the keys that seal. */
|
|
102
133
|
export interface SecondFactorConfig {
|
|
103
134
|
/** Shown in the authenticator app beside the account: your product's name. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"janus-config.d.ts","sourceRoot":"","sources":["../../../src/auth/config/janus-config.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"janus-config.d.ts","sourceRoot":"","sources":["../../../src/auth/config/janus-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-config.d.ts","sourceRoot":"","sources":["../../../src/auth/config/resolve-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACX,WAAW,EAGX,MAAM,gBAAgB,CAAC;AAQxB,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,mBAAmB,CAAC;AAGtE,qFAAqF;AACrF,wBAAgB,aAAa,CAC5B,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,GACX,cAAc,
|
|
1
|
+
{"version":3,"file":"resolve-config.d.ts","sourceRoot":"","sources":["../../../src/auth/config/resolve-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACX,WAAW,EAGX,MAAM,gBAAgB,CAAC;AAQxB,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,mBAAmB,CAAC;AAGtE,qFAAqF;AACrF,wBAAgB,aAAa,CAC5B,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,GACX,cAAc,CA0BhB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the two `{ throttle }` options, which take the same shape and
|
|
3
|
+
* differ in their defaults: `signIn.throttle`, ten passwords per login per
|
|
4
|
+
* fifteen minutes, and `mail.throttle`, five requests per flow, per address
|
|
5
|
+
* or user, per ten minutes. Each is on unless `false`.
|
|
6
|
+
*/
|
|
7
|
+
import { type Duration } from '../../time/duration';
|
|
8
|
+
import type { ResolvedConfig } from './resolved-config';
|
|
9
|
+
/** A throttle once resolved, or `null` when it is `false`. */
|
|
10
|
+
type ResolvedThrottle = ResolvedConfig['signInThrottle'];
|
|
11
|
+
/** What either option takes: `{ throttle }`, a limit or `false`. */
|
|
12
|
+
interface ThrottleOption {
|
|
13
|
+
readonly throttle?: {
|
|
14
|
+
readonly attempts?: number;
|
|
15
|
+
readonly window?: Duration;
|
|
16
|
+
} | false;
|
|
17
|
+
}
|
|
18
|
+
/** Resolves `signIn.throttle`: on unless `false`, ten passwords per login per fifteen minutes. */
|
|
19
|
+
export declare function resolveSignInThrottle(config: ThrottleOption | undefined, where: string): ResolvedThrottle;
|
|
20
|
+
/**
|
|
21
|
+
* Resolves `mail.throttle`: on unless `false`, five requests per flow, per
|
|
22
|
+
* address or user, per ten minutes — room for a visitor who asks again, a
|
|
23
|
+
* loop held to thirty e-mails an hour, and a window **no longer than the
|
|
24
|
+
* shortest default lifetime** (a sign-in code's and a step-up's, `'10m'`):
|
|
25
|
+
* the last link or code sent, issued in the window, still works until the
|
|
26
|
+
* refusal ends.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveMailThrottle(config: ThrottleOption | undefined, where: string): ResolvedThrottle;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=resolve-throttle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-throttle.d.ts","sourceRoot":"","sources":["../../../src/auth/config/resolve-throttle.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,QAAQ,EAAiB,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,8DAA8D;AAC9D,KAAK,gBAAgB,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAC;AAEzD,oEAAoE;AACpE,UAAU,cAAc;IACvB,QAAQ,CAAC,QAAQ,CAAC,EACf;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAA;KAAE,GAC1D,KAAK,CAAC;CACT;AASD,kGAAkG;AAClG,wBAAgB,qBAAqB,CACpC,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,KAAK,EAAE,MAAM,GACX,gBAAgB,CAMlB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,KAAK,EAAE,MAAM,GACX,gBAAgB,CAMlB"}
|
|
@@ -33,6 +33,11 @@ export interface ResolvedConfig {
|
|
|
33
33
|
readonly attempts: number;
|
|
34
34
|
readonly windowMs: number;
|
|
35
35
|
} | null;
|
|
36
|
+
/** `null` when `mail.throttle` is `false`. */
|
|
37
|
+
readonly mailThrottle: {
|
|
38
|
+
readonly attempts: number;
|
|
39
|
+
readonly windowMs: number;
|
|
40
|
+
} | null;
|
|
36
41
|
readonly secondFactor: {
|
|
37
42
|
readonly issuer: string;
|
|
38
43
|
readonly sealer: Sealer;
|
|
@@ -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;KACxB,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,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
|
+
{"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;KACxB,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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one wiring mistake the mail throttle cannot refuse: a `tokens.*`
|
|
3
|
+
* lifetime shorter than `mail.throttle.window`. A refused request spends
|
|
4
|
+
* nothing, so the last link or code sent keeps working, but only while it has
|
|
5
|
+
* not expired: with a shorter lifetime it can lapse before the refusal ends.
|
|
6
|
+
* That is a choice an application may make on purpose, so it is a warning,
|
|
7
|
+
* emitted once per `janus()` call, never an error.
|
|
8
|
+
*/
|
|
9
|
+
import type { ResolvedConfig } from './resolved-config';
|
|
10
|
+
/** The warning's text, or `null` when no lifetime is shorter than the window. */
|
|
11
|
+
export declare function throttleWindowMessage(resolved: Pick<ResolvedConfig, 'mailThrottle' | 'tokenTtlMs'>, where: string): string | null;
|
|
12
|
+
/** Emits {@link throttleWindowMessage} through `process.emitWarning`, where the runtime has one. */
|
|
13
|
+
export declare function warnThrottleWindow(resolved: Pick<ResolvedConfig, 'mailThrottle' | 'tokenTtlMs'>, where: string): void;
|
|
14
|
+
//# sourceMappingURL=warn-throttle-window.d.ts.map
|
|
@@ -0,0 +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;AAwBxD,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,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The key that names a count of attempts stored under no user — the
|
|
3
|
+
* passwords tried at a login (`sign-in-attempts.ts`), the e-mails asked for
|
|
4
|
+
* an address (`mail-requests.ts`) — and the keyed hashes made with it.
|
|
5
|
+
*
|
|
6
|
+
* Derived from the sealing keys when `secondFactor` is configured; without
|
|
7
|
+
* them it is a fixed one, and the hash only keeps the login or the address
|
|
8
|
+
* out of plain sight — safe because a `secondFactor` token is redeemed only
|
|
9
|
+
* by the second factor's flows, which do not exist without the keys.
|
|
10
|
+
*/
|
|
11
|
+
import type { Context } from './context';
|
|
12
|
+
/**
|
|
13
|
+
* The key `purpose` names its counts with. Renamed, a purpose's every count
|
|
14
|
+
* in progress would start over.
|
|
15
|
+
*/
|
|
16
|
+
export declare function counterKey(context: Context, purpose: string): Buffer;
|
|
17
|
+
/** A keyed hash of `parts`, base64url: a name, never a secret. */
|
|
18
|
+
export declare const keyed: (key: Buffer, parts: readonly string[]) => string;
|
|
19
|
+
//# sourceMappingURL=counter-key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"counter-key.d.ts","sourceRoot":"","sources":["../../src/auth/counter-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAMpE;AAED,kEAAkE;AAClE,eAAO,MAAM,KAAK,GAAI,KAAK,MAAM,EAAE,OAAO,SAAS,MAAM,EAAE,KAAG,MAClB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reset-password.d.ts","sourceRoot":"","sources":["../../../src/auth/email-flows/reset-password.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,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,EAOZ,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"reset-password.d.ts","sourceRoot":"","sources":["../../../src/auth/email-flows/reset-password.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,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,EAOZ,MAAM,YAAY,CAAC;AAMpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGjD,KAAK,aAAa,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC,eAAe,CAAC,CAAC;AAEhE;;;GAGG;AACH,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,EAAE,GACJ,aAAa,CA8Cf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify-email.d.ts","sourceRoot":"","sources":["../../../src/auth/email-flows/verify-email.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,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,EAKZ,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"verify-email.d.ts","sourceRoot":"","sources":["../../../src/auth/email-flows/verify-email.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,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,EAKZ,MAAM,YAAY,CAAC;AAIpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C,uFAAuF;AACvF,wBAAgB,gBAAgB,CAC/B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,EAAE,GACJ,cAAc,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,CAwCxC"}
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { CookieConfig, DevicesConfig, FieldsJson, JanusConfig, MultiTypeConfig, Normalize, PasswordConfig, PasswordHasher, SecondFactorConfig, SessionConfig, SignInConfig, SignInThrottleConfig, SingleTypeConfig, UserSchema, UserTypeConfig, } from './config';
|
|
1
|
+
export type { CookieConfig, DevicesConfig, FieldsJson, JanusConfig, MailConfig, MailThrottleConfig, MultiTypeConfig, Normalize, PasswordConfig, PasswordHasher, SecondFactorConfig, SessionConfig, SignInConfig, SignInThrottleConfig, SingleTypeConfig, UserSchema, UserTypeConfig, } from './config';
|
|
2
2
|
export type { UserEvent, UserEventListener, UserEventType, } from './events';
|
|
3
3
|
export { bunHasher, scryptHasher } from './hashers';
|
|
4
4
|
export { janus } from './janus';
|
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,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,YAAY,EACZ,UAAU,EACV,WAAW,EACX,KAAK,EACL,OAAO,EACP,YAAY,EACZ,WAAW,EACX,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,OAAO,EACP,OAAO,EACP,YAAY,EACZ,UAAU,EACV,WAAW,EACX,KAAK,EACL,OAAO,EACP,YAAY,EACZ,WAAW,EACX,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"}
|
package/dist/auth/janus.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"janus.d.ts","sourceRoot":"","sources":["../../src/auth/janus.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,WAAW,EAAiB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"janus.d.ts","sourceRoot":"","sources":["../../src/auth/janus.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,WAAW,EAAiB,MAAM,UAAU,CAAC;AAO3D,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAG9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,KAAK,CAAC,KAAK,CAAC,CAAC,SAAS,WAAW,EAChD,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACpB,KAAK,CAAC,CAAC,CAAC,CA2DV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"magic-link.d.ts","sourceRoot":"","sources":["../../src/auth/magic-link.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,WAAW,CAAC;AAG/D,OAAO,EACN,KAAK,MAAM,EAIX,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"magic-link.d.ts","sourceRoot":"","sources":["../../src/auth/magic-link.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,WAAW,CAAC;AAG/D,OAAO,EACN,KAAK,MAAM,EAIX,MAAM,iBAAiB,CAAC;AAGzB,OAAO,KAAK,EAAe,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC7B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,EAAE,EACN,MAAM,EAAE,MAAM,GACZ,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAY3D"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The requests that hand out something to e-mail, counted by the store per
|
|
3
|
+
* window — `janus({ mail: { throttle } })`, five per ten minutes by
|
|
4
|
+
* default. Past the last one, the request answers `MAIL_THROTTLED` with
|
|
5
|
+
* `retryAfter`, and **issues nothing**: no token is minted, so there is
|
|
6
|
+
* nothing to send — and **nothing is spent**: counted before anything is
|
|
7
|
+
* issued, a refused request never reaches the step that spends the earlier
|
|
8
|
+
* tokens, so the last link or code sent still works. Nothing locks past a
|
|
9
|
+
* window. With the default lifetimes, the window (`'10m'`) is no longer than
|
|
10
|
+
* any token's, so the last one sent — issued in the window — outlives the
|
|
11
|
+
* refusal: somebody who asks for an address in a loop mails its owner real
|
|
12
|
+
* links, and the last of them signs in.
|
|
13
|
+
*
|
|
14
|
+
* **Each flow counts on its own**, so a loop on one — a sign-in link asked
|
|
15
|
+
* for again and again — never shuts another, and what one address can be
|
|
16
|
+
* sent is bounded per flow:
|
|
17
|
+
*
|
|
18
|
+
* - **per address**, for the requests anybody can make with an e-mail —
|
|
19
|
+
* `magicLink.request`, `signInCode.request`, `resetPassword.request`.
|
|
20
|
+
* Counted **before anything is looked up**, the address normalised, and
|
|
21
|
+
* whatever the user type: an address nobody holds is counted, and refused
|
|
22
|
+
* past the limit, as a registered one is, so being throttled never tells
|
|
23
|
+
* who has an account;
|
|
24
|
+
* - **per user**, for the requests the application makes for a user it
|
|
25
|
+
* knows — `verifyEmail.send`, and `stepUp.request` when it e-mails a code.
|
|
26
|
+
* Nobody without the user's session or the application's call can spend
|
|
27
|
+
* that count, so a loop on their address leaves their own requests alone;
|
|
28
|
+
* and whatever addresses one user moves through, they are sent at most as
|
|
29
|
+
* many.
|
|
30
|
+
*
|
|
31
|
+
* Counted in an attempt window (`one-time/window.ts`), in `secondFactor`
|
|
32
|
+
* tokens stored under no user: the `userId` of each is a keyed hash of the
|
|
33
|
+
* flow and the address or the user (`counter-key.ts`). Nothing spends a
|
|
34
|
+
* link, and one that is spent carries its count on: the count never starts
|
|
35
|
+
* again before its window ends.
|
|
36
|
+
*
|
|
37
|
+
* A store that cannot count throws `STORE_FAILED`: never a refusal, and
|
|
38
|
+
* never a request let through uncounted.
|
|
39
|
+
*/
|
|
40
|
+
import { type ResolvedType } from './config';
|
|
41
|
+
import type { Context } from './context';
|
|
42
|
+
/** The flows that hand out something to e-mail, each counted on its own. */
|
|
43
|
+
export type MailFlow = 'magicLink' | 'signInCode' | 'resetPassword' | 'verifyEmail' | 'stepUp';
|
|
44
|
+
/**
|
|
45
|
+
* Counts one request of `flow` for `email` — before it is looked up — and
|
|
46
|
+
* refuses past the last one, whether anybody holds the address or not.
|
|
47
|
+
*/
|
|
48
|
+
export declare function countMailByAddress(context: Context, type: ResolvedType, flow: MailFlow, email: string, where: string): Promise<void>;
|
|
49
|
+
/** Counts one request of `flow` for the user `userId`, and refuses past the last one. */
|
|
50
|
+
export declare function countMailByUser(context: Context, type: ResolvedType, flow: MailFlow, userId: string, where: string): Promise<void>;
|
|
51
|
+
//# sourceMappingURL=mail-requests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-requests.d.ts","sourceRoot":"","sources":["../../src/auth/mail-requests.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;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,CAAC;AAKZ;;;GAGG;AACH,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAQf;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"}
|
|
@@ -14,12 +14,9 @@
|
|
|
14
14
|
*
|
|
15
15
|
* Counted in an attempt window (`one-time/window.ts`), in `secondFactor`
|
|
16
16
|
* tokens stored under no user: the `userId` of each is a keyed hash of the
|
|
17
|
-
* login, never the login
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* token is redeemed only by the second factor's flows, which do not exist
|
|
21
|
-
* without the keys. A sign-in that opens a session spends the link it
|
|
22
|
-
* counts on, and the login's count **restarts** from zero.
|
|
17
|
+
* login, never the login (`counter-key.ts`). A sign-in that opens a session
|
|
18
|
+
* spends the link it counts on, and the login's count **restarts** from
|
|
19
|
+
* zero.
|
|
23
20
|
*
|
|
24
21
|
* A store that cannot count throws `STORE_FAILED`: never a refusal, and
|
|
25
22
|
* never a sign-in let through uncounted.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sign-in-attempts.d.ts","sourceRoot":"","sources":["../../src/auth/sign-in-attempts.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sign-in-attempts.d.ts","sourceRoot":"","sources":["../../src/auth/sign-in-attempts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAgC/C;;;GAGG;AACH,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAWf"}
|
|
@@ -13,8 +13,9 @@ import type { SignInCodeApi, SignInResult } from './types';
|
|
|
13
13
|
* spends the challenge. **At most one code is live per user**: `request`
|
|
14
14
|
* spends every other once it issued its own, so concurrent requests cannot
|
|
15
15
|
* each keep one. Yet anybody who knows an e-mail can ask for another — and
|
|
16
|
-
* each request cancels the code before — so
|
|
17
|
-
* `
|
|
16
|
+
* each request cancels the code before — so `request` is counted per
|
|
17
|
+
* address (`mail-requests.ts`), and the application rate-limits it per
|
|
18
|
+
* client. The code's hash is keyed by the challenge, so the
|
|
18
19
|
* tokens alone do not reveal it.
|
|
19
20
|
*/
|
|
20
21
|
export declare function signInCodeFlows(context: Context, type: ResolvedType, at: At, finish: Finish): SignInCodeApi<AnyUser, SignInResult<AnyUser>>['signInCode'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sign-in-code.d.ts","sourceRoot":"","sources":["../../src/auth/sign-in-code.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,WAAW,CAAC;AAE3E,OAAO,EACN,KAAK,MAAM,EAIX,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"sign-in-code.d.ts","sourceRoot":"","sources":["../../src/auth/sign-in-code.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,WAAW,CAAC;AAE3E,OAAO,EACN,KAAK,MAAM,EAIX,MAAM,iBAAiB,CAAC;AAYzB,OAAO,KAAK,EAEX,aAAa,EAEb,YAAY,EACZ,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,EAAE,EACN,MAAM,EAAE,MAAM,GACZ,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAqB7D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/auth/step-up/request.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAKZ,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/auth/step-up/request.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAKZ,MAAM,YAAY,CAAC;AAMpB,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEpE,wEAAwE;AACxE,MAAM,MAAM,YAAY,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;AAEzE,sEAAsE;AACtE,wBAAsB,aAAa,CAClC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,CAAC,CAqBvB"}
|
|
@@ -43,10 +43,12 @@ export interface SignInCodeApi<U, Answer = SignedIn<U>> {
|
|
|
43
43
|
* the visitor which**: answer the same page either way, and in the same
|
|
44
44
|
* time — send the e-mail off the request's path.
|
|
45
45
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
46
|
+
* Every call issues a new challenge with five attempts of its own, and
|
|
47
|
+
* spends the earlier ones: only the last code sent works, and a new
|
|
48
|
+
* `request` is five guesses more. **Throttled per address**, whether
|
|
49
|
+
* anybody holds it or not: past five requests in 10 minutes
|
|
50
|
+
* (`janus({ mail: { throttle } })`), `MAIL_THROTTLED` with
|
|
51
|
+
* `retryAfter`, and no code. Rate-limit it per client too.
|
|
50
52
|
*/
|
|
51
53
|
request(email: string): Promise<IssuedCode<U> | null>;
|
|
52
54
|
/**
|
|
@@ -68,7 +70,12 @@ export interface SignInCodeApi<U, Answer = SignedIn<U>> {
|
|
|
68
70
|
/** What a user type with an e-mail answers besides. */
|
|
69
71
|
export interface VerifyEmailApi<U> {
|
|
70
72
|
readonly verifyEmail: {
|
|
71
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* Issues a token for the user's current e-mail. Sending it is yours.
|
|
75
|
+
* **Throttled per user**: past five in 10 minutes
|
|
76
|
+
* (`janus({ mail: { throttle } })`), `MAIL_THROTTLED` with
|
|
77
|
+
* `retryAfter`, and no token.
|
|
78
|
+
*/
|
|
72
79
|
send(user: UserRef): Promise<IssuedToken>;
|
|
73
80
|
/**
|
|
74
81
|
* Redeems a token and marks the e-mail verified. A token sent to an
|
|
@@ -84,7 +91,10 @@ export interface ResetPasswordApi<U> {
|
|
|
84
91
|
* Issues a reset token for the user of this type holding this e-mail, or
|
|
85
92
|
* answers `null` when there is none. **Never tell the visitor which**:
|
|
86
93
|
* answer the same page either way. The user's earlier reset tokens are
|
|
87
|
-
* spent: only the last one sent works.
|
|
94
|
+
* spent: only the last one sent works. **Throttled per address**,
|
|
95
|
+
* whether anybody holds it or not: past five requests in 10 minutes
|
|
96
|
+
* (`janus({ mail: { throttle } })`), `MAIL_THROTTLED` with
|
|
97
|
+
* `retryAfter`, and no token.
|
|
88
98
|
*/
|
|
89
99
|
request(email: string): Promise<(IssuedToken & {
|
|
90
100
|
readonly user: U;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email-flows.d.ts","sourceRoot":"","sources":["../../../src/auth/types/email-flows.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAgB,MAAM,WAAW,CAAC;AACvE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CACzB;AAED,oFAAoF;AACpF,MAAM,WAAW,UAAU,CAAC,CAAC;IAC5B,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uCAAuC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;CACjB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,UAAU,EAAE;QACpB
|
|
1
|
+
{"version":3,"file":"email-flows.d.ts","sourceRoot":"","sources":["../../../src/auth/types/email-flows.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAgB,MAAM,WAAW,CAAC;AACvE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CACzB;AAED,oFAAoF;AACpF,MAAM,WAAW,UAAU,CAAC,CAAC;IAC5B,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uCAAuC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;CACjB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,UAAU,EAAE;QACpB;;;;;;;;;;;;WAYG;QACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACtD;;;;;;;;;;;;WAYG;QACH,OAAO,CACN,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,CAAC,CAAC;KACnB,CAAC;CACF;AAED,uDAAuD;AACvD,MAAM,WAAW,cAAc,CAAC,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE;QACrB;;;;;WAKG;QACH,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QAC1C;;;WAGG;QACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;KACnC,CAAC;CACF;AAED,sEAAsE;AACtE,MAAM,WAAW,gBAAgB,CAAC,CAAC;IAClC,QAAQ,CAAC,aAAa,EAAE;QACvB;;;;;;;;WAQG;QACH,OAAO,CACN,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,CAAC,WAAW,GAAG;YAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;SAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QACxD;;;;;;WAMG;QACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;KACrD,CAAC;CACF"}
|
|
@@ -23,8 +23,10 @@ export interface MagicLinkApi<U, Answer = SignedIn<U>> {
|
|
|
23
23
|
*
|
|
24
24
|
* Put `token` in a link to a page of yours, and **only in the e-mail**.
|
|
25
25
|
* The user's earlier links are spent: only the last one sent works.
|
|
26
|
-
* **
|
|
27
|
-
*
|
|
26
|
+
* **Throttled per address**, whether anybody holds it or not: past
|
|
27
|
+
* five requests in 10 minutes (`janus({ mail: { throttle } })`),
|
|
28
|
+
* `MAIL_THROTTLED` with `retryAfter`, and no token. Rate-limit it per
|
|
29
|
+
* client too: one client can ask for many addresses.
|
|
28
30
|
*/
|
|
29
31
|
request(email: string): Promise<(IssuedToken & {
|
|
30
32
|
readonly user: U;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"magic-link.d.ts","sourceRoot":"","sources":["../../../src/auth/types/magic-link.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,SAAS,EAAE;QACnB
|
|
1
|
+
{"version":3,"file":"magic-link.d.ts","sourceRoot":"","sources":["../../../src/auth/types/magic-link.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,SAAS,EAAE;QACnB;;;;;;;;;;;;WAYG;QACH,OAAO,CACN,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,CAAC,WAAW,GAAG;YAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;SAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QACxD;;;;;;;;;;;;;;WAcG;QACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;KACjE,CAAC;CACF"}
|
|
@@ -53,7 +53,10 @@ export interface StepUpApi<U, Issued = StepUpByEmail<U>> {
|
|
|
53
53
|
* step-up is live per user**: the ones issued before stop working.
|
|
54
54
|
*
|
|
55
55
|
* `NOT_FOUND` for no such user of this type, or one with no e-mail;
|
|
56
|
-
* `USER_INACTIVE` for an inactive one.
|
|
56
|
+
* `USER_INACTIVE` for an inactive one. A code to e-mail is **throttled
|
|
57
|
+
* per user**: past five in 10 minutes (`janus({ mail: { throttle } })`),
|
|
58
|
+
* `MAIL_THROTTLED` with `retryAfter`, and no challenge. A challenge for
|
|
59
|
+
* the app sends nothing, and is not counted.
|
|
57
60
|
*/
|
|
58
61
|
request(user: UserRef): Promise<Issued>;
|
|
59
62
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"step-up.d.ts","sourceRoot":"","sources":["../../../src/auth/types/step-up.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,mFAAmF;AACnF,MAAM,WAAW,aAAa,CAAC,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uCAAuC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;IACtD,QAAQ,CAAC,MAAM,EAAE;QAChB
|
|
1
|
+
{"version":3,"file":"step-up.d.ts","sourceRoot":"","sources":["../../../src/auth/types/step-up.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,mFAAmF;AACnF,MAAM,WAAW,aAAa,CAAC,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uCAAuC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;IACtD,QAAQ,CAAC,MAAM,EAAE;QAChB;;;;;;;;;;;WAWG;QACH,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QACxC;;;;;;;;;;;;;;;;WAgBG;QACH,OAAO,CACN,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACV,OAAO,CAAC,OAAO,CAAC,CAAC;KACpB,CAAC;CACF"}
|