@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,41 @@
1
+ import type { EmailVerificationHandler } from '../account/email-verification.handler.js';
2
+ import type { PasswordResetHandler } from '../account/password-reset.handler.js';
3
+ import type { MagicLinkHandler } from '../magic-link/magic-link.handler.js';
4
+ import type { OidcAccountResolver } from '../oidc/oidc-account.resolver.js';
5
+ import type { AuthenticationProvider } from '../providers/authentication.provider.js';
6
+ /**
7
+ * The feature handlers, by the name of the module option each one goes
8
+ * with: what `registerHandler()` takes. A feature needs both, its option and
9
+ * its handler, or the module refuses to start.
10
+ */
11
+ export interface AuthenticationHandlers {
12
+ /** Delivers verification links and records verified addresses. */
13
+ emailVerification: EmailVerificationHandler;
14
+ /** Finds accounts, delivers reset links and stores new passwords. */
15
+ passwordReset: PasswordResetHandler;
16
+ /** Delivers magic links and maps an address to a user. */
17
+ magicLink: MagicLinkHandler;
18
+ /** Maps an OpenID Connect identity to a user. */
19
+ oidc: OidcAccountResolver;
20
+ }
21
+ export type AuthenticationHandlerName = keyof AuthenticationHandlers;
22
+ /** `registerProvider()` options. */
23
+ export interface RegisterProviderOptions {
24
+ /**
25
+ * Where the provider runs in the chain: ascending, the first provider that
26
+ * returns a user wins. Default `0`. Two providers can't share an order.
27
+ */
28
+ order?: number;
29
+ /** Replace the provider registered at the same `order` (tests, a wrapper around it). */
30
+ replace?: boolean;
31
+ }
32
+ /** `registerHandler()` options. */
33
+ export interface RegisterHandlerOptions {
34
+ /** Replace the handler already registered for the feature (tests, a wrapper around it). */
35
+ replace?: boolean;
36
+ }
37
+ /**
38
+ * What the guard calls: an `AuthenticationProvider` subclass, or any object
39
+ * with its `authenticate()` (and optional `challenge()`).
40
+ */
41
+ export type CredentialProvider<TUser = any, TSession = any> = Pick<AuthenticationProvider<TUser, TSession>, 'authenticate' | 'challenge'>;
@@ -0,0 +1,25 @@
1
+ import type { AuthenticationTypes } from '../index.js';
2
+ /**
3
+ * The user type the app declared by augmenting {@link AuthenticationTypes}.
4
+ * Falls back to a string-keyed record when nothing was declared.
5
+ */
6
+ export type AuthenticatedUser = AuthenticationTypes extends {
7
+ user: infer U;
8
+ } ? U : Record<string, unknown>;
9
+ /** The session type declared on {@link AuthenticationTypes}, `unknown` otherwise. */
10
+ export type AuthenticatedSession = AuthenticationTypes extends {
11
+ session: infer S;
12
+ } ? S : unknown;
13
+ /**
14
+ * `pending`: first factor done, second factor outstanding. Such a result
15
+ * does not count as signed in: `SignInService.completeMfa()` finishes it.
16
+ * `verified`: a second factor was presented. Required by
17
+ * `@Authenticate({ mfa: true })`.
18
+ */
19
+ export type MfaState = 'pending' | 'verified';
20
+ export interface AuthenticationResult<TUser = AuthenticatedUser, TSession = AuthenticatedSession> {
21
+ user: TUser;
22
+ /** Whatever the provider considers the session: a stored record, JWT claims, an `ApiKeySession`. */
23
+ session?: TSession;
24
+ mfa?: MfaState;
25
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,29 @@
1
+ import type { EmailTokenStore } from './email-token-store.interface.js';
2
+ import type { RefreshTokenStore } from './refresh-token-store.interface.js';
3
+ import type { MagicLinkStore } from './magic-link-store.interface.js';
4
+ import type { MfaStore } from './mfa-store.interface.js';
5
+ import type { OidcStateStore } from './oidc-state-store.interface.js';
6
+ import type { SessionStore } from './session-store.interface.js';
7
+ /**
8
+ * The storage contracts, by name: what `registerSource()` takes. One
9
+ * provider may implement several (`{ sessions: this, refreshTokens: this }`),
10
+ * or several providers split them (sessions in Redis, the rest in SQL).
11
+ */
12
+ export interface AuthenticationStorageSources {
13
+ sessions?: SessionStore;
14
+ refreshTokens?: RefreshTokenStore;
15
+ /** Authenticators, recovery codes and failed attempts. */
16
+ mfa?: MfaStore;
17
+ /** Pending magic links. */
18
+ magicLinks?: MagicLinkStore;
19
+ /** OAuth / OpenID Connect logins in progress. */
20
+ oidcStates?: OidcStateStore;
21
+ /** Pending password reset and email verification links. */
22
+ emailTokens?: EmailTokenStore;
23
+ }
24
+ export type AuthenticationStorageContract = keyof AuthenticationStorageSources;
25
+ /** `registerSource()` options. */
26
+ export interface AuthenticationStorageRegisterOptions {
27
+ /** Replace the source of a contract that is already registered (tests, a wrapper around it). */
28
+ replace?: boolean;
29
+ }
@@ -0,0 +1,2 @@
1
+ /** Milliseconds, or a string such as `"250ms"`, `"30s"`, `"15m"`, `"6h"`, `"3d"`, `"1w"`. */
2
+ export type Duration = number | `${number}${'ms' | 's' | 'm' | 'h' | 'd' | 'w'}`;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,52 @@
1
+ /** What a mailed token proves when it comes back. */
2
+ export type EmailTokenPurpose = 'password-reset' | 'email-verification';
3
+ /**
4
+ * A token sent by email to prove control of an address: a password reset
5
+ * link, or an email verification link. Stored by the SHA-256 of the token;
6
+ * the token itself only exists in the email.
7
+ */
8
+ export interface EmailTokenRecord {
9
+ /** SHA-256 of the token. */
10
+ id: string;
11
+ purpose: EmailTokenPurpose;
12
+ userId: string;
13
+ /** The address the token was sent to, and the only one it works for. */
14
+ email: string;
15
+ /**
16
+ * Password resets: SHA-256 of the user's password hash when the link was
17
+ * sent, so a password change (by any route) invalidates the link.
18
+ */
19
+ fingerprint?: string;
20
+ createdAt: Date;
21
+ expiresAt: Date;
22
+ }
23
+ /**
24
+ * Storage for password reset and email verification tokens. Implement it
25
+ * on your database or Redis, and register the provider with
26
+ * `AuthenticationStorage.registerSource({ emailTokens: this })`.
27
+ *
28
+ * `consumeEmailToken()` must be one atomic get-and-delete
29
+ * (`DELETE … RETURNING`, `GETDEL`), so a link works once however many
30
+ * requests present it. Anyone can ask for a reset link, so the store must
31
+ * stay bounded: drop expired tokens as new ones are saved, and cap the
32
+ * rest. Each method's comment has its rule, and
33
+ * `authenticationStoreContract()` from `@nestjs/authentication/testing`
34
+ * checks them.
35
+ */
36
+ export interface EmailTokenStore {
37
+ /**
38
+ * Saves a new token (a fresh random id: a plain insert), then keeps the
39
+ * store bounded: deletes tokens whose `expiresAt` is at or before this
40
+ * one's `createdAt`, and past a cap, those that expire first.
41
+ */
42
+ saveEmailToken(record: EmailTokenRecord): Promise<void>;
43
+ /**
44
+ * Removes and returns the token if it exists and was issued for
45
+ * `purpose`, in one atomic step; `undefined` otherwise, leaving a token of
46
+ * another purpose in place. Of several concurrent calls, exactly one gets
47
+ * the record. Expired tokens may be returned: the services check expiry.
48
+ */
49
+ consumeEmailToken(id: string, purpose: EmailTokenPurpose): Promise<EmailTokenRecord | undefined>;
50
+ /** Deletes the user's outstanding tokens for `purpose` (after a reset, the other reset links). */
51
+ deleteUserEmailTokens(userId: string, purpose: EmailTokenPurpose): Promise<void>;
52
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ import type { Duration } from './duration.interface.js';
2
+ /** What `EmailVerificationHandler.send()` delivers. */
3
+ export interface EmailVerificationLink {
4
+ userId: string;
5
+ /** The address to verify, and to send the link to. */
6
+ email: string;
7
+ /** `emailVerification.url` with `?token=…`. */
8
+ url: string;
9
+ expiresAt: Date;
10
+ }
11
+ export interface EmailVerificationOptions {
12
+ /** Page that receives `?token=…` and POSTs it back, e.g. `https://app.example.com/verify-email`. */
13
+ url: string;
14
+ /** Lifetime of a link. Default `'24h'`. */
15
+ ttl?: Duration;
16
+ /** Clock in epoch milliseconds, for tests. */
17
+ now?: () => number;
18
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,27 @@
1
+ export * from './api-key.interface.js';
2
+ export * from './authenticate-options.interface.js';
3
+ export * from './authentication-error-options.interface.js';
4
+ export * from './authentication-module-options.interface.js';
5
+ export * from './authentication-registry.interface.js';
6
+ export * from './authentication-result.interface.js';
7
+ export * from './authentication-storage.interface.js';
8
+ export * from './duration.interface.js';
9
+ export * from './email-token-store.interface.js';
10
+ export * from './email-verification.interface.js';
11
+ export * from './jwt-options.interface.js';
12
+ export * from './jwt.interface.js';
13
+ export * from './magic-link-store.interface.js';
14
+ export * from './magic-link.interface.js';
15
+ export * from './mfa-options.interface.js';
16
+ export * from './mfa-store.interface.js';
17
+ export * from './oidc-provider.interface.js';
18
+ export * from './oidc-state-store.interface.js';
19
+ export * from './oidc.interface.js';
20
+ export * from './password-hasher-options.interface.js';
21
+ export * from './password-reset.interface.js';
22
+ export * from './refresh-token-options.interface.js';
23
+ export * from './refresh-token-store.interface.js';
24
+ export * from './session-store.interface.js';
25
+ export * from './session.interface.js';
26
+ export * from './sign-in-options.interface.js';
27
+ export * from './token.interface.js';
@@ -0,0 +1,27 @@
1
+ export * from './api-key.interface.js';
2
+ export * from './authenticate-options.interface.js';
3
+ export * from './authentication-error-options.interface.js';
4
+ export * from './authentication-module-options.interface.js';
5
+ export * from './authentication-registry.interface.js';
6
+ export * from './authentication-result.interface.js';
7
+ export * from './authentication-storage.interface.js';
8
+ export * from './duration.interface.js';
9
+ export * from './email-token-store.interface.js';
10
+ export * from './email-verification.interface.js';
11
+ export * from './jwt-options.interface.js';
12
+ export * from './jwt.interface.js';
13
+ export * from './magic-link-store.interface.js';
14
+ export * from './magic-link.interface.js';
15
+ export * from './mfa-options.interface.js';
16
+ export * from './mfa-store.interface.js';
17
+ export * from './oidc-provider.interface.js';
18
+ export * from './oidc-state-store.interface.js';
19
+ export * from './oidc.interface.js';
20
+ export * from './password-hasher-options.interface.js';
21
+ export * from './password-reset.interface.js';
22
+ export * from './refresh-token-options.interface.js';
23
+ export * from './refresh-token-store.interface.js';
24
+ export * from './session-store.interface.js';
25
+ export * from './session.interface.js';
26
+ export * from './sign-in-options.interface.js';
27
+ export * from './token.interface.js';
@@ -0,0 +1,68 @@
1
+ import type { KeyObject } from 'node:crypto';
2
+ import type { JwksClient } from '../jwt/jwks.client.js';
3
+ import type { Duration } from './duration.interface.js';
4
+ import type { ClaimRules, JwsAlgorithm } from './jwt.interface.js';
5
+ export interface JwksClientOptions {
6
+ /** How long a fetched key set is trusted. Default `'10m'`. */
7
+ cacheTtl?: Duration;
8
+ /**
9
+ * Minimum gap between refetches triggered by an unknown `kid`. Default
10
+ * `'30s'`. Stops a flood of tokens with random `kid`s from turning into a
11
+ * flood of requests to the IdP.
12
+ */
13
+ cooldown?: Duration;
14
+ /** Request timeout. Default `'5s'`. */
15
+ timeout?: Duration;
16
+ fetch?: typeof fetch;
17
+ /** Clock in epoch milliseconds, for tests. */
18
+ now?: () => number;
19
+ }
20
+ export interface JwtVerifierOptions extends ClaimRules {
21
+ /**
22
+ * A static key: an HS256 secret (at least 32 bytes), or a public or
23
+ * private key as a `KeyObject` or PEM text (a string or a `Buffer`). A
24
+ * public key needs `issuer` and `audience`, as a `jwks` does: it is an
25
+ * identity provider's, which signs the tokens of all its clients with it.
26
+ * A JWK, or DER, is refused (read as bytes, it would be an HS256 secret):
27
+ * pass `createPublicKey({ key: jwk, format: 'jwk' })`.
28
+ */
29
+ key?: KeyObject | string | Buffer;
30
+ /**
31
+ * A JWKS URL, or a shared {@link JwksClient}. Needs `issuer` and
32
+ * `audience`: an identity provider's keys sign the tokens of every one of
33
+ * its clients.
34
+ */
35
+ jwks?: string | JwksClient;
36
+ /**
37
+ * Accepted `alg` values. Defaults: `['HS256']` for a secret, the key's own
38
+ * algorithm for an asymmetric key, `['RS256', 'ES256']` for a JWKS.
39
+ * `none` is never accepted.
40
+ */
41
+ algorithms?: JwsAlgorithm[];
42
+ /** Required `typ` header, e.g. `at+jwt` (RFC 9068). Not checked by default. */
43
+ type?: string;
44
+ }
45
+ export interface JwtSignerOptions {
46
+ /**
47
+ * An HS256 secret (at least 32 bytes), or a private key for RS256, ES256
48
+ * or EdDSA: a `KeyObject`, or PEM text (a string or a `Buffer`). A JWK, or
49
+ * DER, is refused: pass `createPrivateKey({ key: jwk, format: 'jwk' })`.
50
+ */
51
+ key: KeyObject | string | Buffer;
52
+ /** Default: HS256 for a secret, the key's own algorithm for a private key. */
53
+ alg?: JwsAlgorithm;
54
+ /** Published in the header so verifiers can pick the key from a JWKS. */
55
+ kid?: string;
56
+ issuer?: string;
57
+ audience?: string | string[];
58
+ /** Lifetime of a token. Default `'15m'`: access tokens should be short-lived. */
59
+ ttl?: Duration;
60
+ /** `typ` header. Default `JWT`; RFC 9068 access tokens use `at+jwt`. */
61
+ type?: string;
62
+ /** Clock in epoch milliseconds, for tests. */
63
+ now?: () => number;
64
+ }
65
+ export interface JwtBearerProviderOptions extends JwtVerifierOptions {
66
+ /** `realm` in the `WWW-Authenticate` challenge. Default `api`. */
67
+ realm?: string;
68
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,36 @@
1
+ import type { Duration } from './duration.interface.js';
2
+ /**
3
+ * Supported JWS algorithms. EdDSA means Ed25519 only: Ed448 is rejected
4
+ * (untested here, and rare in practice).
5
+ */
6
+ export type JwsAlgorithm = 'HS256' | 'RS256' | 'ES256' | 'EdDSA';
7
+ export interface JwtClaims {
8
+ iss?: string;
9
+ sub?: string;
10
+ aud?: string | string[];
11
+ exp?: number;
12
+ nbf?: number;
13
+ iat?: number;
14
+ jti?: string;
15
+ [claim: string]: unknown;
16
+ }
17
+ export interface ClaimRules {
18
+ issuer?: string;
19
+ /**
20
+ * Accepted `aud` values. `false` accepts any audience, for tokens that
21
+ * carry none (check the claim that names your client in `validate()`).
22
+ */
23
+ audience?: string | string[] | false;
24
+ /**
25
+ * Leeway for `exp`, `nbf` and `iat`. Default `0`, right for the app's own
26
+ * tokens. Set it (`'30s'`) for another issuer's: a clock a second ahead
27
+ * would otherwise issue tokens "in the future".
28
+ */
29
+ clockTolerance?: Duration;
30
+ /** Reject tokens issued longer ago than this (needs `iat`). */
31
+ maxAge?: Duration;
32
+ /** Claims that must be present. `exp` is required by default. */
33
+ required?: string[];
34
+ /** Clock in epoch milliseconds, for tests. */
35
+ now?: () => number;
36
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,36 @@
1
+ export interface MagicLinkRecord {
2
+ /**
3
+ * SHA-256 of the token, and of the secret that binds the link to the
4
+ * browser that requested it (`magicLink.bindToBrowser`): the link alone
5
+ * does not find it.
6
+ */
7
+ id: string;
8
+ email: string;
9
+ createdAt: Date;
10
+ expiresAt: Date;
11
+ redirectTo?: string;
12
+ }
13
+ /**
14
+ * Storage for pending magic links. Implement it on your database or Redis,
15
+ * and register the provider with
16
+ * `AuthenticationStorage.registerSource({ magicLinks: this })`.
17
+ *
18
+ * `consumeMagicLink()` must be one atomic get-and-delete
19
+ * (`DELETE … RETURNING`, `GETDEL`), so a link works once however many
20
+ * requests present it. Anyone can request links, so the store must stay
21
+ * bounded: drop expired links as new ones are saved, and cap the rest.
22
+ */
23
+ export interface MagicLinkStore {
24
+ /**
25
+ * Saves a new link (a fresh random id: a plain insert), then keeps the
26
+ * store bounded: deletes links whose `expiresAt` is at or before this
27
+ * one's `createdAt`, and past a cap, those that expire first.
28
+ */
29
+ saveMagicLink(record: MagicLinkRecord): Promise<void>;
30
+ /**
31
+ * Removes and returns the link, in one atomic step; `undefined` if there
32
+ * is none. Of several concurrent calls, exactly one gets the record.
33
+ * Expired links may be returned: `MagicLinkService` checks expiry.
34
+ */
35
+ consumeMagicLink(id: string): Promise<MagicLinkRecord | undefined>;
36
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,55 @@
1
+ import type { CookieAttributes } from '../session/cookies.util.js';
2
+ import type { Duration } from './duration.interface.js';
3
+ export interface MagicLink {
4
+ email: string;
5
+ url: string;
6
+ expiresAt: Date;
7
+ }
8
+ /** The account behind an address, as `MagicLinkHandler.resolveUser()` returns it. */
9
+ export interface MagicLinkAccount {
10
+ id: string;
11
+ /**
12
+ * The address the account has stored. The link signs the account in only
13
+ * when it is the link's address (compared trimmed and lowercased).
14
+ */
15
+ email: string;
16
+ }
17
+ export interface MagicLinkOptions {
18
+ /** Page that receives `?token=…`, e.g. `https://app.example.com/auth/magic`. */
19
+ url: string;
20
+ /** Lifetime of a link. Default `'15m'`. */
21
+ ttl?: Duration;
22
+ /**
23
+ * Whether a link works only in the browser that requested it. Default
24
+ * `true`: `create()` sets a transaction cookie, and `consume()` refuses a
25
+ * link the browser holds no cookie for (`magic-link-refused`,
26
+ * `not-this-browser`). Without it, anyone can request a link for their
27
+ * own address and get someone else to open it, which signs that person's
28
+ * browser in to the attacker's account (login CSRF). `false` trades that
29
+ * for links that work on another device than the one that asked for them
30
+ * (requested on the laptop, opened on the phone).
31
+ */
32
+ bindToBrowser?: boolean;
33
+ /**
34
+ * Attributes of the transaction cookie, `__Host-magic_link_tx` (or
35
+ * `magic_link_tx` when they rule the prefix out). `secure` defaults to
36
+ * `true`; `SameSite` is always `Lax`, which lets the cookie through the
37
+ * top-level navigation from the mail client to the page.
38
+ */
39
+ cookie?: CookieAttributes;
40
+ /** Clock in epoch milliseconds, for tests. */
41
+ now?: () => number;
42
+ }
43
+ /** The HTTP request that presents a link, as Express and Fastify provide it. */
44
+ export type MagicLinkRequest = {
45
+ headers: Record<string, string | string[] | undefined>;
46
+ };
47
+ export interface CreatedMagicLink {
48
+ expiresAt: Date;
49
+ /**
50
+ * The `Set-Cookie` value of the transaction cookie, already set on the HTTP
51
+ * response when called from a handler; send it yourself elsewhere. Absent
52
+ * with `bindToBrowser: false`.
53
+ */
54
+ cookie?: string;
55
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,44 @@
1
+ import type { Duration } from './duration.interface.js';
2
+ export interface MfaOptions {
3
+ /**
4
+ * Encryption of TOTP secrets at rest (AES-256-GCM): `{ keys: [key] }`,
5
+ * newest key first. Required once `mfa` is configured: pass `false` to
6
+ * store plaintext deliberately (tests, throwaway in-memory setups).
7
+ */
8
+ encryption: SecretEncryptionOptions | false;
9
+ /** Shown in authenticator apps. */
10
+ issuer?: string;
11
+ /** Accepted 30-second steps either side of now: an integer from 0 to 10. Default 1, per RFC 6238 §5.2. */
12
+ window?: number;
13
+ /** Failed codes allowed per `lockoutWindow` before every code is refused: an integer of at least 1. Default 5. */
14
+ maxAttempts?: number;
15
+ /** Default `'15m'`. */
16
+ lockoutWindow?: Duration;
17
+ /** Recovery codes per batch: an integer of at least 1. Default 10. */
18
+ recoveryCodes?: number;
19
+ /**
20
+ * How long a session that passed its first factor may wait for the second
21
+ * (`mfa: 'pending'`) before it expires. Default `'10m'`, never more than
22
+ * `session.absoluteTtl`. A pending cookie is half a credential: this keeps a
23
+ * stolen one from staying useful for the session's full lifetime.
24
+ */
25
+ pendingTtl?: Duration;
26
+ /** Clock in epoch milliseconds, for tests. */
27
+ now?: () => number;
28
+ }
29
+ export interface SecretEncryptionOptions {
30
+ /**
31
+ * AES-256-GCM keys: 32-byte `Buffer`s, or strings of at least 32
32
+ * characters (random secrets, expanded with HKDF-SHA256; not passwords).
33
+ * The first key encrypts, and every key decrypts. Prepend a new key to
34
+ * rotate.
35
+ */
36
+ keys: (string | Buffer)[];
37
+ /**
38
+ * Accept stored values that are not ciphertext (secrets saved before
39
+ * encryption was turned on) and re-encrypt them on the next successful
40
+ * verification. Off by default: with encryption on, a plaintext value in
41
+ * the store is otherwise indistinguishable from one an attacker planted.
42
+ */
43
+ migratePlaintext?: boolean;
44
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,70 @@
1
+ export interface TotpRecord {
2
+ /** Sealed secret (`v1.<keyId>.…`, see `SecretCipher`); base32 plaintext only with `encryption: false`. */
3
+ secret: string;
4
+ /** `false` until the user proved the authenticator works. */
5
+ confirmed: boolean;
6
+ /**
7
+ * A replacement secret (sealed like `secret`) staged by
8
+ * `enroll(…, { replace: true })`. `secret` stays active until `confirm()`
9
+ * proves the new authenticator works.
10
+ */
11
+ pendingSecret?: string;
12
+ /** Last accepted time step, for replay protection. */
13
+ lastUsedStep?: number;
14
+ }
15
+ /**
16
+ * Second-factor storage: each user's authenticator, recovery code hashes,
17
+ * and failed attempts. Implement it on your database or Redis, and register
18
+ * the provider with `AuthenticationStorage.registerSource({ mfa: this })`.
19
+ *
20
+ * Four methods are what stop a code from being accepted twice, or a burst
21
+ * of guesses from outrunning the lockout, and must be single atomic writes
22
+ * (a conditional update or delete, an upsert, a Lua script), never a read
23
+ * followed by a write: `saveTotp()`, `claimTotpStep()`,
24
+ * `consumeRecoveryCode()` and `recordMfaFailure()`. Each one's comment has
25
+ * the race it prevents, and `authenticationStoreContract()` from
26
+ * `@nestjs/authentication/testing` checks them (`concurrent: true`).
27
+ *
28
+ * Times (`now`) are epoch milliseconds from `MfaService`'s clock, never the
29
+ * store's. Optional fields come back absent (`undefined`), never `null`.
30
+ */
31
+ export interface MfaStore {
32
+ getTotp(userId: string): Promise<TotpRecord | undefined>;
33
+ /**
34
+ * Saves the user's authenticator (an upsert), or deletes it (`null`).
35
+ * Never lowers the stored `lastUsedStep`: keep the larger of the stored
36
+ * one and the record's (`GREATEST()` in the upsert). A record read before
37
+ * a concurrent `claimTotpStep()` must not reopen the step it claimed.
38
+ */
39
+ saveTotp(userId: string, record: TotpRecord | null): Promise<void>;
40
+ /**
41
+ * Sets `lastUsedStep = step` iff the user has an authenticator and `step`
42
+ * is greater than the stored one (or none is stored), in one conditional
43
+ * write; `true` if it did. Of several concurrent calls with the same step,
44
+ * exactly one gets `true`: a TOTP code works once.
45
+ */
46
+ claimTotpStep(userId: string, step: number): Promise<boolean>;
47
+ /** Replaces the user's recovery code hashes with `hashes` (`[]` deletes them). */
48
+ saveRecoveryCodes(userId: string, hashes: string[]): Promise<void>;
49
+ /**
50
+ * Removes one recovery code hash of this user, in one conditional delete;
51
+ * `true` if this call removed it. Of several concurrent calls, exactly one
52
+ * gets `true`.
53
+ */
54
+ consumeRecoveryCode(userId: string, hash: string): Promise<boolean>;
55
+ countRecoveryCodes(userId: string): Promise<number>;
56
+ /**
57
+ * Records a failed attempt at `now`, then returns the failures within
58
+ * `windowMs` before `now` (`at > now - windowMs`), this one included.
59
+ * Record first, count second, each visible to other callers as soon as it
60
+ * returns: parallel calls each count every attempt recorded before them,
61
+ * so no more than `n` of them see a count of `n` or less. `MfaService`
62
+ * calls it *before* checking a code, which is what stops a burst of
63
+ * parallel guesses.
64
+ */
65
+ recordMfaFailure(userId: string, windowMs: number, now: number): Promise<number>;
66
+ /** The failures within `windowMs` before `now`, without recording one. */
67
+ countMfaFailures(userId: string, windowMs: number, now: number): Promise<number>;
68
+ /** Forgets the user's failures (after a code verified). */
69
+ clearMfaFailures(userId: string): Promise<void>;
70
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,56 @@
1
+ import type { JwsAlgorithm } from './jwt.interface.js';
2
+ export interface OidcProfile {
3
+ /** Config key of the provider (`google`, `github`, …). */
4
+ provider: string;
5
+ /** Stable account id at the provider. Link accounts by (provider, subject), never by email. */
6
+ subject: string;
7
+ email?: string;
8
+ /** Only `true` when the provider asserted it. Unverified emails must not link accounts. */
9
+ emailVerified: boolean;
10
+ name?: string;
11
+ picture?: string;
12
+ /** Verified ID token claims merged with userinfo (OIDC), or the raw userinfo (OAuth 2.0). */
13
+ claims: Record<string, unknown>;
14
+ }
15
+ export interface OAuthTokens {
16
+ accessToken: string;
17
+ refreshToken?: string;
18
+ idToken?: string;
19
+ expiresIn?: number;
20
+ scope?: string;
21
+ }
22
+ export interface ProfileContext {
23
+ provider: string;
24
+ tokens: OAuthTokens;
25
+ /** GET with the access token, JSON response. For extra API calls. */
26
+ fetchJson(url: string): Promise<any>;
27
+ }
28
+ export interface OidcProviderConfig {
29
+ /** `oidc` (default): discovery + ID token. `oauth2`: plain OAuth 2.0 (GitHub), profile from an API. */
30
+ kind?: 'oidc' | 'oauth2';
31
+ /** OIDC issuer; discovery is `${issuer}/.well-known/openid-configuration`. */
32
+ issuer?: string;
33
+ clientId: string;
34
+ clientSecret?: string;
35
+ /** Default `openid email profile` for OIDC. */
36
+ scopes?: string[];
37
+ /** Override or (for `oauth2`) supply endpoints. */
38
+ authorizationEndpoint?: string;
39
+ tokenEndpoint?: string;
40
+ userinfoEndpoint?: string;
41
+ jwksUri?: string;
42
+ /** Accepted ID token algorithms. Default `RS256`, `ES256`. */
43
+ idTokenAlgorithms?: JwsAlgorithm[];
44
+ /** Default `client_secret_basic` with a secret, `none` without (public client + PKCE). */
45
+ tokenEndpointAuthMethod?: 'client_secret_basic' | 'client_secret_post' | 'none';
46
+ /**
47
+ * Extra authorization request parameters (`prompt`, `hd`, `login_hint`,
48
+ * …). They travel through the browser, which can change or drop them:
49
+ * hints to the provider, never checks. Check what they ask for in the
50
+ * resolver, on the verified claims (`profile.claims.hd`, `acr`,
51
+ * `auth_time`).
52
+ */
53
+ authorizationParams?: Record<string, string>;
54
+ /** `oauth2` only: builds the profile from the userinfo response. */
55
+ profile?(userinfo: any, context: ProfileContext): OidcProfile | Promise<OidcProfile>;
56
+ }
@@ -0,0 +1 @@
1
+ export {};