@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.
Files changed (60) hide show
  1. package/README.md +159 -20
  2. package/dist/auth/config.d.ts +28 -1
  3. package/dist/auth/config.d.ts.map +1 -1
  4. package/dist/auth/context.d.ts +6 -0
  5. package/dist/auth/context.d.ts.map +1 -1
  6. package/dist/auth/index.d.ts +3 -2
  7. package/dist/auth/index.d.ts.map +1 -1
  8. package/dist/auth/one-time.d.ts +92 -0
  9. package/dist/auth/one-time.d.ts.map +1 -0
  10. package/dist/auth/port/types.d.ts +10 -7
  11. package/dist/auth/port/types.d.ts.map +1 -1
  12. package/dist/auth/sealing.d.ts +39 -0
  13. package/dist/auth/sealing.d.ts.map +1 -0
  14. package/dist/auth/second-factor/challenge.d.ts +14 -0
  15. package/dist/auth/second-factor/challenge.d.ts.map +1 -0
  16. package/dist/auth/second-factor/factor.d.ts +27 -0
  17. package/dist/auth/second-factor/factor.d.ts.map +1 -0
  18. package/dist/auth/second-factor/flows.d.ts +23 -0
  19. package/dist/auth/second-factor/flows.d.ts.map +1 -0
  20. package/dist/auth/second-factor/lifecycle.d.ts +8 -0
  21. package/dist/auth/second-factor/lifecycle.d.ts.map +1 -0
  22. package/dist/auth/sessions.d.ts.map +1 -1
  23. package/dist/auth/sign-in-code.d.ts +17 -0
  24. package/dist/auth/sign-in-code.d.ts.map +1 -0
  25. package/dist/auth/totp.d.ts +36 -0
  26. package/dist/auth/totp.d.ts.map +1 -0
  27. package/dist/auth/types.d.ts +140 -7
  28. package/dist/auth/types.d.ts.map +1 -1
  29. package/dist/auth/users.d.ts +2 -2
  30. package/dist/auth/users.d.ts.map +1 -1
  31. package/dist/chunks/{index-qwfkhqkk.js → index-06vp9c5r.js} +12 -3
  32. package/dist/chunks/{index-qwfkhqkk.js.map → index-06vp9c5r.js.map} +3 -3
  33. package/dist/chunks/{index-53y1afjz.js → index-5vr13kkb.js} +2 -2
  34. package/dist/chunks/{index-mgh85djb.js → index-c4v27jfr.js} +2 -2
  35. package/dist/chunks/{index-thtyq7a9.js → index-gbwn2tts.js} +2 -2
  36. package/dist/conformance/cases/tokens.d.ts.map +1 -1
  37. package/dist/conformance/index.js +15 -4
  38. package/dist/conformance/index.js.map +3 -3
  39. package/dist/errors/janus-error.d.ts +28 -2
  40. package/dist/errors/janus-error.d.ts.map +1 -1
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +478 -51
  44. package/dist/index.js.map +15 -7
  45. package/dist/permissions/index.js +3 -3
  46. package/docs/README.md +2 -0
  47. package/docs/guide/adapters.md +12 -7
  48. package/docs/guide/email-flows.md +4 -0
  49. package/docs/guide/errors.md +19 -7
  50. package/docs/guide/second-factor.md +571 -0
  51. package/docs/guide/sessions.md +18 -0
  52. package/docs/guide/sign-in-code.md +471 -0
  53. package/docs/guide/users.md +10 -3
  54. package/docs/guide/vocabulary.md +9 -6
  55. package/docs/roadmap.md +39 -54
  56. package/docs/troubleshooting.md +414 -5
  57. package/package.json +1 -1
  58. /package/dist/chunks/{index-53y1afjz.js.map → index-5vr13kkb.js.map} +0 -0
  59. /package/dist/chunks/{index-mgh85djb.js.map → index-c4v27jfr.js.map} +0 -0
  60. /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 sixteen
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`, `InvalidCursorError`, `UnsupportedError`
189
- and `PermissionDepthError`. `StoreFailure` and `StoreConflict` are exported
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, and not a connection URI, because a connection string
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`, `version`,
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 `resetPassword` — they are absent from its type, not
351
- failing at run time. Changing the e-mail sets `emailVerified` back to `false`.
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 already holds what one-time codes need, before any flow uses it: a
400
- user's `secondFactor` (a TOTP secret, or `null`; the core will seal it before
401
- a store sees it, once the second factor ships), a token's `codeHash` and
402
- `attempts`, and `TokenStore.countAttempt`, which counts one attempt in one
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 44 cases. They cover:
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 three plausible mistakes, one hundred and three refused at compile time — 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` (twenty, on
702
- `janus()`, from the point of view of the application) and `test/types/permissions.ts` (forty-eight, on the
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
@@ -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":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/auth/config.ts"],"names":[],"mappings":"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"}
@@ -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":"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"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/auth/context.ts"],"names":[],"mappings":"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"}
@@ -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
@@ -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.** Once the second factor ships, the core
91
- * will seal it with a key the application holds before a store ever sees it,
92
- * so a dump of the users cannot produce a code. A store keeps the string byte
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
- /** The e-mail the token was sent to — the one a verification marks verified. */
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 guessing a six-digit
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"}