@nxgt/janus 0.4.0 → 0.6.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 +159 -20
- package/dist/auth/config.d.ts +28 -1
- package/dist/auth/config.d.ts.map +1 -1
- package/dist/auth/context.d.ts +6 -0
- package/dist/auth/context.d.ts.map +1 -1
- package/dist/auth/index.d.ts +3 -2
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/one-time.d.ts +92 -0
- package/dist/auth/one-time.d.ts.map +1 -0
- package/dist/auth/port/types.d.ts +10 -7
- package/dist/auth/port/types.d.ts.map +1 -1
- package/dist/auth/sealing.d.ts +39 -0
- package/dist/auth/sealing.d.ts.map +1 -0
- package/dist/auth/second-factor/challenge.d.ts +14 -0
- package/dist/auth/second-factor/challenge.d.ts.map +1 -0
- package/dist/auth/second-factor/factor.d.ts +27 -0
- package/dist/auth/second-factor/factor.d.ts.map +1 -0
- package/dist/auth/second-factor/flows.d.ts +23 -0
- package/dist/auth/second-factor/flows.d.ts.map +1 -0
- package/dist/auth/second-factor/lifecycle.d.ts +8 -0
- package/dist/auth/second-factor/lifecycle.d.ts.map +1 -0
- package/dist/auth/sessions.d.ts.map +1 -1
- package/dist/auth/sign-in-code.d.ts +17 -0
- package/dist/auth/sign-in-code.d.ts.map +1 -0
- package/dist/auth/totp.d.ts +36 -0
- package/dist/auth/totp.d.ts.map +1 -0
- package/dist/auth/types.d.ts +140 -7
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/auth/users.d.ts +2 -2
- package/dist/auth/users.d.ts.map +1 -1
- package/dist/chunks/{index-qwfkhqkk.js → index-06vp9c5r.js} +12 -3
- package/dist/chunks/{index-qwfkhqkk.js.map → index-06vp9c5r.js.map} +3 -3
- package/dist/chunks/{index-53y1afjz.js → index-5vr13kkb.js} +2 -2
- package/dist/chunks/{index-mgh85djb.js → index-c4v27jfr.js} +2 -2
- package/dist/chunks/{index-thtyq7a9.js → index-gbwn2tts.js} +2 -2
- package/dist/conformance/cases/tokens.d.ts.map +1 -1
- package/dist/conformance/index.js +15 -4
- package/dist/conformance/index.js.map +3 -3
- package/dist/errors/janus-error.d.ts +28 -2
- package/dist/errors/janus-error.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +478 -51
- package/dist/index.js.map +15 -7
- package/dist/permissions/index.js +3 -3
- package/docs/README.md +2 -0
- package/docs/guide/adapters.md +12 -7
- package/docs/guide/email-flows.md +4 -0
- package/docs/guide/errors.md +19 -7
- package/docs/guide/second-factor.md +571 -0
- package/docs/guide/sessions.md +18 -0
- package/docs/guide/sign-in-code.md +471 -0
- package/docs/guide/users.md +10 -3
- package/docs/guide/vocabulary.md +9 -6
- package/docs/roadmap.md +39 -54
- package/docs/troubleshooting.md +414 -5
- package/package.json +1 -1
- /package/dist/chunks/{index-53y1afjz.js.map → index-5vr13kkb.js.map} +0 -0
- /package/dist/chunks/{index-mgh85djb.js.map → index-c4v27jfr.js.map} +0 -0
- /package/dist/chunks/{index-thtyq7a9.js.map → index-gbwn2tts.js.map} +0 -0
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ a published entry point is a promise.
|
|
|
46
46
|
## Three ways to use it
|
|
47
47
|
|
|
48
48
|
Janus has two sides. **Identities** answers *who is this?* — users, their
|
|
49
|
-
logins and passwords, sessions, one-time tokens. **Permissions** answers *may
|
|
49
|
+
logins and passwords, codes sent by e-mail, a TOTP second factor, sessions, one-time tokens. **Permissions** answers *may
|
|
50
50
|
they?* — a model, the tuples stored against it, and `can`. Each side is usable
|
|
51
51
|
alone, and neither loads the other's code: a spec reads the import graph of
|
|
52
52
|
each entry point and fails if one reaches into the other.
|
|
@@ -165,7 +165,7 @@ 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
|
|
168
|
+
so no consumer has to order their `catch` blocks. `code` is a union of nineteen
|
|
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:
|
|
171
171
|
|
|
@@ -177,6 +177,8 @@ compilation of callers that exhaust it:
|
|
|
177
177
|
| `USER_INVALID` | 400, field by field from `issues` |
|
|
178
178
|
| `PASSWORD_TOO_SHORT`, `HASH_UNSUPPORTED` | 400 |
|
|
179
179
|
| `CREDENTIALS_INVALID` | 401 — one code for an unknown login, no password and a wrong one |
|
|
180
|
+
| `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 |
|
|
181
|
+
| `SECOND_FACTOR_NOT_ENROLLED`, `SECOND_FACTOR_ACTIVE` | 409 — the factor is not in the state the call needs |
|
|
180
182
|
| `USER_INACTIVE` | 403 |
|
|
181
183
|
| `TOKEN_UNKNOWN`, `TOKEN_SPENT`, `TOKEN_EXPIRED`, `TOKEN_STALE` | 400 |
|
|
182
184
|
| `INVALID_CURSOR` | 400 |
|
|
@@ -185,13 +187,15 @@ compilation of callers that exhaust it:
|
|
|
185
187
|
|
|
186
188
|
Each code has its class, all exported: `StoreFailure`, `StoreConflict` (`on:
|
|
187
189
|
'login' | 'version'`), `NotFoundError`, `UserInvalidError`, `CredentialError`,
|
|
188
|
-
`UserInactiveError`, `TokenError
|
|
189
|
-
|
|
190
|
+
`UserInactiveError`, `TokenError` (the `TOKEN_*` codes and `CODE_INVALID`),
|
|
191
|
+
`SecondFactorError`, `InvalidCursorError`, `UnsupportedError` and
|
|
192
|
+
`PermissionDepthError`. `StoreFailure` and `StoreConflict` are exported
|
|
190
193
|
**because an adapter throws them**. An adapter defines no error class of its own, so `instanceof` holds
|
|
191
194
|
across the two packages.
|
|
192
195
|
|
|
193
196
|
**No message ever holds a secret** — not a password, not a hash, not a session
|
|
194
|
-
token, not a token's hash,
|
|
197
|
+
token, not a token's hash, not a challenge, a code or a TOTP secret, and not a
|
|
198
|
+
connection URI, because a connection string
|
|
195
199
|
holds a password. Nor a login: a message reports a shape, never a value, so
|
|
196
200
|
`LOGIN_TAKEN` names the login in `error.login`, not in its message.
|
|
197
201
|
|
|
@@ -299,14 +303,16 @@ const auth = janus({
|
|
|
299
303
|
hasher: scryptHasher(),
|
|
300
304
|
});
|
|
301
305
|
|
|
302
|
-
await auth.signUp({ email, name, password }); // { user, session, token }
|
|
303
|
-
await auth.signIn({ email, password }); // { user, session, token }
|
|
306
|
+
await auth.signUp({ email, name, password }); // { status: 'signedIn', user, session, token }
|
|
307
|
+
await auth.signIn({ email, password }); // { status: 'signedIn', user, session, token }
|
|
304
308
|
await auth.authenticate(request); // { user, session, token, renewed } | null
|
|
305
309
|
await auth.signOut(request);
|
|
306
310
|
await auth.verifyEmail.send(user); // { token, email, expiresAt } — sending it is yours
|
|
307
311
|
await auth.verifyEmail.confirm(token);
|
|
308
312
|
await auth.resetPassword.request(email); // … | null
|
|
309
313
|
await auth.resetPassword.confirm(token, newPassword);
|
|
314
|
+
await auth.signInCode.request(email); // { code, challenge, email, expiresAt, user } | null
|
|
315
|
+
await auth.signInCode.confirm(challenge, code); // { status: 'signedIn', user, session, token }
|
|
310
316
|
|
|
311
317
|
// Several user types
|
|
312
318
|
const clinic = janus({
|
|
@@ -333,8 +339,8 @@ store answers every method of the port, and connects to nothing. Everything
|
|
|
333
339
|
else reaches the store and is asynchronous.
|
|
334
340
|
|
|
335
341
|
- **A user is your schema's fields, at the top level**, plus what `janus` sets:
|
|
336
|
-
`id`, `type`, `emailVerified`, `active`, `hasPassword`, `
|
|
337
|
-
`createdAt`, `updatedAt`. A schema declaring one of those, or a `password`, is
|
|
342
|
+
`id`, `type`, `emailVerified`, `active`, `hasPassword`, `hasSecondFactor`,
|
|
343
|
+
`version`, `createdAt`, `updatedAt`. A schema declaring one of those, or a `password`, is
|
|
338
344
|
refused at compile time. The password hash never reaches a user.
|
|
339
345
|
- **Schemas** are any [Standard Schema](https://standardschema.dev) — Zod 4,
|
|
340
346
|
Valibot, ArkType. There is no validation peer. The output must be JSON, and a
|
|
@@ -347,8 +353,9 @@ else reaches the store and is asynchronous.
|
|
|
347
353
|
compile error on `login`, and the message lists the fields you could have
|
|
348
354
|
meant. It is normalised with `'lowercaseTrim'` unless you say otherwise.
|
|
349
355
|
- **`email`** defaults to the field named `email`. A type without one has no
|
|
350
|
-
`verifyEmail` and no `
|
|
351
|
-
failing at run time. Changing the e-mail sets `emailVerified`
|
|
356
|
+
`verifyEmail`, no `resetPassword` and no `signInCode` — they are absent from
|
|
357
|
+
its type, not failing at run time. Changing the e-mail sets `emailVerified`
|
|
358
|
+
back to `false`.
|
|
352
359
|
- **Per type**: `create`, `find` (or `null`), `get` (or `NOT_FOUND`), `list`,
|
|
353
360
|
`update(user, patch)` — merged over the stored fields, then validated whole —
|
|
354
361
|
`setActive` and `delete`; with a password, `signUp`, `signIn`, `findByLogin`,
|
|
@@ -396,11 +403,10 @@ adapter. `assertStores(store, where)` is the check `janus()` runs on it, for an
|
|
|
396
403
|
adapter that wants to fail as early. The six rules an adapter keeps are
|
|
397
404
|
written on the port's types.
|
|
398
405
|
|
|
399
|
-
The port
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
conditional write:
|
|
406
|
+
The port holds what one-time codes need: a user's `secondFactor` (a TOTP
|
|
407
|
+
secret the core seals before a store sees it, or `null`), a token's
|
|
408
|
+
`codeHash` and `attempts`, and `TokenStore.countAttempt`, which counts one
|
|
409
|
+
attempt in one conditional write:
|
|
404
410
|
|
|
405
411
|
```ts
|
|
406
412
|
import { createMemoryStores, mintId } from '@nxgt/janus';
|
|
@@ -428,6 +434,104 @@ port until it implements `countAttempt`, and `janus()` refuses it at wiring —
|
|
|
428
434
|
[Writing an adapter](docs/guide/adapters.md#tokenstorecountattempt) has the
|
|
429
435
|
contract.
|
|
430
436
|
|
|
437
|
+
### Second factor — `secondFactor`
|
|
438
|
+
|
|
439
|
+
```ts
|
|
440
|
+
import { z } from 'zod';
|
|
441
|
+
import { createMemoryStores, janus, scryptHasher } from '@nxgt/janus';
|
|
442
|
+
|
|
443
|
+
const auth = janus({
|
|
444
|
+
user: z.object({ email: z.email() }),
|
|
445
|
+
password: { login: 'email' },
|
|
446
|
+
store: createMemoryStores(),
|
|
447
|
+
hasher: scryptHasher(),
|
|
448
|
+
secondFactor: {
|
|
449
|
+
issuer: 'Example', // shown in the authenticator app
|
|
450
|
+
keys: [{ id: '2026-09', key: process.env.TOTP_KEY ?? '' }], // openssl rand -base64 32
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
const { secret, uri } = await auth.secondFactor.enroll(user); // show uri as a QR code, secret beside it
|
|
455
|
+
await auth.secondFactor.activate(user, code); // the first code: the factor is active
|
|
456
|
+
|
|
457
|
+
const result = await auth.signIn({ email, password });
|
|
458
|
+
if (result.status === 'secondFactor') {
|
|
459
|
+
// no session yet: keep result.challenge for the next request — never in a URL or a log
|
|
460
|
+
const signedIn = await auth.secondFactor.confirm(result.challenge, code); // { status: 'signedIn', … }
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
await auth.secondFactor.disable(user);
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
A TOTP second factor — the six-digit codes of any authenticator app — for
|
|
467
|
+
every user type with a password.
|
|
468
|
+
|
|
469
|
+
- **`signIn` answers a union once `secondFactor` is configured**:
|
|
470
|
+
`{ status: 'signedIn', user, session, token }`, or
|
|
471
|
+
`{ status: 'secondFactor', challenge, expiresAt }` for a user whose factor
|
|
472
|
+
is active. Switch on `status`: reading `token` before that is a compile
|
|
473
|
+
error. Without `secondFactor`, `signIn` answers a session, as before.
|
|
474
|
+
- **A factor is enrolled, then active.** `enroll` answers the secret and its
|
|
475
|
+
`otpauth://` URI once; enrolling again replaces a factor still waiting.
|
|
476
|
+
`activate` checks a first code, and only then does `signIn` ask for one —
|
|
477
|
+
`hasSecondFactor` says so.
|
|
478
|
+
- **`confirm(challenge, code)`** opens the session. A challenge lives `'5m'`
|
|
479
|
+
(`secondFactor.challenge`) and takes five attempts: a wrong code is
|
|
480
|
+
`CODE_INVALID` with `attemptsLeft`, and the fifth spends the challenge. A
|
|
481
|
+
code is accepted once, so a replay is `CODE_INVALID` too.
|
|
482
|
+
- **`keys` seal every TOTP secret** with AES-256-GCM before a store sees it.
|
|
483
|
+
The first seals and every key opens, so keys rotate: put the new one first,
|
|
484
|
+
keep the old one until no secret is sealed with it.
|
|
485
|
+
- **Asking for a password or a code before `enroll` or `disable` is your
|
|
486
|
+
policy**, not the library's — a recent `session.authenticatedAt` is one
|
|
487
|
+
rule.
|
|
488
|
+
|
|
489
|
+
[The second factor guide](docs/guide/second-factor.md) has every option,
|
|
490
|
+
error and state, key rotation, and a sign-in route with the challenge in a
|
|
491
|
+
cookie.
|
|
492
|
+
|
|
493
|
+
### Sign-in codes — `signInCode`
|
|
494
|
+
|
|
495
|
+
```ts
|
|
496
|
+
import { z } from 'zod';
|
|
497
|
+
import { createMemoryStores, janus } from '@nxgt/janus';
|
|
498
|
+
|
|
499
|
+
const auth = janus({
|
|
500
|
+
user: z.object({ email: z.email(), name: z.string() }), // no password: codes only
|
|
501
|
+
store: createMemoryStores(),
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
const issued = await auth.signInCode.request(email); // null for nobody, or an inactive user
|
|
505
|
+
if (issued !== null) {
|
|
506
|
+
await sendMail(issued.email, `Your sign-in code: ${issued.code}`); // the code, and only the code
|
|
507
|
+
}
|
|
508
|
+
// answer the same page either way; keep issued.challenge with the visitor — a cookie, never a URL
|
|
509
|
+
|
|
510
|
+
const signedIn = await auth.signInCode.confirm(challenge, code); // { status: 'signedIn', user, session, token }
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
A six-digit code sent to the user's e-mail signs them in, with no password.
|
|
514
|
+
|
|
515
|
+
- **On every user type with an e-mail**, with a password or without one. A
|
|
516
|
+
type with no password signs in by code alone; a type with no e-mail has no
|
|
517
|
+
`signInCode` at all.
|
|
518
|
+
- **`request(email)` answers `null`** when nobody of this type holds that
|
|
519
|
+
e-mail, or the user is inactive — never say which. It answers the `code`
|
|
520
|
+
for the e-mail and the `challenge` for the visitor; the code's hash is
|
|
521
|
+
stored, keyed by the challenge.
|
|
522
|
+
- **`confirm(challenge, code)`** marks the e-mail verified and opens the
|
|
523
|
+
session. A challenge lives `'10m'` (`tokens.signInCode`) and takes five
|
|
524
|
+
attempts: a wrong code is `CODE_INVALID` with `attemptsLeft`, and the fifth
|
|
525
|
+
spends it. An e-mail changed since is `TOKEN_STALE`; a user deactivated
|
|
526
|
+
since is `USER_INACTIVE`.
|
|
527
|
+
- **An active second factor is still asked for**: with `secondFactor`
|
|
528
|
+
configured, `confirm` answers `SignInResult` on a type with a password, and
|
|
529
|
+
a user whose factor is active gets a challenge for `secondFactor.confirm`
|
|
530
|
+
— switch on `status`, as after `signIn`.
|
|
531
|
+
|
|
532
|
+
[The sign-in code guide](docs/guide/sign-in-code.md) has the request that
|
|
533
|
+
tells nobody who exists, the challenge in a cookie, every error, and a test.
|
|
534
|
+
|
|
431
535
|
### Permissions — `@nxgt/janus/permissions`
|
|
432
536
|
|
|
433
537
|
```ts
|
|
@@ -538,7 +642,7 @@ describeJanusStores({
|
|
|
538
642
|
});
|
|
539
643
|
```
|
|
540
644
|
|
|
541
|
-
There are
|
|
645
|
+
There are 45 cases. They cover:
|
|
542
646
|
- round-trip, byte for byte — including every edge character the core lets
|
|
543
647
|
through (control characters, U+FFFF, a surrogate pair);
|
|
544
648
|
- uniqueness, as a constraint: of twenty concurrent inserts of one login,
|
|
@@ -551,6 +655,7 @@ There are 44 cases. They cover:
|
|
|
551
655
|
- one-time tokens: of twenty concurrent redemptions, exactly one succeeds;
|
|
552
656
|
of twenty concurrent `countAttempt` calls, each answers a distinct count,
|
|
553
657
|
and none is counted once a racing redemption spent the token;
|
|
658
|
+
- a second-factor challenge, whose address is `''`, kept, counted and spent;
|
|
554
659
|
- a user's second factor: round-trip, kept by a patch that does not name it,
|
|
555
660
|
removed by one that names `null`;
|
|
556
661
|
- deletion: a user's logins are freed, and every session and token of theirs
|
|
@@ -587,6 +692,39 @@ example; `allRelationCases`, `relationStoreCases`, `relationOutageCases` and
|
|
|
587
692
|
|
|
588
693
|
## Traps
|
|
589
694
|
|
|
695
|
+
**Once `secondFactor` is configured, switch on `signIn`'s `status`** — and
|
|
696
|
+
on `signInCode.confirm`'s. A user whose factor is active gets
|
|
697
|
+
`{ status: 'secondFactor', challenge }`, with no `token` and no `session`: an
|
|
698
|
+
e-mailed code proves the e-mail, not the factor.
|
|
699
|
+
`if (result.status === 'secondFactor') …` before anything reads them.
|
|
700
|
+
|
|
701
|
+
**A challenge is a secret, like a session token** — `signIn`'s and
|
|
702
|
+
`signInCode.request`'s alike. Keep it in a short-lived `HttpOnly` cookie or
|
|
703
|
+
the body of the code form — never in the e-mail, never in a URL, where logs,
|
|
704
|
+
proxies and the `Referer` header see it, and never in a log. The e-mail holds
|
|
705
|
+
the code and nothing else.
|
|
706
|
+
|
|
707
|
+
**Answer `signInCode.request` the same whether it issued a code or not** —
|
|
708
|
+
the same status, body and cookie: set a random challenge when it answered
|
|
709
|
+
`null`. The code route then still tells a decoy (`TOKEN_UNKNOWN`) from a
|
|
710
|
+
real challenge (`CODE_INVALID`, `attemptsLeft`): answer its refusals alike
|
|
711
|
+
where addresses must stay secret. And rate-limit the request: `janus` issues
|
|
712
|
+
a new code on every call, so without a limit anyone can fill a user's inbox.
|
|
713
|
+
|
|
714
|
+
**Every `janus()` that signs users in needs the same `secondFactor`.** An
|
|
715
|
+
instance without keys never signs in a user whose factor is active: `signIn`
|
|
716
|
+
throws a `TypeError` rather than open a session on the password alone. Build
|
|
717
|
+
the configuration once and import it everywhere.
|
|
718
|
+
|
|
719
|
+
**Never remove a sealing key while a secret is sealed with it, nor change a
|
|
720
|
+
key under the same id.** That user's next sign-in is a `TypeError`, not a
|
|
721
|
+
refusal. Put the new key first and keep the old one until your database holds
|
|
722
|
+
no secret starting `v1.<old id>.`.
|
|
723
|
+
|
|
724
|
+
**`enroll` and `disable` ask for nothing.** Whether the user proves their
|
|
725
|
+
password or a code first is yours to decide; without a check, a stolen
|
|
726
|
+
session can switch the factor off.
|
|
727
|
+
|
|
590
728
|
**On a user type, only `setOf` makes a set.** A user passed as it is — or
|
|
591
729
|
`{ type: 'staff', id, relation: 'managers' }` written out — is that one user,
|
|
592
730
|
even with a field named `relation`. The compiler refuses the written-out set
|
|
@@ -691,15 +829,16 @@ could not answer: that is a denial made of an outage.
|
|
|
691
829
|
|
|
692
830
|
## Type safety, counted
|
|
693
831
|
|
|
694
|
-
**One hundred and
|
|
832
|
+
**One hundred and fourteen plausible mistakes, one hundred and fourteen refused at compile time — and
|
|
695
833
|
two gaps, named.**
|
|
696
834
|
|
|
697
835
|
The lists are typechecked and never run, with one `@ts-expect-error` per
|
|
698
836
|
mistake beside the shapes that must keep compiling:
|
|
699
837
|
`test/types/refusals.ts` (fourteen, on the shared vocabulary),
|
|
700
838
|
`test/types/port.ts` (twenty-one, on the identity stores' port, from the point
|
|
701
|
-
of view of the person implementing it), `test/types/auth.ts` (
|
|
702
|
-
`janus()`, from the point of view of the application
|
|
839
|
+
of view of the person implementing it), `test/types/auth.ts` (thirty-one, on
|
|
840
|
+
`janus()`, from the point of view of the application — eight of them on the
|
|
841
|
+
second factor, three on sign-in codes) and `test/types/permissions.ts` (forty-eight, on the
|
|
703
842
|
permission model and the questions asked of it). The rule
|
|
704
843
|
comes from `nxgt-data`, and so does the reason to
|
|
705
844
|
distrust the claim without the files: when it was last measured on
|
package/dist/auth/config.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type { RelationStore } from '../permissions/port/types';
|
|
|
10
10
|
import type { Clock } from '../time/clock';
|
|
11
11
|
import { type Duration } from '../time/duration';
|
|
12
12
|
import type { JanusStores } from './port/types';
|
|
13
|
+
import { type Sealer, type SealingKey } from './sealing';
|
|
13
14
|
import type { StandardSchemaV1 } from './standard-schema';
|
|
14
15
|
/**
|
|
15
16
|
* How a login is normalised before any store sees it. `'lowercaseTrim'` when
|
|
@@ -136,7 +137,27 @@ interface SharedConfig {
|
|
|
136
137
|
readonly verifyEmail?: Duration;
|
|
137
138
|
/** `'1h'` when absent. */
|
|
138
139
|
readonly resetPassword?: Duration;
|
|
140
|
+
/** How long an e-mailed sign-in code waits. `'10m'` when absent. */
|
|
141
|
+
readonly signInCode?: Duration;
|
|
139
142
|
};
|
|
143
|
+
/**
|
|
144
|
+
* A TOTP second factor, for every user type with a password. Absent, no
|
|
145
|
+
* `secondFactor` flows exist and `signIn` answers a session directly.
|
|
146
|
+
*/
|
|
147
|
+
readonly secondFactor?: SecondFactorConfig;
|
|
148
|
+
}
|
|
149
|
+
/** What a TOTP second factor needs: a name for the app, and the keys that seal. */
|
|
150
|
+
export interface SecondFactorConfig {
|
|
151
|
+
/** Shown in the authenticator app beside the account: your product's name. */
|
|
152
|
+
readonly issuer: string;
|
|
153
|
+
/**
|
|
154
|
+
* The keys every TOTP secret is sealed with before a store sees it. **The
|
|
155
|
+
* first seals, every one opens**: to rotate, put the new key first and keep
|
|
156
|
+
* the old one until no secret is sealed with it.
|
|
157
|
+
*/
|
|
158
|
+
readonly keys: readonly [SealingKey, ...SealingKey[]];
|
|
159
|
+
/** How long `signIn`'s challenge waits for a code. `'5m'` when absent. */
|
|
160
|
+
readonly challenge?: Duration;
|
|
140
161
|
}
|
|
141
162
|
/** An application with one user type: `user` is its schema. */
|
|
142
163
|
export interface SingleTypeConfig extends SharedConfig, Omit<UserTypeConfig, 'schema'> {
|
|
@@ -161,7 +182,7 @@ export declare const SINGLE_TYPE = "user";
|
|
|
161
182
|
* Keys `janus` sets on every user, so a schema may not declare them.
|
|
162
183
|
* `password` too: it is taken beside the fields, and never stored among them.
|
|
163
184
|
*/
|
|
164
|
-
export declare const RESERVED_FIELDS: readonly ["id", "type", "emailVerified", "active", "hasPassword", "version", "createdAt", "updatedAt", "password"];
|
|
185
|
+
export declare const RESERVED_FIELDS: readonly ["id", "type", "emailVerified", "active", "hasPassword", "hasSecondFactor", "version", "createdAt", "updatedAt", "password"];
|
|
165
186
|
/** Names on `janus()`'s answer, so a user type may not take one. */
|
|
166
187
|
export declare const RESERVED_TYPES: readonly ["authenticate", "signOut", "signOutEverywhere", "findUser", "getUser", "cookie", "collectExpired", "types"];
|
|
167
188
|
/** One user type, with every default applied and every duration in milliseconds. */
|
|
@@ -184,7 +205,13 @@ export interface ResolvedConfig {
|
|
|
184
205
|
readonly tokenTtlMs: {
|
|
185
206
|
readonly verifyEmail: number;
|
|
186
207
|
readonly resetPassword: number;
|
|
208
|
+
readonly signInCode: number;
|
|
187
209
|
};
|
|
210
|
+
readonly secondFactor: {
|
|
211
|
+
readonly issuer: string;
|
|
212
|
+
readonly sealer: Sealer;
|
|
213
|
+
readonly challengeTtlMs: number;
|
|
214
|
+
} | null;
|
|
188
215
|
readonly cookie: {
|
|
189
216
|
readonly name: string;
|
|
190
217
|
readonly domain: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/auth/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,KAAK,QAAQ,EAAiB,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAClB,MAAM,GACN,WAAW,GACX,eAAe,GACf,mBAAmB,GACnB,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;AAE/B;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GACnB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,UAAU,EAAE,GACrB;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAA;CAAE,CAAC;AAEtD;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,gBAAgB,CACxC,OAAO,EACP;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAA;CAAE,CAClD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC9B,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD;;;;;OAKG;IACH,WAAW,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CACpC;AAED,kCAAkC;AAClC,MAAM,WAAW,cAAc;IAC9B;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,mCAAmC;IACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,wDAAwD;AACxD,MAAM,WAAW,aAAa;IAC7B,0BAA0B;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;CACvC;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,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;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/auth/config.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/context.d.ts
CHANGED
|
@@ -84,4 +84,10 @@ export declare function getRecord(context: Context, id: string, type: string | n
|
|
|
84
84
|
* `VERSION_CONFLICT`, and nothing is written.
|
|
85
85
|
*/
|
|
86
86
|
export declare function writeUser(context: Context, user: UserRef, type: ResolvedType, options: WriteOptions | undefined, where: string, patchOf: (record: UserRecord, now: Date) => Omit<UserPatch, 'updatedAt'> | Promise<Omit<UserPatch, 'updatedAt'>>): Promise<UserRecord>;
|
|
87
|
+
/**
|
|
88
|
+
* The user of this type whose e-mail this is, or `null`. Looked up as a
|
|
89
|
+
* login — every e-mail is one — and then compared, so a username that only
|
|
90
|
+
* looks like an e-mail is nobody's.
|
|
91
|
+
*/
|
|
92
|
+
export declare function holderOfEmail(context: Context, type: ResolvedType, email: string): Promise<UserRecord | null>;
|
|
87
93
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/auth/context.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAEN,KAAK,cAAc,EAEnB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,MAAM,UAAU,CAAC;AAElB,OAAO,KAAK,EACX,WAAW,EAEX,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,UAAU,EACV,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE3D,MAAM,WAAW,OAAO;IACvB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IACvC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IAC9C,+EAA+E;IAC/E,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAC5B,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,aAAa,GAAG,IAAI,EAC/B,YAAY,EAAE,iBAAiB,EAC/B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,cAAc,GAAG,IAAI,EAC7B,SAAS,EAAE,SAAS,cAAc,EAAE,GAClC,OAAO,CAmBT;AAED,kEAAkE;AAClE,MAAM,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/auth/context.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAEN,KAAK,cAAc,EAEnB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,MAAM,UAAU,CAAC;AAElB,OAAO,KAAK,EACX,WAAW,EAEX,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,UAAU,EACV,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE3D,MAAM,WAAW,OAAO;IACvB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IACvC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IAC9C,+EAA+E;IAC/E,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAC5B,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,aAAa,GAAG,IAAI,EAC/B,YAAY,EAAE,iBAAiB,EAC/B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,cAAc,GAAG,IAAI,EAC7B,SAAS,EAAE,SAAS,cAAc,EAAE,GAClC,OAAO,CAmBT;AAED,kEAAkE;AAClE,MAAM,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAalD;AAED,sCAAsC;AACtC,eAAO,MAAM,IAAI,GAAI,MAAM,OAAO,KAAG,MACK,CAAC;AAE3C;;;GAGG;AACH,wBAAsB,cAAc,CACnC,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,UAAU,CAAC,CAmCrB;AA+DD,gFAAgF;AAChF,wBAAgB,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAG7E;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CACvB,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,GACX,MAAM,EAAE,CAiCV;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAC5B,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACX,IAAI,CASN;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,CAO7E;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACpC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CAiBlB;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAC7B,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,UAAU,CAAC,CAyBrB;AAUD;;;;;GAKG;AACH,wBAAsB,UAAU,CAC/B,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,GAAG,IAAI,GACjB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAM5B;AAED,gCAAgC;AAChC,wBAAsB,SAAS,CAC9B,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,UAAU,CAAC,CAIrB;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAC9B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,YAAY,GAAG,SAAS,EACjC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CACR,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,IAAI,KACL,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,GACvE,OAAO,CAAC,UAAU,CAAC,CAyBrB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAClC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAM5B"}
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
export type { CookieConfig, FieldsJson, JanusConfig, MultiTypeConfig, Normalize, PasswordConfig, PasswordHasher, SessionConfig, SingleTypeConfig, UserSchema, UserTypeConfig, } from './config';
|
|
1
|
+
export type { CookieConfig, FieldsJson, JanusConfig, MultiTypeConfig, Normalize, PasswordConfig, PasswordHasher, SecondFactorConfig, SessionConfig, SingleTypeConfig, UserSchema, UserTypeConfig, } from './config';
|
|
2
2
|
export { bunHasher, scryptHasher } from './hashers';
|
|
3
3
|
export { janus } from './janus';
|
|
4
4
|
export { assertStores } from './port/assert-stores';
|
|
5
5
|
export { createMemoryStores } from './port/memory';
|
|
6
6
|
export type { JanusStores, Json, JsonObject, PasswordRecord, SecondFactorRecord, SessionId, SessionRecord, SessionStore, StoreCapabilities, TokenKind, TokenRecord, TokenStore, UserPageRequest, UserPatch, UserRecord, UserStore, } from './port/types';
|
|
7
|
+
export type { SealingKey } from './sealing';
|
|
7
8
|
export type { StandardSchemaV1 } from './standard-schema';
|
|
8
|
-
export type { Authenticated, Checked, EmailOf, HeaderRecord, IssuedToken, Janus, LoginOf, PasswordApi, RequestLike, RequiredStringKeys, ResetPasswordApi, Session, SharedApi, SignedIn, TypeApi, TypesOf, User, UserBase, UserOf, UserRef, UserTypeApi, VerifyEmailApi, WriteOptions, } from './types';
|
|
9
|
+
export type { Authenticated, Checked, EmailOf, HeaderRecord, IssuedCode, IssuedToken, Janus, LoginOf, PasswordApi, RequestLike, RequiredStringKeys, ResetPasswordApi, SecondFactorApi, SecondFactorEnrolment, SecondFactorRequired, Session, SharedApi, SignedIn, SignInCodeApi, SignInResult, TypeApi, TypesOf, User, UserBase, UserOf, UserRef, UserTypeApi, VerifyEmailApi, WriteOptions, } from './types';
|
|
9
10
|
//# 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,UAAU,EACV,WAAW,EACX,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,cAAc,GACd,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,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,YAAY,EACX,aAAa,EACb,OAAO,EACP,OAAO,EACP,YAAY,EACZ,WAAW,EACX,KAAK,EACL,OAAO,EACP,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,OAAO,EACP,SAAS,EACT,QAAQ,EACR,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,UAAU,EACV,WAAW,EACX,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,cAAc,GACd,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,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,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,OAAO,EACP,SAAS,EACT,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,OAAO,EACP,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,OAAO,EACP,WAAW,EACX,cAAc,EACd,YAAY,GACZ,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { TokenError } from '../errors/janus-error';
|
|
2
|
+
import { type ResolvedType } from './config';
|
|
3
|
+
import { type Context } from './context';
|
|
4
|
+
import type { TokenKind, TokenRecord, UserRecord } from './port/types';
|
|
5
|
+
/**
|
|
6
|
+
* The rules every one-time token shares — an e-mail link, a second-factor
|
|
7
|
+
* challenge — kept in one place so the two cannot drift apart.
|
|
8
|
+
*
|
|
9
|
+
* `noun` is what the messages call it: `token` for a link, `challenge` for
|
|
10
|
+
* what `signIn` answers. No message names the secret or its hash.
|
|
11
|
+
*/
|
|
12
|
+
export type OneTimeNoun = 'token' | 'challenge';
|
|
13
|
+
/**
|
|
14
|
+
* How many codes one challenge takes — a second factor's or an e-mail
|
|
15
|
+
* code's. A six-digit code has a million values: five attempts is a
|
|
16
|
+
* one-in-200,000 chance **per challenge**, and the attempts are counted by
|
|
17
|
+
* the store in one write, never read then written.
|
|
18
|
+
*/
|
|
19
|
+
export declare const CODE_ATTEMPTS = 5;
|
|
20
|
+
/**
|
|
21
|
+
* Counts one attempt at a challenge's code, before anything is compared: a
|
|
22
|
+
* guess that fails for any reason has still cost one. Refuses a challenge
|
|
23
|
+
* that cannot be used, and one past its last attempt — a call that raced the
|
|
24
|
+
* one that spent it — unread.
|
|
25
|
+
*/
|
|
26
|
+
export declare function countCodeAttempt(context: Context, secret: string, kind: TokenKind, where: string, userType: string): Promise<{
|
|
27
|
+
readonly token: TokenRecord;
|
|
28
|
+
readonly attemptsLeft: number;
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* A code that does not match — a second factor's or an e-mailed one — or a
|
|
32
|
+
* TOTP code already used. `attemptsLeft` only when a challenge counted it.
|
|
33
|
+
*/
|
|
34
|
+
export declare function codeInvalid(where: string, userId: string, userType: string, attemptsLeft?: number): TokenError;
|
|
35
|
+
/**
|
|
36
|
+
* Refuses a token sent to an e-mail the user no longer has: redeeming it
|
|
37
|
+
* would prove an address nobody holds any more.
|
|
38
|
+
*/
|
|
39
|
+
export declare function refuseStale(type: ResolvedType, user: UserRecord, token: TokenRecord, where: string, noun: 'token' | 'code'): void;
|
|
40
|
+
/**
|
|
41
|
+
* Refuses a token that cannot be used: none, spent, or lapsed. What a store
|
|
42
|
+
* answered — before a `consumeToken`, after a `countAttempt` — is read the
|
|
43
|
+
* same way: `spentAt` set means somebody else used it.
|
|
44
|
+
*/
|
|
45
|
+
export declare function refuseUnusable(token: TokenRecord | null, now: Date, where: string, noun: OneTimeNoun): asserts token is TokenRecord;
|
|
46
|
+
/** The refusal for a token whose user is gone, or of another type. */
|
|
47
|
+
export declare const unknownOneTime: (where: string, noun: OneTimeNoun) => TokenError;
|
|
48
|
+
/**
|
|
49
|
+
* Spends a token, and refuses it when this call did not: the store answers it
|
|
50
|
+
* **as it was before**, so exactly one call ever reads `spentAt: null`. A
|
|
51
|
+
* lapsed token is spent all the same, so it cannot be retried.
|
|
52
|
+
*/
|
|
53
|
+
export declare function spendOneTime(context: Context, secret: string, kind: TokenKind, where: string, noun: OneTimeNoun): Promise<TokenRecord>;
|
|
54
|
+
/**
|
|
55
|
+
* Spends a token whose last attempt failed. Its answer is not read: a racing
|
|
56
|
+
* call that spent it first changes nothing for this one, which is refused
|
|
57
|
+
* for its code either way.
|
|
58
|
+
*/
|
|
59
|
+
export declare function burnOneTime(context: Context, secret: string, kind: TokenKind): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* A code's hash, **keyed by its challenge**: the tokens alone — a dump, a
|
|
62
|
+
* log of the table — do not reveal the code, since a million guesses at it
|
|
63
|
+
* each need the challenge, which only the visitor holds.
|
|
64
|
+
*/
|
|
65
|
+
export declare const hashCode: (challenge: string, code: string) => string;
|
|
66
|
+
/** Whether `code` is the one whose hash the token holds, compared in constant time. */
|
|
67
|
+
export declare function codeMatches(token: TokenRecord, challenge: string, code: string): boolean;
|
|
68
|
+
interface OneTimeRequest {
|
|
69
|
+
readonly kind: TokenKind;
|
|
70
|
+
readonly userId: string;
|
|
71
|
+
readonly address: string;
|
|
72
|
+
readonly ttlMs: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Issues a one-time token: 32 random bytes, given back once, and only their
|
|
76
|
+
* hash stored.
|
|
77
|
+
*/
|
|
78
|
+
export declare function issueOneTime(context: Context, token: OneTimeRequest): Promise<{
|
|
79
|
+
readonly secret: string;
|
|
80
|
+
readonly expiresAt: Date;
|
|
81
|
+
}>;
|
|
82
|
+
/**
|
|
83
|
+
* Issues a one-time token with a six-digit code for a person to type: the
|
|
84
|
+
* token is the challenge, and only the code's hash is stored, keyed by it.
|
|
85
|
+
*/
|
|
86
|
+
export declare function issueCode(context: Context, token: OneTimeRequest): Promise<{
|
|
87
|
+
readonly secret: string;
|
|
88
|
+
readonly expiresAt: Date;
|
|
89
|
+
readonly code: string;
|
|
90
|
+
}>;
|
|
91
|
+
export {};
|
|
92
|
+
//# sourceMappingURL=one-time.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"one-time.d.ts","sourceRoot":"","sources":["../../src/auth/one-time.ts"],"names":[],"mappings":"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"}
|
|
@@ -87,10 +87,10 @@ export interface PasswordRecord {
|
|
|
87
87
|
/**
|
|
88
88
|
* A second factor, as the store holds it: a TOTP secret.
|
|
89
89
|
*
|
|
90
|
-
* **The secret is opaque to a store.**
|
|
91
|
-
*
|
|
92
|
-
* so a dump of the users cannot produce a code. A store
|
|
93
|
-
* for byte, like a password hash, and never parses it.
|
|
90
|
+
* **The secret is opaque to a store.** The core seals it with a key the
|
|
91
|
+
* application holds — AES-256-GCM, `v1.<key id>.<iv>.<ciphertext>` — before a
|
|
92
|
+
* store ever sees it, so a dump of the users cannot produce a code. A store
|
|
93
|
+
* keeps the string byte for byte, like a password hash, and never parses it.
|
|
94
94
|
*/
|
|
95
95
|
export interface SecondFactorRecord {
|
|
96
96
|
/** How the codes are made. `'totp'`, the codes of an authenticator app, is the only one. */
|
|
@@ -372,7 +372,10 @@ export interface TokenRecord {
|
|
|
372
372
|
readonly tokenHash: string;
|
|
373
373
|
readonly kind: TokenKind;
|
|
374
374
|
readonly userId: Id;
|
|
375
|
-
/**
|
|
375
|
+
/**
|
|
376
|
+
* The e-mail the token was sent to — the one a verification marks
|
|
377
|
+
* verified. `''` for a second-factor challenge, which nothing was sent for.
|
|
378
|
+
*/
|
|
376
379
|
readonly address: string;
|
|
377
380
|
/**
|
|
378
381
|
* For a token redeemed with a code — `signInCode` — the code's hash, keyed
|
|
@@ -383,8 +386,8 @@ export interface TokenRecord {
|
|
|
383
386
|
readonly codeHash: string | null;
|
|
384
387
|
/**
|
|
385
388
|
* How many codes were tried against it: `0` at insertion, and one more on
|
|
386
|
-
* every {@link TokenStore.countAttempt}. What bounds
|
|
387
|
-
* code.
|
|
389
|
+
* every {@link TokenStore.countAttempt}. What bounds the attempts at a
|
|
390
|
+
* six-digit code.
|
|
388
391
|
*/
|
|
389
392
|
readonly attempts: number;
|
|
390
393
|
readonly expiresAt: Date;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/auth/port/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/auth/port/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A second factor's secret, sealed before any store sees it: AES-256-GCM
|
|
3
|
+
* under a key the application holds, so a dump of the users is not a dump of
|
|
4
|
+
* everyone's authenticator.
|
|
5
|
+
*
|
|
6
|
+
* The sealed form is `v1.<key id>.<iv>.<ciphertext and tag>`, the last two in
|
|
7
|
+
* base64url. It names its key, so keys rotate: the first key seals, every key
|
|
8
|
+
* opens, and a secret sealed under an older one is sealed again under the
|
|
9
|
+
* first the next time a code is accepted. The user's id is the additional
|
|
10
|
+
* data, so a sealed secret copied onto another user does not open.
|
|
11
|
+
*/
|
|
12
|
+
/** One key, as `janus({ secondFactor: { keys } })` takes it. */
|
|
13
|
+
export interface SealingKey {
|
|
14
|
+
/** Names the key in every secret it seals: letters, digits, `_` and `-`. */
|
|
15
|
+
readonly id: string;
|
|
16
|
+
/** 32 random bytes, in base64 or base64url: `openssl rand -base64 32`. */
|
|
17
|
+
readonly key: string;
|
|
18
|
+
}
|
|
19
|
+
/** The keys, decoded and checked: the first seals. */
|
|
20
|
+
export interface Sealer {
|
|
21
|
+
readonly sealWith: string;
|
|
22
|
+
readonly keys: ReadonlyMap<string, Buffer>;
|
|
23
|
+
}
|
|
24
|
+
/** Decodes the keys and refuses what cannot seal. `where` names the option. */
|
|
25
|
+
export declare function resolveSealer(keys: unknown, where: string): Sealer;
|
|
26
|
+
/** Seals `plain` under the first key, bound to `boundTo` — the user's id. */
|
|
27
|
+
export declare function seal(sealer: Sealer, plain: string, boundTo: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Opens a sealed secret, and says which key sealed it.
|
|
30
|
+
*
|
|
31
|
+
* Every failure is a **wiring** mistake, a bare `TypeError`: a key taken out
|
|
32
|
+
* of `keys` while secrets it sealed are still stored, or a key changed under
|
|
33
|
+
* the same id. None of them comes from a request.
|
|
34
|
+
*/
|
|
35
|
+
export declare function unseal(sealer: Sealer, sealed: string, boundTo: string, where: string): {
|
|
36
|
+
readonly plain: string;
|
|
37
|
+
readonly keyId: string;
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=sealing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sealing.d.ts","sourceRoot":"","sources":["../../src/auth/sealing.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,gEAAgE;AAChE,MAAM,WAAW,UAAU;IAC1B,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;AAED,sDAAsD;AACtD,MAAM,WAAW,MAAM;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAQD,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CA0BlE;AAED,6EAA6E;AAC7E,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAW3E;AAED;;;;;;GAMG;AACH,wBAAgB,MAAM,CACrB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACX;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAwCpD"}
|