@nxgt/janus 0.6.0 → 0.8.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 +107 -17
- package/dist/auth/config.d.ts +8 -0
- package/dist/auth/config.d.ts.map +1 -1
- package/dist/auth/context.d.ts +10 -1
- package/dist/auth/context.d.ts.map +1 -1
- package/dist/auth/email-flows.d.ts +11 -0
- package/dist/auth/email-flows.d.ts.map +1 -0
- package/dist/auth/events.d.ts +52 -0
- package/dist/auth/events.d.ts.map +1 -0
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/janus.d.ts.map +1 -1
- package/dist/auth/one-time.d.ts +7 -0
- package/dist/auth/one-time.d.ts.map +1 -1
- package/dist/auth/password-written.d.ts +24 -0
- package/dist/auth/password-written.d.ts.map +1 -0
- package/dist/auth/port/assert-stores.d.ts.map +1 -1
- package/dist/auth/port/types.d.ts +23 -1
- package/dist/auth/port/types.d.ts.map +1 -1
- package/dist/auth/second-factor/challenge.d.ts.map +1 -1
- package/dist/auth/sign-in-code.d.ts +6 -3
- package/dist/auth/sign-in-code.d.ts.map +1 -1
- package/dist/auth/types.d.ts +6 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/auth/users.d.ts.map +1 -1
- package/dist/chunks/{index-gbwn2tts.js → index-c0jajeda.js} +12 -2
- package/dist/chunks/{index-gbwn2tts.js.map → index-c0jajeda.js.map} +3 -3
- package/dist/conformance/cases/outage.d.ts.map +1 -1
- package/dist/conformance/cases/tokens.d.ts.map +1 -1
- package/dist/conformance/index.js +73 -2
- package/dist/conformance/index.js.map +4 -4
- package/dist/index.js +207 -95
- package/dist/index.js.map +14 -11
- package/docs/README.md +2 -1
- package/docs/guide/adapters.md +56 -3
- package/docs/guide/email-flows.md +11 -1
- package/docs/guide/events.md +199 -0
- package/docs/guide/second-factor.md +27 -2
- package/docs/guide/sign-in-code.md +28 -9
- package/docs/guide/users.md +8 -4
- package/docs/guide/vocabulary.md +3 -0
- package/docs/roadmap.md +25 -13
- package/docs/troubleshooting.md +89 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ supported.
|
|
|
36
36
|
|
|
37
37
|
| Import | What it holds |
|
|
38
38
|
| --- | --- |
|
|
39
|
-
| `@nxgt/janus` | **Identities**: `janus()`, the identity stores' port and its in-memory reference (`createMemoryStores`), the hashers. And the **shared vocabulary**: errors, subjects and the tuple notation, ids, pagination, time |
|
|
39
|
+
| `@nxgt/janus` | **Identities**: `janus()`, the identity stores' port and its in-memory reference (`createMemoryStores`), the hashers, the user events (`UserEvent`, `UserEventListener`, `UserEventType`). And the **shared vocabulary**: errors, subjects and the tuple notation, ids, pagination, time |
|
|
40
40
|
| `@nxgt/janus/permissions` | **Permissions**: `defineModel`, `fromField`, `when`, `permissions()` — `can`, `list`, `grant`, `revoke` — the relation store's port and its in-memory reference (`createMemoryRelations`) |
|
|
41
41
|
| `@nxgt/janus/conformance` | **For adapters**: the suites a store runs — `describeJanusStores`, `describeRelationStores` — their cases as data, and the reference harnesses |
|
|
42
42
|
|
|
@@ -429,10 +429,38 @@ await tokens.countAttempt(tokenHash, 'signInCode'); // { …, attempts: 1 }
|
|
|
429
429
|
await tokens.countAttempt(tokenHash, 'verifyEmail'); // null: no token of that kind
|
|
430
430
|
```
|
|
431
431
|
|
|
432
|
+
`spendUserTokens(userId, kind, at, except?)` spends the unspent tokens of one
|
|
433
|
+
user and one kind — but the one whose hash is `except` — and answers how many:
|
|
434
|
+
what issuing a sign-in code and writing a password call:
|
|
435
|
+
|
|
436
|
+
```ts
|
|
437
|
+
const userId = mintId();
|
|
438
|
+
const now = new Date();
|
|
439
|
+
const code = (tokenHash: string) => ({
|
|
440
|
+
tokenHash,
|
|
441
|
+
kind: 'signInCode' as const,
|
|
442
|
+
userId,
|
|
443
|
+
address: 'ada@example.test',
|
|
444
|
+
codeHash: 'c'.repeat(64),
|
|
445
|
+
attempts: 0,
|
|
446
|
+
expiresAt: new Date(now.getTime() + 10 * 60_000),
|
|
447
|
+
spentAt: null,
|
|
448
|
+
createdAt: now,
|
|
449
|
+
});
|
|
450
|
+
const kept = code('d'.repeat(64));
|
|
451
|
+
await tokens.insertToken(kept);
|
|
452
|
+
await tokens.insertToken(code('e'.repeat(64)));
|
|
453
|
+
await tokens.spendUserTokens(userId, 'signInCode', now, kept.tokenHash); // 1: the other one
|
|
454
|
+
await tokens.spendUserTokens(userId, 'signInCode', now); // 1: `kept`, now
|
|
455
|
+
await tokens.spendUserTokens(userId, 'signInCode', now); // 0: none left unspent
|
|
456
|
+
```
|
|
457
|
+
|
|
432
458
|
An adapter written against `@nxgt/janus` 0.3 does not compile against this
|
|
433
|
-
port until it implements `countAttempt`,
|
|
434
|
-
|
|
435
|
-
|
|
459
|
+
port until it implements `countAttempt`, nor one written against 0.6 until it
|
|
460
|
+
implements `spendUserTokens`, and `janus()` refuses either at wiring —
|
|
461
|
+
[Writing an adapter](docs/guide/adapters.md) has the contracts:
|
|
462
|
+
[`countAttempt`](docs/guide/adapters.md#tokenstorecountattempt) and
|
|
463
|
+
[`spendUserTokens`](docs/guide/adapters.md#tokenstorespendusertokens).
|
|
436
464
|
|
|
437
465
|
### Second factor — `secondFactor`
|
|
438
466
|
|
|
@@ -468,7 +496,7 @@ every user type with a password.
|
|
|
468
496
|
|
|
469
497
|
- **`signIn` answers a union once `secondFactor` is configured**:
|
|
470
498
|
`{ status: 'signedIn', user, session, token }`, or
|
|
471
|
-
`{ status: 'secondFactor', challenge, expiresAt }` for a user whose factor
|
|
499
|
+
`{ status: 'secondFactor', challenge, expiresAt, userId }` for a user whose factor
|
|
472
500
|
is active. Switch on `status`: reading `token` before that is a compile
|
|
473
501
|
error. Without `secondFactor`, `signIn` answers a session, as before.
|
|
474
502
|
- **A factor is enrolled, then active.** `enroll` answers the secret and its
|
|
@@ -532,6 +560,51 @@ A six-digit code sent to the user's e-mail signs them in, with no password.
|
|
|
532
560
|
[The sign-in code guide](docs/guide/sign-in-code.md) has the request that
|
|
533
561
|
tells nobody who exists, the challenge in a cookie, every error, and a test.
|
|
534
562
|
|
|
563
|
+
### User events — `events`
|
|
564
|
+
|
|
565
|
+
```ts
|
|
566
|
+
import { z } from 'zod';
|
|
567
|
+
import { createMemoryStores, janus, scryptHasher, type UserEvent } from '@nxgt/janus';
|
|
568
|
+
|
|
569
|
+
const auth = janus({
|
|
570
|
+
user: z.object({ email: z.email() }),
|
|
571
|
+
password: { login: 'email' },
|
|
572
|
+
store: createMemoryStores(),
|
|
573
|
+
hasher: scryptHasher(),
|
|
574
|
+
async events(event: UserEvent) {
|
|
575
|
+
// { id, type: 'user.created', occurredAt, userId, userType }
|
|
576
|
+
await queue.add(event.type, event, { jobId: event.id }); // deliver it once
|
|
577
|
+
},
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
await auth.signUp({ email, password }); // the listener has the event before this answers
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
`janus({ events })` hears what happened to a user, once it is written:
|
|
584
|
+
|
|
585
|
+
| `type` | Sent by |
|
|
586
|
+
| --- | --- |
|
|
587
|
+
| `user.created` | `create`, `signUp` |
|
|
588
|
+
| `user.emailVerified` | `verifyEmail.confirm`; `resetPassword.confirm` and `signInCode.confirm`, whose link or code proves the e-mail too — never for an e-mail already verified |
|
|
589
|
+
| `user.passwordReset` | `resetPassword.confirm` |
|
|
590
|
+
| `user.deleted` | `delete`, once — a replay that deletes nobody sends nothing |
|
|
591
|
+
|
|
592
|
+
- **The user is named by id, and nothing else**: no login, no e-mail, no
|
|
593
|
+
field, no password, no token. Whoever receives the event reads the rest
|
|
594
|
+
from where it is kept, if they may.
|
|
595
|
+
- **Each event has an `id` of its own**, a UUIDv7: the key to deliver it once.
|
|
596
|
+
- **The listener runs after the write, and is awaited** before the
|
|
597
|
+
flow answers, so a durable queue has the event by then. `occurredAt` is the
|
|
598
|
+
write's own time. A refused flow sends nothing.
|
|
599
|
+
- **Typed**: `events` is a `UserEventListener`; `UserEventType` is the closed
|
|
600
|
+
union of the four types, so a `switch` on `event.type` is exhaustive.
|
|
601
|
+
- **A listener that throws fails no flow** — the write happened. It is a
|
|
602
|
+
`JANUS_EVENT_FAILED` warning naming the event's type, its id and the user's
|
|
603
|
+
id, never the failure's message.
|
|
604
|
+
|
|
605
|
+
[The user events guide](docs/guide/events.md) has the listener, the four
|
|
606
|
+
types, what a failure costs, and a test.
|
|
607
|
+
|
|
535
608
|
### Permissions — `@nxgt/janus/permissions`
|
|
536
609
|
|
|
537
610
|
```ts
|
|
@@ -642,7 +715,7 @@ describeJanusStores({
|
|
|
642
715
|
});
|
|
643
716
|
```
|
|
644
717
|
|
|
645
|
-
There are
|
|
718
|
+
There are 49 cases. They cover:
|
|
646
719
|
- round-trip, byte for byte — including every edge character the core lets
|
|
647
720
|
through (control characters, U+FFFF, a surrogate pair);
|
|
648
721
|
- uniqueness, as a constraint: of twenty concurrent inserts of one login,
|
|
@@ -655,12 +728,15 @@ There are 45 cases. They cover:
|
|
|
655
728
|
- one-time tokens: of twenty concurrent redemptions, exactly one succeeds;
|
|
656
729
|
of twenty concurrent `countAttempt` calls, each answers a distinct count,
|
|
657
730
|
and none is counted once a racing redemption spent the token;
|
|
731
|
+
- spending a user's tokens of one kind — `spendUserTokens` — spends only the
|
|
732
|
+
unspent ones of that user and kind, spares the one named by `except`, and
|
|
733
|
+
never spends the same token as a racing redemption;
|
|
658
734
|
- a second-factor challenge, whose address is `''`, kept, counted and spent;
|
|
659
735
|
- a user's second factor: round-trip, kept by a patch that does not name it,
|
|
660
736
|
removed by one that names `null`;
|
|
661
737
|
- deletion: a user's logins are freed, and every session and token of theirs
|
|
662
738
|
goes, with a replay answering `false` or `0` rather than failing;
|
|
663
|
-
- **outages**, one case for each of the
|
|
739
|
+
- **outages**, one case for each of the thirteen methods whose honest answer can
|
|
664
740
|
be "nothing".
|
|
665
741
|
|
|
666
742
|
The suite imports no test framework and no assertion library. It runs under
|
|
@@ -694,8 +770,10 @@ example; `allRelationCases`, `relationStoreCases`, `relationOutageCases` and
|
|
|
694
770
|
|
|
695
771
|
**Once `secondFactor` is configured, switch on `signIn`'s `status`** — and
|
|
696
772
|
on `signInCode.confirm`'s. A user whose factor is active gets
|
|
697
|
-
`{ status: 'secondFactor', challenge }`, with no `token`
|
|
698
|
-
e-mailed code proves the e-mail, not the factor.
|
|
773
|
+
`{ status: 'secondFactor', challenge, expiresAt, userId }`, with no `token`
|
|
774
|
+
and no `session`: an e-mailed code proves the e-mail, not the factor.
|
|
775
|
+
`userId` is for your logs and rate limits — answer the visitor the
|
|
776
|
+
challenge alone.
|
|
699
777
|
`if (result.status === 'secondFactor') …` before anything reads them.
|
|
700
778
|
|
|
701
779
|
**A challenge is a secret, like a session token** — `signIn`'s and
|
|
@@ -707,9 +785,12 @@ the code and nothing else.
|
|
|
707
785
|
**Answer `signInCode.request` the same whether it issued a code or not** —
|
|
708
786
|
the same status, body and cookie: set a random challenge when it answered
|
|
709
787
|
`null`. The code route then still tells a decoy (`TOKEN_UNKNOWN`) from a
|
|
710
|
-
real challenge (`CODE_INVALID`, `attemptsLeft`
|
|
711
|
-
|
|
712
|
-
|
|
788
|
+
real challenge (`CODE_INVALID`, `attemptsLeft`, or `TOKEN_SPENT` once a later
|
|
789
|
+
request spent it): answer its refusals alike
|
|
790
|
+
where addresses must stay secret. And rate-limit the request **per
|
|
791
|
+
address**: at most one code is live per user — a new `request` spends the one
|
|
792
|
+
before — so without a limit anyone who knows an address can fill its inbox,
|
|
793
|
+
or cancel its owner's code before they type it.
|
|
713
794
|
|
|
714
795
|
**Every `janus()` that signs users in needs the same `secondFactor`.** An
|
|
715
796
|
instance without keys never signs in a user whose factor is active: `signIn`
|
|
@@ -756,7 +837,9 @@ denied. `resetPassword.request` answers `null` for an unknown e-mail for the
|
|
|
756
837
|
same reason: answer the visitor the same page either way.
|
|
757
838
|
|
|
758
839
|
**`resetPassword.confirm` signs the user out everywhere, and opens no session.**
|
|
759
|
-
Whoever had the old password loses their sessions
|
|
840
|
+
Whoever had the old password loses their sessions, and a sign-in they left
|
|
841
|
+
waiting on its second factor is spent with them — as it is by `setPassword`
|
|
842
|
+
and `changePassword`; what the visitor does next is
|
|
760
843
|
your policy. A password refused for its length does not spend the token.
|
|
761
844
|
|
|
762
845
|
**A sign-in can move a user's `version`.** Rewriting a stale hash is a write. A
|
|
@@ -821,6 +904,13 @@ a query of your own.
|
|
|
821
904
|
`list()` with its own error, as it threw. Never answer `[]` for a database that
|
|
822
905
|
could not answer: that is a denial made of an outage.
|
|
823
906
|
|
|
907
|
+
**A user event is sent at most once, from the process that wrote.** It is
|
|
908
|
+
handed to the listener after the write, in the same process: a crash between
|
|
909
|
+
the two loses it, and nothing sends it later. Build what must not miss one
|
|
910
|
+
— a billing sync, a search index — to also read the users themselves now and
|
|
911
|
+
then, and treat events as the fast path. A slow listener slows every flow
|
|
912
|
+
that sends one, since it is awaited: queue the event and return.
|
|
913
|
+
|
|
824
914
|
## Documentation
|
|
825
915
|
|
|
826
916
|
- [Guides](docs/README.md) — one page per area, every option with an example
|
|
@@ -829,16 +919,16 @@ could not answer: that is a denial made of an outage.
|
|
|
829
919
|
|
|
830
920
|
## Type safety, counted
|
|
831
921
|
|
|
832
|
-
**One hundred and
|
|
922
|
+
**One hundred and eighteen plausible mistakes, one hundred and eighteen refused at compile time — and
|
|
833
923
|
two gaps, named.**
|
|
834
924
|
|
|
835
925
|
The lists are typechecked and never run, with one `@ts-expect-error` per
|
|
836
926
|
mistake beside the shapes that must keep compiling:
|
|
837
927
|
`test/types/refusals.ts` (fourteen, on the shared vocabulary),
|
|
838
|
-
`test/types/port.ts` (twenty-
|
|
839
|
-
of view of the person implementing it), `test/types/auth.ts` (thirty-
|
|
928
|
+
`test/types/port.ts` (twenty-two, on the identity stores' port, from the point
|
|
929
|
+
of view of the person implementing it), `test/types/auth.ts` (thirty-four, on
|
|
840
930
|
`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
|
|
931
|
+
second factor, three on sign-in codes, three on user events) and `test/types/permissions.ts` (forty-eight, on the
|
|
842
932
|
permission model and the questions asked of it). The rule
|
|
843
933
|
comes from `nxgt-data`, and so does the reason to
|
|
844
934
|
distrust the claim without the files: when it was last measured on
|
package/dist/auth/config.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import type { RelationStore } from '../permissions/port/types';
|
|
10
10
|
import type { Clock } from '../time/clock';
|
|
11
11
|
import { type Duration } from '../time/duration';
|
|
12
|
+
import type { UserEventListener } from './events';
|
|
12
13
|
import type { JanusStores } from './port/types';
|
|
13
14
|
import { type Sealer, type SealingKey } from './sealing';
|
|
14
15
|
import type { StandardSchemaV1 } from './standard-schema';
|
|
@@ -145,6 +146,13 @@ interface SharedConfig {
|
|
|
145
146
|
* `secondFactor` flows exist and `signIn` answers a session directly.
|
|
146
147
|
*/
|
|
147
148
|
readonly secondFactor?: SecondFactorConfig;
|
|
149
|
+
/**
|
|
150
|
+
* Called with every user event — `user.created`, `user.emailVerified`,
|
|
151
|
+
* `user.passwordReset`, `user.deleted` — once the write landed,
|
|
152
|
+
* and awaited before the flow answers. Any function will do; the coming
|
|
153
|
+
* `@nxgt/janus-webhooks` will sign and deliver them.
|
|
154
|
+
*/
|
|
155
|
+
readonly events?: UserEventListener;
|
|
148
156
|
}
|
|
149
157
|
/** What a TOTP second factor needs: a name for the app, and the keys that seal. */
|
|
150
158
|
export interface SecondFactorConfig {
|
|
@@ -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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"}
|
package/dist/auth/context.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import type { RelationStore } from '../permissions/port/types';
|
|
10
10
|
import type { Clock } from '../time/clock';
|
|
11
11
|
import { type PasswordHasher, type ResolvedConfig, type ResolvedType } from './config';
|
|
12
|
+
import type { UserEventListener } from './events';
|
|
12
13
|
import type { JanusStores, JsonObject, StoreCapabilities, UserPatch, UserRecord } from './port/types';
|
|
13
14
|
import type { User, UserRef, WriteOptions } from './types';
|
|
14
15
|
export interface Context {
|
|
@@ -24,8 +25,10 @@ export interface Context {
|
|
|
24
25
|
readonly verifiers: readonly PasswordHasher[];
|
|
25
26
|
/** Hashed once, lazily: what a missing user's password is compared against. */
|
|
26
27
|
dummyHash(): Promise<string>;
|
|
28
|
+
/** What `janus({ events })` was given, or `null`. */
|
|
29
|
+
readonly events: UserEventListener | null;
|
|
27
30
|
}
|
|
28
|
-
export declare function createContext(config: ResolvedConfig, store: JanusStores, relations: RelationStore | null, capabilities: StoreCapabilities, clock: Clock, hasher: PasswordHasher | null, verifiers: readonly PasswordHasher[]): Context;
|
|
31
|
+
export declare function createContext(config: ResolvedConfig, store: JanusStores, relations: RelationStore | null, capabilities: StoreCapabilities, clock: Clock, hasher: PasswordHasher | null, verifiers: readonly PasswordHasher[], events?: UserEventListener | null): Context;
|
|
29
32
|
/** A user of any type, as the degenericised core handles them. */
|
|
30
33
|
export type AnyUser = User<string, Record<string, unknown>>;
|
|
31
34
|
/**
|
|
@@ -49,6 +52,12 @@ export declare function emailOf(type: ResolvedType, fields: JsonObject): string
|
|
|
49
52
|
* still be found by the e-mail a reset is requested for.
|
|
50
53
|
*/
|
|
51
54
|
export declare function loginsOf(type: ResolvedType, fields: JsonObject, where: string): string[];
|
|
55
|
+
/** The type's password rule, or a wiring refusal for a JavaScript caller. */
|
|
56
|
+
export declare function passwordRule(type: ResolvedType, where: string): {
|
|
57
|
+
readonly login: string;
|
|
58
|
+
readonly normalize: (value: string) => string;
|
|
59
|
+
readonly minLength: number;
|
|
60
|
+
};
|
|
52
61
|
/** Refuses a password shorter than the policy. Reports the policy, never the password. */
|
|
53
62
|
export declare function checkPassword(type: ResolvedType, password: string, where: string): void;
|
|
54
63
|
/** The hasher. `janus()` refused a password type without one, so this is a wiring net. */
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/auth/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ResolvedType } from './config';
|
|
2
|
+
import { type AnyUser, type Context } from './context';
|
|
3
|
+
import type { ResetPasswordApi, VerifyEmailApi } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* The e-mail flows: send a one-time token by e-mail, then confirm it —
|
|
6
|
+
* verifying the address, or resetting the password. Both confirm the same
|
|
7
|
+
* way: spend the token, read the user, and check the address again on the
|
|
8
|
+
* very record the write replaces.
|
|
9
|
+
*/
|
|
10
|
+
export declare function emailFlows(context: Context, type: ResolvedType, at: (operation: string) => string): VerifyEmailApi<AnyUser> & ResetPasswordApi<AnyUser>;
|
|
11
|
+
//# sourceMappingURL=email-flows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-flows.d.ts","sourceRoot":"","sources":["../../src/auth/email-flows.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAWZ,MAAM,WAAW,CAAC;AAUnB,OAAO,KAAK,EAAe,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE7E;;;;;GAKG;AACH,wBAAgB,UAAU,CACzB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAC/B,cAAc,CAAC,OAAO,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,CA6IrD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type Id } from '../ids/id';
|
|
2
|
+
import type { Context } from './context';
|
|
3
|
+
/**
|
|
4
|
+
* What happened to a user, once it is written:
|
|
5
|
+
*
|
|
6
|
+
* - `user.created` — by `create` or `signUp`;
|
|
7
|
+
* - `user.emailVerified` — by `verifyEmail.confirm`, or by the link of
|
|
8
|
+
* `resetPassword.confirm` or the code of `signInCode.confirm`, which prove
|
|
9
|
+
* the e-mail too; never for an e-mail already verified;
|
|
10
|
+
* - `user.passwordReset` — by `resetPassword.confirm`;
|
|
11
|
+
* - `user.deleted` — by `delete`, once; a replay that finds nobody is none.
|
|
12
|
+
*/
|
|
13
|
+
export type UserEventType = 'user.created' | 'user.emailVerified' | 'user.passwordReset' | 'user.deleted';
|
|
14
|
+
/**
|
|
15
|
+
* A user event: **the user named by id, and nothing else** — no login, no
|
|
16
|
+
* e-mail, no field, no password, no token. Whoever receives it reads the rest
|
|
17
|
+
* from where it is kept, if they may.
|
|
18
|
+
*/
|
|
19
|
+
export interface UserEvent {
|
|
20
|
+
/** A UUIDv7 minted for this event: the key to deliver it once. */
|
|
21
|
+
readonly id: Id;
|
|
22
|
+
readonly type: UserEventType;
|
|
23
|
+
/**
|
|
24
|
+
* When the write landed: the `createdAt` or `updatedAt` it wrote, or, for
|
|
25
|
+
* a deletion, the time read just before it — not when the listener ran.
|
|
26
|
+
*/
|
|
27
|
+
readonly occurredAt: Date;
|
|
28
|
+
readonly userId: Id;
|
|
29
|
+
readonly userType: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* What `janus({ events })` takes: called once per event, **after** the write
|
|
33
|
+
* landed and before the flow answers — awaited, so a queue that stores the
|
|
34
|
+
* event durably has done so by then. A listener that throws fails nothing:
|
|
35
|
+
* the write happened, and the flow answers as it would have. The failure is a
|
|
36
|
+
* `JANUS_EVENT_FAILED` warning naming the event, never silence.
|
|
37
|
+
*/
|
|
38
|
+
export type UserEventListener = (event: UserEvent) => void | Promise<void>;
|
|
39
|
+
/** The listener given to `janus()`, or a wiring refusal for a JavaScript caller. */
|
|
40
|
+
export declare function resolveEvents(events: unknown, where: string): UserEventListener | null;
|
|
41
|
+
/**
|
|
42
|
+
* Hands one event to the listener after the write it reports. A flow whose
|
|
43
|
+
* steps after the write matter to the listener — a reset's revocation, a
|
|
44
|
+
* deletion's cleanup — runs them in a `try` and emits from its `finally`, so
|
|
45
|
+
* an outage there does not lose the event for good. Its failure is the application's, not the flow's: warned about, with what
|
|
46
|
+
* it takes to send the event again — never thrown, since the write has landed.
|
|
47
|
+
*/
|
|
48
|
+
export declare function emit(context: Context, type: UserEventType, user: {
|
|
49
|
+
readonly id: Id;
|
|
50
|
+
readonly type: string;
|
|
51
|
+
}, occurredAt: Date): Promise<void>;
|
|
52
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/auth/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,EAAU,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GACtB,cAAc,GACd,oBAAoB,GACpB,oBAAoB,GACpB,cAAc,CAAC;AAElB;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACzB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE3E,oFAAoF;AACpF,wBAAgB,aAAa,CAC5B,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,MAAM,GACX,iBAAiB,GAAG,IAAI,CAQ1B;AAED;;;;;;GAMG;AACH,wBAAsB,IAAI,CACzB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAChD,UAAU,EAAE,IAAI,GACd,OAAO,CAAC,IAAI,CAAC,CAoBf"}
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type { CookieConfig, FieldsJson, JanusConfig, MultiTypeConfig, Normalize, PasswordConfig, PasswordHasher, SecondFactorConfig, SessionConfig, SingleTypeConfig, UserSchema, UserTypeConfig, } from './config';
|
|
2
|
+
export type { UserEvent, UserEventListener, UserEventType, } from './events';
|
|
2
3
|
export { bunHasher, scryptHasher } from './hashers';
|
|
3
4
|
export { janus } from './janus';
|
|
4
5
|
export { assertStores } from './port/assert-stores';
|
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,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"}
|
|
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,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,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"}
|
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;AAM3D,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,CA0DV"}
|
package/dist/auth/one-time.d.ts
CHANGED
|
@@ -45,6 +45,13 @@ export declare function refuseStale(type: ResolvedType, user: UserRecord, token:
|
|
|
45
45
|
export declare function refuseUnusable(token: TokenRecord | null, now: Date, where: string, noun: OneTimeNoun): asserts token is TokenRecord;
|
|
46
46
|
/** The refusal for a token whose user is gone, or of another type. */
|
|
47
47
|
export declare const unknownOneTime: (where: string, noun: OneTimeNoun) => TokenError;
|
|
48
|
+
/**
|
|
49
|
+
* The refusal for a challenge whose user is gone, or of another type — the
|
|
50
|
+
* API of the wrong type compares no code. Its attempt was counted all the
|
|
51
|
+
* same, before the type was known, so the last one spends the challenge, as
|
|
52
|
+
* a wrong code would: past it, every call answers `TOKEN_SPENT`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function unknownChallenge(context: Context, token: TokenRecord, secret: string, where: string): Promise<TokenError>;
|
|
48
55
|
/**
|
|
49
56
|
* Spends a token, and refuses it when this call did not: the store answers it
|
|
50
57
|
* **as it was before**, so exactly one call ever reads `spentAt: null`. A
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"one-time.d.ts","sourceRoot":"","sources":["../../src/auth/one-time.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"one-time.d.ts","sourceRoot":"","sources":["../../src/auth/one-time.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Id } from '../ids/id';
|
|
2
|
+
import type { ResolvedType } from './config';
|
|
3
|
+
import { type AnyUser, type Context } from './context';
|
|
4
|
+
import type { UserRecord } from './port/types';
|
|
5
|
+
import type { SignInResult } from './types';
|
|
6
|
+
/**
|
|
7
|
+
* What writing a password ends besides: every second-factor challenge of the
|
|
8
|
+
* user still open, so a sign-in started with the old password cannot be
|
|
9
|
+
* finished. Called **after** the write — the other half of
|
|
10
|
+
* {@link heldByPassword}, which reads **after** it issued.
|
|
11
|
+
*/
|
|
12
|
+
export declare function endSignInsWaiting(context: Context, userId: Id): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Whether the password a sign-in verified is still the user's, once the
|
|
15
|
+
* sign-in answered. A password written meanwhile ends the sign-in: its
|
|
16
|
+
* session is revoked, or its challenge spent, and `false` is answered.
|
|
17
|
+
*
|
|
18
|
+
* A password writer writes, then spends the challenges waiting; a sign-in
|
|
19
|
+
* issues, then reads here. Whichever order they interleave in, one of the two
|
|
20
|
+
* sees the other. A hash that changed with the same password — a concurrent
|
|
21
|
+
* sign-in rehashing it — is not a change: the password is compared again.
|
|
22
|
+
*/
|
|
23
|
+
export declare function heldByPassword(context: Context, type: ResolvedType, verified: UserRecord, password: string, result: SignInResult<AnyUser>, where: string): Promise<boolean>;
|
|
24
|
+
//# sourceMappingURL=password-written.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-written.d.ts","sourceRoot":"","sources":["../../src/auth/password-written.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAGZ,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACtC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,EAAE,GACR,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CACnC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CAkBlB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assert-stores.d.ts","sourceRoot":"","sources":["../../../src/auth/port/assert-stores.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,iBAAiB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"assert-stores.d.ts","sourceRoot":"","sources":["../../../src/auth/port/assert-stores.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAmC9D;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC3B,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,MAAM,GACX,iBAAiB,CAmCnB"}
|
|
@@ -35,7 +35,11 @@
|
|
|
35
35
|
* 5. **Every method is atomic on its own.** Nothing composes into a
|
|
36
36
|
* transaction, and the core never opens one. An adapter may open one
|
|
37
37
|
* *inside* a method — a normalised SQL schema writes several rows per
|
|
38
|
-
* user — but the port exposes none.
|
|
38
|
+
* user — but the port exposes none. And **a read sees every write that
|
|
39
|
+
* completed before it**: never a secondary or a read replica. A sign-in
|
|
40
|
+
* that re-reads the user after answering, and a new code spending the
|
|
41
|
+
* ones issued before it, both count on it — the one promise here no suite
|
|
42
|
+
* can check.
|
|
39
43
|
* 6. **Schema management is not on this interface.** An adapter exposes its own
|
|
40
44
|
* `sync()`; the core never calls it.
|
|
41
45
|
*
|
|
@@ -441,6 +445,24 @@ export interface TokenStore {
|
|
|
441
445
|
* core's decision, after the call; spending the token is `consumeToken`.
|
|
442
446
|
*/
|
|
443
447
|
countAttempt(tokenHash: string, kind: TokenKind): Promise<TokenRecord | null>;
|
|
448
|
+
/**
|
|
449
|
+
* Spends every **unspent** token of one user and one `kind` at `at` —
|
|
450
|
+
* but the one whose hash is `except`, when given — and answers how many
|
|
451
|
+
* it spent. What issuing a sign-in code calls, sparing the code it just
|
|
452
|
+
* issued, so only the last code sent works; and what writing a password
|
|
453
|
+
* calls, so no second-factor challenge opened with the old one survives.
|
|
454
|
+
*
|
|
455
|
+
* - A spent token keeps its `spentAt`: it never changes once set.
|
|
456
|
+
* - A token of another `kind`, or of another user, is not touched.
|
|
457
|
+
* - An expired token is spent all the same, or not counted by a store that
|
|
458
|
+
* already dropped it.
|
|
459
|
+
* - `0` for a user with none: an absence, not a failure.
|
|
460
|
+
*
|
|
461
|
+
* Each token is spent by a conditional write, as `consumeToken` spends
|
|
462
|
+
* one: a token `consumeToken` spends at the same moment is counted by
|
|
463
|
+
* exactly one of the two calls.
|
|
464
|
+
*/
|
|
465
|
+
spendUserTokens(userId: Id, kind: TokenKind, at: Date, except?: string): Promise<number>;
|
|
444
466
|
/**
|
|
445
467
|
* Deletes every token of one user, spent or not, and answers how many.
|
|
446
468
|
* What deleting a user calls: a token holds the e-mail it was sent to, which
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/auth/port/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/auth/port/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D;;;;;;;;GAQG;AACH,MAAM,MAAM,IAAI,GACb,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,IAAI,EAAE,GACf,UAAU,CAAC;AAEd;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAE1D,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC9B,wFAAwF;IACxF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IAClC,4FAA4F;IAC5F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IAC1B,gEAAgE;IAChE,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;;;;OASG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IACzC,iDAAiD;IACjD,QAAQ,CAAC,YAAY,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACjD;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,IAAI,GAAG,IAAI,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAClD,QAAQ,CAAC,eAAe,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACvC;AAED,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC/B,+BAA+B;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC;IAC1B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAED,wDAAwD;AACxD,MAAM,WAAW,SAAS;IACzB;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAEpD,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAE7C;;;;;OAKG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAEzE;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IAElE;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAE7E;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrC;AAED,mEAAmE;AACnE,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;IACpB,qFAAqF;IACrF,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,uCAAuC;IACvC,QAAQ,CAAC,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC5B;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpD,mEAAmE;IACnE,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAEzE;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAE7E;;;;;OAKG;IACH,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEzD;;;;OAIG;IACH,kBAAkB,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE9E;;;;;OAKG;IACH,kBAAkB,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEhD;;;;;;;;OAQG;IACH,qBAAqB,CAAC,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACtD;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,SAAS,GAClB,aAAa,GACb,eAAe,GACf,cAAc,GACd,YAAY,CAAC;AAEhB,yEAAyE;AACzE,MAAM,WAAW,WAAW;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CACzB;AAED,kDAAkD;AAClD,MAAM,WAAW,UAAU;IAC1B;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD;;;;;;;;;;;;;;;;;;OAkBG;IACH,YAAY,CACX,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,IAAI,GACN,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE/B;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE9E;;;;;;;;;;;;;;;;OAgBG;IACH,eAAe,CACd,MAAM,EAAE,EAAE,EACV,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,IAAI,EACR,MAAM,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB;;;;OAIG;IACH,gBAAgB,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC5B;AAED,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CACjC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../../../src/auth/second-factor/challenge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,OAAO,EAAc,MAAM,YAAY,CAAC;AASpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAG/D;;;;GAIG;AACH,wBAAgB,cAAc,CAC7B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM;kBAQvB,UAAU,SACX,MAAM,GACX,OAAO,CAAC,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../../../src/auth/second-factor/challenge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,OAAO,EAAc,MAAM,YAAY,CAAC;AASpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAG/D;;;;GAIG;AACH,wBAAgB,cAAc,CAC7B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM;kBAQvB,UAAU,SACX,MAAM,GACX,OAAO,CAAC,oBAAoB,CAAC;uBAqBP,MAAM,QAAQ,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;EAkE3E"}
|
|
@@ -9,9 +9,12 @@ import type { SignInCodeApi, SignInResult } from './types';
|
|
|
9
9
|
* The code is six digits, so it is guessable where a link is not. What
|
|
10
10
|
* bounds that is the same as for a second factor: the store counts every
|
|
11
11
|
* attempt in one write, before the code is compared, and the fifth wrong one
|
|
12
|
-
* spends the challenge. **
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* spends the challenge. **At most one code is live per user**: `request`
|
|
13
|
+
* spends every other once it issued its own, so concurrent requests cannot
|
|
14
|
+
* each keep one. Yet anybody who knows an e-mail can ask for another — and
|
|
15
|
+
* each request cancels the code before — so the application rate-limits
|
|
16
|
+
* `request`, per address. The code's hash is keyed by the challenge, so the
|
|
17
|
+
* tokens alone do not reveal it.
|
|
15
18
|
*/
|
|
16
19
|
export declare function signInCodeFlows(context: Context, type: ResolvedType, at: (operation: string) => string, finish: (record: UserRecord, where: string) => Promise<SignInResult<AnyUser>>): SignInCodeApi<AnyUser, SignInResult<AnyUser>>['signInCode'];
|
|
17
20
|
//# sourceMappingURL=sign-in-code.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sign-in-code.d.ts","sourceRoot":"","sources":["../../src/auth/sign-in-code.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAKZ,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"sign-in-code.d.ts","sourceRoot":"","sources":["../../src/auth/sign-in-code.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,OAAO,EAKZ,MAAM,WAAW,CAAC;AAanB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE3D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,EACjC,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,GAC3E,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAkF7D"}
|
package/dist/auth/types.d.ts
CHANGED
|
@@ -69,6 +69,12 @@ export interface SecondFactorRequired {
|
|
|
69
69
|
readonly challenge: string;
|
|
70
70
|
/** When the challenge lapses. Five minutes after `signIn`, by default. */
|
|
71
71
|
readonly expiresAt: Date;
|
|
72
|
+
/**
|
|
73
|
+
* Whose sign-in waits for its code — for your logs and your rate limits.
|
|
74
|
+
* **Not for the visitor**: they have proved a password or an e-mail, not
|
|
75
|
+
* yet who they are, so answer them the challenge alone.
|
|
76
|
+
*/
|
|
77
|
+
readonly userId: Id;
|
|
72
78
|
}
|
|
73
79
|
/** What `signIn` answers once a second factor is configured: switch on `status`. */
|
|
74
80
|
export type SignInResult<U> = SignedIn<U> | SecondFactorRequired;
|