@nestjs/authentication 0.0.1

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 (215) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +50 -0
  3. package/dist/account/email-verification.handler.d.ts +23 -0
  4. package/dist/account/email-verification.handler.js +17 -0
  5. package/dist/account/email-verification.service.d.ts +46 -0
  6. package/dist/account/email-verification.service.js +111 -0
  7. package/dist/account/email.util.d.ts +14 -0
  8. package/dist/account/email.util.js +28 -0
  9. package/dist/account/in-memory-email-token.store.d.ts +12 -0
  10. package/dist/account/in-memory-email-token.store.js +60 -0
  11. package/dist/account/password-reset.handler.d.ts +19 -0
  12. package/dist/account/password-reset.handler.js +9 -0
  13. package/dist/account/password-reset.service.d.ts +69 -0
  14. package/dist/account/password-reset.service.js +204 -0
  15. package/dist/authentication.constants.d.ts +13 -0
  16. package/dist/authentication.constants.js +13 -0
  17. package/dist/authentication.module-definition.d.ts +21 -0
  18. package/dist/authentication.module-definition.js +147 -0
  19. package/dist/authentication.module.d.ts +34 -0
  20. package/dist/authentication.module.js +139 -0
  21. package/dist/context/authentication-scope.service.d.ts +39 -0
  22. package/dist/context/authentication-scope.service.js +64 -0
  23. package/dist/context/authentication.context.d.ts +28 -0
  24. package/dist/context/authentication.context.js +58 -0
  25. package/dist/context/index.d.ts +2 -0
  26. package/dist/context/index.js +2 -0
  27. package/dist/decorators/authenticate.decorator.d.ts +10 -0
  28. package/dist/decorators/authenticate.decorator.js +18 -0
  29. package/dist/decorators/current-session.decorator.d.ts +2 -0
  30. package/dist/decorators/current-session.decorator.js +6 -0
  31. package/dist/decorators/current-user.decorator.d.ts +6 -0
  32. package/dist/decorators/current-user.decorator.js +11 -0
  33. package/dist/decorators/index.d.ts +4 -0
  34. package/dist/decorators/index.js +4 -0
  35. package/dist/decorators/public.decorator.d.ts +5 -0
  36. package/dist/decorators/public.decorator.js +6 -0
  37. package/dist/errors/authentication.error.d.ts +27 -0
  38. package/dist/errors/authentication.error.js +33 -0
  39. package/dist/errors/index.d.ts +7 -0
  40. package/dist/errors/index.js +7 -0
  41. package/dist/errors/jwt.error.d.ts +9 -0
  42. package/dist/errors/jwt.error.js +12 -0
  43. package/dist/errors/magic-link.error.d.ts +18 -0
  44. package/dist/errors/magic-link.error.js +21 -0
  45. package/dist/errors/mfa-already-enrolled.error.d.ts +14 -0
  46. package/dist/errors/mfa-already-enrolled.error.js +17 -0
  47. package/dist/errors/oidc.error.d.ts +15 -0
  48. package/dist/errors/oidc.error.js +13 -0
  49. package/dist/errors/refresh-token.error.d.ts +10 -0
  50. package/dist/errors/refresh-token.error.js +12 -0
  51. package/dist/errors/secret-decryption.error.d.ts +3 -0
  52. package/dist/errors/secret-decryption.error.js +6 -0
  53. package/dist/events/authentication-events.interface.d.ts +121 -0
  54. package/dist/events/authentication-events.interface.js +1 -0
  55. package/dist/events/authentication-events.service.d.ts +19 -0
  56. package/dist/events/authentication-events.service.js +39 -0
  57. package/dist/events/authentication.channels.d.ts +4 -0
  58. package/dist/events/authentication.channels.js +11 -0
  59. package/dist/events/index.d.ts +3 -0
  60. package/dist/events/index.js +3 -0
  61. package/dist/guards/authentication.guard.d.ts +57 -0
  62. package/dist/guards/authentication.guard.js +171 -0
  63. package/dist/guards/index.d.ts +1 -0
  64. package/dist/guards/index.js +1 -0
  65. package/dist/index.d.ts +52 -0
  66. package/dist/index.js +52 -0
  67. package/dist/interceptors/authentication-scope.interceptor.d.ts +20 -0
  68. package/dist/interceptors/authentication-scope.interceptor.js +48 -0
  69. package/dist/interceptors/index.d.ts +1 -0
  70. package/dist/interceptors/index.js +1 -0
  71. package/dist/interfaces/api-key.interface.d.ts +41 -0
  72. package/dist/interfaces/api-key.interface.js +1 -0
  73. package/dist/interfaces/authenticate-options.interface.d.ts +31 -0
  74. package/dist/interfaces/authenticate-options.interface.js +1 -0
  75. package/dist/interfaces/authentication-error-options.interface.d.ts +8 -0
  76. package/dist/interfaces/authentication-error-options.interface.js +1 -0
  77. package/dist/interfaces/authentication-module-options.interface.d.ts +58 -0
  78. package/dist/interfaces/authentication-module-options.interface.js +1 -0
  79. package/dist/interfaces/authentication-registry.interface.d.ts +41 -0
  80. package/dist/interfaces/authentication-registry.interface.js +1 -0
  81. package/dist/interfaces/authentication-result.interface.d.ts +25 -0
  82. package/dist/interfaces/authentication-result.interface.js +1 -0
  83. package/dist/interfaces/authentication-storage.interface.d.ts +29 -0
  84. package/dist/interfaces/authentication-storage.interface.js +1 -0
  85. package/dist/interfaces/duration.interface.d.ts +2 -0
  86. package/dist/interfaces/duration.interface.js +1 -0
  87. package/dist/interfaces/email-token-store.interface.d.ts +52 -0
  88. package/dist/interfaces/email-token-store.interface.js +1 -0
  89. package/dist/interfaces/email-verification.interface.d.ts +18 -0
  90. package/dist/interfaces/email-verification.interface.js +1 -0
  91. package/dist/interfaces/index.d.ts +27 -0
  92. package/dist/interfaces/index.js +27 -0
  93. package/dist/interfaces/jwt-options.interface.d.ts +68 -0
  94. package/dist/interfaces/jwt-options.interface.js +1 -0
  95. package/dist/interfaces/jwt.interface.d.ts +36 -0
  96. package/dist/interfaces/jwt.interface.js +1 -0
  97. package/dist/interfaces/magic-link-store.interface.d.ts +36 -0
  98. package/dist/interfaces/magic-link-store.interface.js +1 -0
  99. package/dist/interfaces/magic-link.interface.d.ts +55 -0
  100. package/dist/interfaces/magic-link.interface.js +1 -0
  101. package/dist/interfaces/mfa-options.interface.d.ts +44 -0
  102. package/dist/interfaces/mfa-options.interface.js +1 -0
  103. package/dist/interfaces/mfa-store.interface.d.ts +70 -0
  104. package/dist/interfaces/mfa-store.interface.js +1 -0
  105. package/dist/interfaces/oidc-provider.interface.d.ts +56 -0
  106. package/dist/interfaces/oidc-provider.interface.js +1 -0
  107. package/dist/interfaces/oidc-state-store.interface.d.ts +25 -0
  108. package/dist/interfaces/oidc-state-store.interface.js +1 -0
  109. package/dist/interfaces/oidc.interface.d.ts +84 -0
  110. package/dist/interfaces/oidc.interface.js +1 -0
  111. package/dist/interfaces/password-hasher-options.interface.d.ts +17 -0
  112. package/dist/interfaces/password-hasher-options.interface.js +1 -0
  113. package/dist/interfaces/password-reset.interface.d.ts +49 -0
  114. package/dist/interfaces/password-reset.interface.js +1 -0
  115. package/dist/interfaces/refresh-token-options.interface.d.ts +10 -0
  116. package/dist/interfaces/refresh-token-options.interface.js +1 -0
  117. package/dist/interfaces/refresh-token-store.interface.d.ts +61 -0
  118. package/dist/interfaces/refresh-token-store.interface.js +1 -0
  119. package/dist/interfaces/session-store.interface.d.ts +53 -0
  120. package/dist/interfaces/session-store.interface.js +1 -0
  121. package/dist/interfaces/session.interface.d.ts +50 -0
  122. package/dist/interfaces/session.interface.js +1 -0
  123. package/dist/interfaces/sign-in-options.interface.d.ts +9 -0
  124. package/dist/interfaces/sign-in-options.interface.js +1 -0
  125. package/dist/interfaces/token.interface.d.ts +30 -0
  126. package/dist/interfaces/token.interface.js +1 -0
  127. package/dist/jwt/amr.util.d.ts +9 -0
  128. package/dist/jwt/amr.util.js +11 -0
  129. package/dist/jwt/in-memory-refresh-token.store.d.ts +29 -0
  130. package/dist/jwt/in-memory-refresh-token.store.js +67 -0
  131. package/dist/jwt/jwks.client.d.ts +34 -0
  132. package/dist/jwt/jwks.client.js +154 -0
  133. package/dist/jwt/jws.util.d.ts +45 -0
  134. package/dist/jwt/jws.util.js +282 -0
  135. package/dist/jwt/jwt-bearer.provider.d.ts +48 -0
  136. package/dist/jwt/jwt-bearer.provider.js +126 -0
  137. package/dist/jwt/jwt-signer.service.d.ts +19 -0
  138. package/dist/jwt/jwt-signer.service.js +36 -0
  139. package/dist/jwt/jwt-verifier.service.d.ts +22 -0
  140. package/dist/jwt/jwt-verifier.service.js +109 -0
  141. package/dist/jwt/token.service.d.ts +81 -0
  142. package/dist/jwt/token.service.js +230 -0
  143. package/dist/magic-link/in-memory-magic-link.store.d.ts +12 -0
  144. package/dist/magic-link/in-memory-magic-link.store.js +45 -0
  145. package/dist/magic-link/magic-link.handler.d.ts +25 -0
  146. package/dist/magic-link/magic-link.handler.js +14 -0
  147. package/dist/magic-link/magic-link.service.d.ts +79 -0
  148. package/dist/magic-link/magic-link.service.js +215 -0
  149. package/dist/mfa/in-memory-mfa.store.d.ts +25 -0
  150. package/dist/mfa/in-memory-mfa.store.js +73 -0
  151. package/dist/mfa/mfa.service.d.ts +104 -0
  152. package/dist/mfa/mfa.service.js +346 -0
  153. package/dist/mfa/otp.util.d.ts +7 -0
  154. package/dist/mfa/otp.util.js +52 -0
  155. package/dist/mfa/secret-cipher.service.d.ts +28 -0
  156. package/dist/mfa/secret-cipher.service.js +106 -0
  157. package/dist/oidc/in-memory-oidc-state.store.d.ts +13 -0
  158. package/dist/oidc/in-memory-oidc-state.store.js +45 -0
  159. package/dist/oidc/oidc-account.resolver.d.ts +23 -0
  160. package/dist/oidc/oidc-account.resolver.js +16 -0
  161. package/dist/oidc/oidc.client.d.ts +44 -0
  162. package/dist/oidc/oidc.client.js +286 -0
  163. package/dist/oidc/oidc.presets.d.ts +24 -0
  164. package/dist/oidc/oidc.presets.js +53 -0
  165. package/dist/oidc/oidc.service.d.ts +88 -0
  166. package/dist/oidc/oidc.service.js +259 -0
  167. package/dist/providers/api-key.provider.d.ts +51 -0
  168. package/dist/providers/api-key.provider.js +93 -0
  169. package/dist/providers/authentication.provider.d.ts +40 -0
  170. package/dist/providers/authentication.provider.js +33 -0
  171. package/dist/providers/index.d.ts +2 -0
  172. package/dist/providers/index.js +2 -0
  173. package/dist/services/authentication-registry.service.d.ts +75 -0
  174. package/dist/services/authentication-registry.service.js +235 -0
  175. package/dist/services/index.d.ts +3 -0
  176. package/dist/services/index.js +3 -0
  177. package/dist/services/password-hasher.service.d.ts +47 -0
  178. package/dist/services/password-hasher.service.js +170 -0
  179. package/dist/services/ws-authenticator.service.d.ts +38 -0
  180. package/dist/services/ws-authenticator.service.js +92 -0
  181. package/dist/session/cookies.util.d.ts +34 -0
  182. package/dist/session/cookies.util.js +82 -0
  183. package/dist/session/in-memory-session.store.d.ts +33 -0
  184. package/dist/session/in-memory-session.store.js +60 -0
  185. package/dist/session/session-cookie.provider.d.ts +36 -0
  186. package/dist/session/session-cookie.provider.js +58 -0
  187. package/dist/session/session.service.d.ts +97 -0
  188. package/dist/session/session.service.js +208 -0
  189. package/dist/session/sign-in.service.d.ts +87 -0
  190. package/dist/session/sign-in.service.js +206 -0
  191. package/dist/storage/authentication.storage.d.ts +130 -0
  192. package/dist/storage/authentication.storage.js +350 -0
  193. package/dist/storage/index.d.ts +1 -0
  194. package/dist/storage/index.js +1 -0
  195. package/dist/testing/index.d.ts +39 -0
  196. package/dist/testing/index.js +531 -0
  197. package/dist/utils/api-key.util.d.ts +10 -0
  198. package/dist/utils/api-key.util.js +10 -0
  199. package/dist/utils/auth-state.util.d.ts +54 -0
  200. package/dist/utils/auth-state.util.js +209 -0
  201. package/dist/utils/bearer.util.d.ts +9 -0
  202. package/dist/utils/bearer.util.js +21 -0
  203. package/dist/utils/cross-origin.util.d.ts +29 -0
  204. package/dist/utils/cross-origin.util.js +90 -0
  205. package/dist/utils/crypto.util.d.ts +19 -0
  206. package/dist/utils/crypto.util.js +38 -0
  207. package/dist/utils/duration.util.d.ts +9 -0
  208. package/dist/utils/duration.util.js +44 -0
  209. package/dist/utils/index.d.ts +8 -0
  210. package/dist/utils/index.js +8 -0
  211. package/dist/utils/options.util.d.ts +20 -0
  212. package/dist/utils/options.util.js +44 -0
  213. package/dist/utils/transport-errors.util.d.ts +33 -0
  214. package/dist/utils/transport-errors.util.js +70 -0
  215. package/package.json +108 -0
@@ -0,0 +1,206 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { ForbiddenException, Injectable, Optional } from '@nestjs/common';
14
+ import { HttpAdapterHost } from '@nestjs/core';
15
+ import { AuthenticationScope } from '../context/authentication-scope.service.js';
16
+ import { AuthenticationEvents } from '../events/authentication-events.service.js';
17
+ import { TokenService } from '../jwt/token.service.js';
18
+ import { MfaService } from '../mfa/mfa.service.js';
19
+ import { sha256 } from '../utils/crypto.util.js';
20
+ import { SessionService } from './session.service.js';
21
+ /**
22
+ * The browser's side of signing in. Called from an HTTP handler (or a
23
+ * GraphQL resolver whose context has `req` and `res`), each method reads
24
+ * this browser's session cookie from the request and sets the new one on
25
+ * the response, on Express and Fastify alike. Elsewhere, nothing is read or
26
+ * set: send the returned `cookie` yourself.
27
+ *
28
+ * `signIn()` is the one place a first factor (password, magic link, OIDC)
29
+ * turns into a session:
30
+ * - a sign-in posted from another origin's page is refused with a 403
31
+ * (login CSRF: signing the victim's browser in to the attacker's
32
+ * account), by the same rule as `app.enableCsrfProtection()`;
33
+ * - the browser's previous session is deleted (session fixation defence);
34
+ * - users with a confirmed authenticator get an `mfa: 'pending'` session,
35
+ * which is not signed in anywhere until `completeMfa()` verifies a code.
36
+ */
37
+ let SignInService = class SignInService {
38
+ constructor(sessions, mfa, tokens, scope = new AuthenticationScope(), adapterHost, events = new AuthenticationEvents()) {
39
+ this.sessions = sessions;
40
+ this.mfa = mfa;
41
+ this.tokens = tokens;
42
+ this.scope = scope;
43
+ this.adapterHost = adapterHost;
44
+ this.events = events;
45
+ }
46
+ /**
47
+ * Signs the user in on this browser. Throws a `ForbiddenException` for a
48
+ * request that changes state from another origin than the app's own and
49
+ * `session.trustedOrigins`.
50
+ */
51
+ async signIn(userId, { method, metadata } = {}) {
52
+ const exchange = this.scope.exchange();
53
+ this.refuseCrossOrigin(exchange?.request);
54
+ const mfa = (await this.mfa.isEnrolled(userId)) ? 'pending' : undefined;
55
+ const stored = { ...this.sessions.metadataFor(exchange?.request), ...metadata };
56
+ const issued = await this.sessions.create(userId, {
57
+ mfa,
58
+ metadata: Object.keys(stored).length ? stored : undefined,
59
+ replacing: this.sessions.tokenFrom(exchange?.request),
60
+ });
61
+ this.setCookie(exchange, issued.cookie);
62
+ this.events.emit({
63
+ type: 'sign-in',
64
+ userId,
65
+ sessionId: issued.session.id,
66
+ ...(method && { method }),
67
+ ...(mfa && { mfa }),
68
+ ...(issued.session.metadata && { metadata: issued.session.metadata }),
69
+ });
70
+ return issued;
71
+ }
72
+ /**
73
+ * Completes the second factor of this browser's session with a TOTP code
74
+ * or a recovery code, and rotates the session to `mfa: 'verified'` under a
75
+ * new id. `null` when the browser has no session or the code is wrong. A
76
+ * request with neither counts nothing against the user's lockout, as
77
+ * `TokenService.issue()` without a `secondFactor` doesn't.
78
+ */
79
+ async completeMfa({ code, recoveryCode }) {
80
+ if (!code && !recoveryCode) {
81
+ return null;
82
+ }
83
+ const exchange = this.scope.exchange();
84
+ const session = await this.sessions.validate(this.sessions.tokenFrom(exchange?.request));
85
+ if (!session) {
86
+ return null;
87
+ }
88
+ const verified = recoveryCode
89
+ ? await this.mfa.verifyRecoveryCode(session.userId, recoveryCode)
90
+ : await this.mfa.verifyTotp(session.userId, code);
91
+ if (!verified) {
92
+ return null;
93
+ }
94
+ // A revocation that took the session meanwhile wins: no verified session comes of it.
95
+ const issued = await this.sessions.rotate(session, { mfa: 'verified' });
96
+ if (issued) {
97
+ this.setCookie(exchange, issued.cookie);
98
+ }
99
+ return issued;
100
+ }
101
+ /**
102
+ * Confirms the user's new authenticator with a code from it
103
+ * (`MfaService.confirm()`), and, when this browser holds a session of the
104
+ * user, rotates it to `mfa: 'verified'` under a new id: the code proved
105
+ * this browser has the authenticator, so the user isn't asked for another
106
+ * code until their next sign-in. Without such a session (a token client,
107
+ * another user's session), it only confirms. `false` when the code is
108
+ * wrong, and nothing changes.
109
+ */
110
+ async confirmMfa(userId, code) {
111
+ if (!(await this.mfa.confirm(userId, code))) {
112
+ return false;
113
+ }
114
+ const exchange = this.scope.exchange();
115
+ const session = await this.sessions.validate(this.sessions.tokenFrom(exchange?.request));
116
+ if (session?.userId === userId) {
117
+ const issued = await this.sessions.rotate(session, { mfa: 'verified' });
118
+ if (issued) {
119
+ this.setCookie(exchange, issued.cookie);
120
+ }
121
+ }
122
+ return true;
123
+ }
124
+ /**
125
+ * Gives this browser's session a new id, keeping its user, expiry and
126
+ * second factor, and updates the cookie. Call it on privilege changes: a
127
+ * new password, a new role. `null` when the browser has no session, or
128
+ * lost it meanwhile (revoked, or rotated by another request).
129
+ */
130
+ async rotateSession() {
131
+ const exchange = this.scope.exchange();
132
+ const session = await this.sessions.validate(this.sessions.tokenFrom(exchange?.request));
133
+ if (!session) {
134
+ return null;
135
+ }
136
+ const issued = await this.sessions.rotate(session);
137
+ if (issued) {
138
+ this.setCookie(exchange, issued.cookie);
139
+ }
140
+ return issued;
141
+ }
142
+ /**
143
+ * Ends this browser's session, pending or not, and clears its cookie.
144
+ * `false` when the browser had no live session (a bearer-token client, an
145
+ * expired cookie).
146
+ */
147
+ async signOut() {
148
+ const exchange = this.scope.exchange();
149
+ const token = this.sessions.tokenFrom(exchange?.request);
150
+ if (!token) {
151
+ return false;
152
+ }
153
+ const session = await this.sessions.validate(token);
154
+ this.setCookie(exchange, this.sessions.clearCookie());
155
+ // Deleted whatever this instance makes of it: idle here, it may still be live for another
156
+ // instance (its clock, or another idleTtl during a rolling deploy).
157
+ await this.sessions.discard(sha256(token));
158
+ if (!session) {
159
+ return false;
160
+ }
161
+ this.events.emit({ type: 'sign-out', userId: session.userId, sessionId: session.id });
162
+ return true;
163
+ }
164
+ /**
165
+ * Ends every session and refresh-token family of the user, and clears
166
+ * this browser's cookie if it was one of them. API keys live in your own
167
+ * table: revoke those yourself.
168
+ */
169
+ async signOutEverywhere(userId) {
170
+ const exchange = this.scope.exchange();
171
+ const own = await this.sessions.validate(this.sessions.tokenFrom(exchange?.request));
172
+ await this.sessions.revokeAll(userId);
173
+ await this.tokens.revokeAll(userId);
174
+ if (own?.userId === userId) {
175
+ this.setCookie(exchange, this.sessions.clearCookie());
176
+ }
177
+ this.events.emit({ type: 'sign-out', userId, everywhere: true });
178
+ }
179
+ /**
180
+ * @internal The 403 `signIn()` answers a request that changes state from
181
+ * another origin than the app's own and `session.trustedOrigins` with.
182
+ * What binds a sign-in to a browser (a magic link's `create()`) checks it
183
+ * too: another site's page must not start one in the victim's browser.
184
+ */
185
+ refuseCrossOrigin(request) {
186
+ if (request && this.sessions.isCrossOriginWrite(request)) {
187
+ throw new ForbiddenException('Cross-origin sign-in refused');
188
+ }
189
+ }
190
+ setCookie(exchange, cookie) {
191
+ if (exchange?.response) {
192
+ this.adapterHost?.httpAdapter?.appendHeader(exchange.response, 'Set-Cookie', cookie);
193
+ }
194
+ }
195
+ };
196
+ SignInService = __decorate([
197
+ Injectable(),
198
+ __param(4, Optional()),
199
+ __metadata("design:paramtypes", [SessionService,
200
+ MfaService,
201
+ TokenService,
202
+ AuthenticationScope,
203
+ HttpAdapterHost,
204
+ AuthenticationEvents])
205
+ ], SignInService);
206
+ export { SignInService };
@@ -0,0 +1,130 @@
1
+ import type { EmailTokenStore } from '../interfaces/email-token-store.interface.js';
2
+ import type { RefreshTokenStore } from '../interfaces/refresh-token-store.interface.js';
3
+ import type { MagicLinkStore } from '../interfaces/magic-link-store.interface.js';
4
+ import type { MfaStore } from '../interfaces/mfa-store.interface.js';
5
+ import type { OidcStateStore } from '../interfaces/oidc-state-store.interface.js';
6
+ import type { SessionStore } from '../interfaces/session-store.interface.js';
7
+ import type { AuthenticationStorageSources, AuthenticationStorageContract, AuthenticationStorageRegisterOptions } from '../interfaces/authentication-storage.interface.js';
8
+ /**
9
+ * @internal What each feature reads or writes, audited against the code
10
+ * paths: the production guard's rule.
11
+ * Any feature that signs someone in reads `mfa`, configured or not: a user
12
+ * may have enrolled an authenticator through another instance, and
13
+ * `MfaService.isEnrolled()` is how a sign-in finds out. Any feature that
14
+ * revokes a user's sign-ins reaches both `sessions` and `refreshTokens`.
15
+ */
16
+ export declare const CONTRACTS_BY_FEATURE: {
17
+ /**
18
+ * A `SessionCookieProvider` in `providers`: `SessionService` (every
19
+ * request), `SignInService.signIn()` (`isEnrolled()`), `completeMfa()`,
20
+ * and `signOutEverywhere()`, which also revokes the user's refresh-token
21
+ * families.
22
+ */
23
+ readonly sessionCookie: readonly ["sessions", "refreshTokens", "mfa"];
24
+ /** `accessToken`: `TokenService` (refresh-token families), whose `issue()` checks for an authenticator. */
25
+ readonly accessToken: readonly ["refreshTokens", "mfa"];
26
+ /** `mfa`: enrollment, codes, recovery codes and the lockout. */
27
+ readonly mfa: readonly ["mfa"];
28
+ /** `magicLinkHandler`: pending links, then `SignInService.signIn()`. */
29
+ readonly magicLink: readonly ["sessions", "mfa", "magicLinks"];
30
+ /** `oidcAccountResolver`: logins in progress, the session that links an account, then `SignInService.signIn()`. */
31
+ readonly oidc: readonly ["sessions", "mfa", "oidcStates"];
32
+ /**
33
+ * `passwordResetHandler`: the links; `reset()` revokes every session and
34
+ * refresh-token family of the user, and with `signIn: true` signs in.
35
+ */
36
+ readonly passwordReset: readonly ["sessions", "refreshTokens", "mfa", "emailTokens"];
37
+ /** `emailVerificationHandler`: the links. */
38
+ readonly emailVerification: readonly ["emailTokens"];
39
+ };
40
+ /** @internal */
41
+ export type AuthenticationFeature = keyof typeof CONTRACTS_BY_FEATURE;
42
+ /** @internal The contracts the features use, in the order messages list them. */
43
+ export declare function contractsUsedBy(features: Iterable<AuthenticationFeature>): AuthenticationStorageContract[];
44
+ /** @internal What the configured features need from storage, computed by the module from its options. */
45
+ export interface AuthenticationStorageRequirements {
46
+ /** The contracts a configured feature uses ({@link contractsUsedBy}): the production guard checks these at startup. */
47
+ contracts: AuthenticationStorageContract[];
48
+ allowInMemoryStorage: boolean;
49
+ }
50
+ interface ContractSpec {
51
+ interfaceName: string;
52
+ /** What is lost with the in-memory default, for the production guard. */
53
+ holds: string;
54
+ methods: readonly string[];
55
+ inMemory: () => object;
56
+ }
57
+ /** @internal Every contract, in the order they are listed in messages. */
58
+ export declare const STORAGE_CONTRACTS: Record<AuthenticationStorageContract, ContractSpec>;
59
+ /** @internal Locks the registry. `AuthenticationModule.onModuleInit()` and the first read call it. */
60
+ export declare const LOCK_STORAGE: unique symbol;
61
+ /**
62
+ * Where the module keeps its state. The app registers its own stores here,
63
+ * from the constructor of an ordinary provider:
64
+ *
65
+ * ```ts
66
+ * @Injectable()
67
+ * export class DrizzleAuthenticationStore implements SessionStore, RefreshTokenStore, MfaStore {
68
+ * constructor(@Inject(DRIZZLE) private readonly db: Database, storage: AuthenticationStorage) {
69
+ * storage.registerSource({ sessions: this, refreshTokens: this, mfa: this });
70
+ * }
71
+ * // ...
72
+ * }
73
+ * ```
74
+ *
75
+ * A contract no source registered uses the in-memory store, so an app that
76
+ * imports the module boots with no storage configured. The registry locks
77
+ * in `AuthenticationModule`'s `onModuleInit` (every provider constructor has
78
+ * run by then), or at the first read of a store if that is earlier (another
79
+ * module's `onModuleInit`): it logs the active sources, and in production
80
+ * refuses to start while a contract a configured feature uses has no
81
+ * source, unless `allowInMemoryStorage` is set. In production, a read of
82
+ * any other contract without a source (an app calling a service outside
83
+ * the features it configured) fails the same way at that read, instead of
84
+ * running on the in-memory default.
85
+ */
86
+ export declare class AuthenticationStorage {
87
+ private readonly requirements?;
88
+ private static readonly logger;
89
+ private readonly registered;
90
+ private readonly active;
91
+ private locked;
92
+ constructor(requirements?: AuthenticationStorageRequirements | undefined);
93
+ /**
94
+ * Registers stores by contract: `{ sessions: this, refreshTokens: this }`.
95
+ * Call it from the constructor of a singleton provider. Throws, registering
96
+ * nothing, when a store lacks one of its contract's methods, when a
97
+ * contract already has a source (unless `replace` is set: tests,
98
+ * wrappers), and once the registry has locked.
99
+ */
100
+ registerSource(sources: AuthenticationStorageSources, options?: AuthenticationStorageRegisterOptions): void;
101
+ /** The active session store: the registered one, else the in-memory default. Reading it locks the registry. */
102
+ get sessions(): SessionStore;
103
+ get refreshTokens(): RefreshTokenStore;
104
+ get mfa(): MfaStore;
105
+ get magicLinks(): MagicLinkStore;
106
+ get oidcStates(): OidcStateStore;
107
+ get emailTokens(): EmailTokenStore;
108
+ /**
109
+ * @internal Freezes the sources, logs them, and enforces the production
110
+ * guard (which leaves the registry open): in production, a contract in use
111
+ * with no source fails unless in-memory storage was allowed. `log: false`
112
+ * for the contract suite, which builds a registry per case.
113
+ */
114
+ [LOCK_STORAGE]({ log }?: {
115
+ log?: boolean;
116
+ }): void;
117
+ private source;
118
+ /**
119
+ * In production, unless `allowInMemoryStorage` is set. A registry built
120
+ * with `new`, outside the module, has no options: it refuses too.
121
+ */
122
+ private refusesInMemory;
123
+ /**
124
+ * The in-memory default, `DrizzleAuthenticationStore` (one source for every
125
+ * contract), or the contracts in use or registered, by source:
126
+ * `RedisSessionStore (sessions); DrizzleAuthenticationStore (mfa); in-memory (oidcStates)`.
127
+ */
128
+ private summary;
129
+ }
130
+ export {};