@rapidrest/auth 1.0.0-beta.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 (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +75 -0
  3. package/dist/lib/auth/BasicStrategy.js +82 -0
  4. package/dist/lib/auth/BasicStrategy.js.map +1 -0
  5. package/dist/lib/auth/FIDO2Strategy.js +179 -0
  6. package/dist/lib/auth/FIDO2Strategy.js.map +1 -0
  7. package/dist/lib/auth/MFAStrategy.js +219 -0
  8. package/dist/lib/auth/MFAStrategy.js.map +1 -0
  9. package/dist/lib/auth/OIDCStrategy.js +397 -0
  10. package/dist/lib/auth/OIDCStrategy.js.map +1 -0
  11. package/dist/lib/auth/OTPStrategy.js +143 -0
  12. package/dist/lib/auth/OTPStrategy.js.map +1 -0
  13. package/dist/lib/auth/PasskeyStrategy.js +185 -0
  14. package/dist/lib/auth/PasskeyStrategy.js.map +1 -0
  15. package/dist/lib/auth/TOTPStrategy.js +84 -0
  16. package/dist/lib/auth/TOTPStrategy.js.map +1 -0
  17. package/dist/lib/auth/index.js +10 -0
  18. package/dist/lib/auth/index.js.map +1 -0
  19. package/dist/lib/auth/shared.js +431 -0
  20. package/dist/lib/auth/shared.js.map +1 -0
  21. package/dist/lib/auth/types.js +12 -0
  22. package/dist/lib/auth/types.js.map +1 -0
  23. package/dist/lib/index.js +4 -0
  24. package/dist/lib/index.js.map +1 -0
  25. package/dist/lib/models/index.js +2 -0
  26. package/dist/lib/models/index.js.map +1 -0
  27. package/dist/lib/models/mongo/AliasMongo.js +77 -0
  28. package/dist/lib/models/mongo/AliasMongo.js.map +1 -0
  29. package/dist/lib/models/mongo/ProfileMongo.js +99 -0
  30. package/dist/lib/models/mongo/ProfileMongo.js.map +1 -0
  31. package/dist/lib/models/mongo/SecretMongo.js +71 -0
  32. package/dist/lib/models/mongo/SecretMongo.js.map +1 -0
  33. package/dist/lib/models/mongo/UserMongo.js +71 -0
  34. package/dist/lib/models/mongo/UserMongo.js.map +1 -0
  35. package/dist/lib/models/mongo/index.js +5 -0
  36. package/dist/lib/models/mongo/index.js.map +1 -0
  37. package/dist/lib/models/mongo.js +2 -0
  38. package/dist/lib/models/mongo.js.map +1 -0
  39. package/dist/lib/models/sql/AliasSQL.js +77 -0
  40. package/dist/lib/models/sql/AliasSQL.js.map +1 -0
  41. package/dist/lib/models/sql/ProfileSQL.js +99 -0
  42. package/dist/lib/models/sql/ProfileSQL.js.map +1 -0
  43. package/dist/lib/models/sql/SecretSQL.js +71 -0
  44. package/dist/lib/models/sql/SecretSQL.js.map +1 -0
  45. package/dist/lib/models/sql/UserSQL.js +68 -0
  46. package/dist/lib/models/sql/UserSQL.js.map +1 -0
  47. package/dist/lib/models/sql/index.js +5 -0
  48. package/dist/lib/models/sql/index.js.map +1 -0
  49. package/dist/lib/models/sql.js +2 -0
  50. package/dist/lib/models/sql.js.map +1 -0
  51. package/dist/lib/models/types.js +35 -0
  52. package/dist/lib/models/types.js.map +1 -0
  53. package/dist/lib/mongo.js +3 -0
  54. package/dist/lib/mongo.js.map +1 -0
  55. package/dist/lib/routes/BaseAliasRoute.js +10 -0
  56. package/dist/lib/routes/BaseAliasRoute.js.map +1 -0
  57. package/dist/lib/routes/BaseAuthBasicRoute.js +132 -0
  58. package/dist/lib/routes/BaseAuthBasicRoute.js.map +1 -0
  59. package/dist/lib/routes/BaseAuthFIDO2Route.js +191 -0
  60. package/dist/lib/routes/BaseAuthFIDO2Route.js.map +1 -0
  61. package/dist/lib/routes/BaseAuthMFARoute.js +310 -0
  62. package/dist/lib/routes/BaseAuthMFARoute.js.map +1 -0
  63. package/dist/lib/routes/BaseAuthOIDCRoute.js +231 -0
  64. package/dist/lib/routes/BaseAuthOIDCRoute.js.map +1 -0
  65. package/dist/lib/routes/BaseAuthOTPRoute.js +214 -0
  66. package/dist/lib/routes/BaseAuthOTPRoute.js.map +1 -0
  67. package/dist/lib/routes/BaseAuthPasskeyRoute.js +182 -0
  68. package/dist/lib/routes/BaseAuthPasskeyRoute.js.map +1 -0
  69. package/dist/lib/routes/BaseAuthTOTPRoute.js +133 -0
  70. package/dist/lib/routes/BaseAuthTOTPRoute.js.map +1 -0
  71. package/dist/lib/routes/BaseProfileRoute.js +10 -0
  72. package/dist/lib/routes/BaseProfileRoute.js.map +1 -0
  73. package/dist/lib/routes/BaseSecretRoute.js +399 -0
  74. package/dist/lib/routes/BaseSecretRoute.js.map +1 -0
  75. package/dist/lib/routes/BaseUserRoute.js +10 -0
  76. package/dist/lib/routes/BaseUserRoute.js.map +1 -0
  77. package/dist/lib/routes/UserUtils.js +78 -0
  78. package/dist/lib/routes/UserUtils.js.map +1 -0
  79. package/dist/lib/routes/index.js +13 -0
  80. package/dist/lib/routes/index.js.map +1 -0
  81. package/dist/lib/routes/mongo/BaseAliasRouteMongo.js +20 -0
  82. package/dist/lib/routes/mongo/BaseAliasRouteMongo.js.map +1 -0
  83. package/dist/lib/routes/mongo/BaseAuthBasicRouteMongo.js +14 -0
  84. package/dist/lib/routes/mongo/BaseAuthBasicRouteMongo.js.map +1 -0
  85. package/dist/lib/routes/mongo/BaseAuthFIDO2RouteMongo.js +14 -0
  86. package/dist/lib/routes/mongo/BaseAuthFIDO2RouteMongo.js.map +1 -0
  87. package/dist/lib/routes/mongo/BaseAuthMFARouteMongo.js +14 -0
  88. package/dist/lib/routes/mongo/BaseAuthMFARouteMongo.js.map +1 -0
  89. package/dist/lib/routes/mongo/BaseAuthOIDCRouteMongo.js +11 -0
  90. package/dist/lib/routes/mongo/BaseAuthOIDCRouteMongo.js.map +1 -0
  91. package/dist/lib/routes/mongo/BaseAuthOTPRouteMongo.js +14 -0
  92. package/dist/lib/routes/mongo/BaseAuthOTPRouteMongo.js.map +1 -0
  93. package/dist/lib/routes/mongo/BaseAuthPasskeyRouteMongo.js +14 -0
  94. package/dist/lib/routes/mongo/BaseAuthPasskeyRouteMongo.js.map +1 -0
  95. package/dist/lib/routes/mongo/BaseAuthTOTPRouteMongo.js +14 -0
  96. package/dist/lib/routes/mongo/BaseAuthTOTPRouteMongo.js.map +1 -0
  97. package/dist/lib/routes/mongo/BaseProfileRouteMongo.js +20 -0
  98. package/dist/lib/routes/mongo/BaseProfileRouteMongo.js.map +1 -0
  99. package/dist/lib/routes/mongo/BaseSecretRouteMongo.js +20 -0
  100. package/dist/lib/routes/mongo/BaseSecretRouteMongo.js.map +1 -0
  101. package/dist/lib/routes/mongo/BaseUserRouteMongo.js +20 -0
  102. package/dist/lib/routes/mongo/BaseUserRouteMongo.js.map +1 -0
  103. package/dist/lib/routes/mongo/index.js +12 -0
  104. package/dist/lib/routes/mongo/index.js.map +1 -0
  105. package/dist/lib/routes/mongo.js +2 -0
  106. package/dist/lib/routes/mongo.js.map +1 -0
  107. package/dist/lib/routes/sql/BaseAliasRouteSQL.js +20 -0
  108. package/dist/lib/routes/sql/BaseAliasRouteSQL.js.map +1 -0
  109. package/dist/lib/routes/sql/BaseAuthBasicRouteSQL.js +14 -0
  110. package/dist/lib/routes/sql/BaseAuthBasicRouteSQL.js.map +1 -0
  111. package/dist/lib/routes/sql/BaseAuthFIDO2RouteSQL.js +14 -0
  112. package/dist/lib/routes/sql/BaseAuthFIDO2RouteSQL.js.map +1 -0
  113. package/dist/lib/routes/sql/BaseAuthMFARouteSQL.js +14 -0
  114. package/dist/lib/routes/sql/BaseAuthMFARouteSQL.js.map +1 -0
  115. package/dist/lib/routes/sql/BaseAuthOIDCRouteSQL.js +11 -0
  116. package/dist/lib/routes/sql/BaseAuthOIDCRouteSQL.js.map +1 -0
  117. package/dist/lib/routes/sql/BaseAuthOTPRouteSQL.js +14 -0
  118. package/dist/lib/routes/sql/BaseAuthOTPRouteSQL.js.map +1 -0
  119. package/dist/lib/routes/sql/BaseAuthPasskeyRouteSQL.js +14 -0
  120. package/dist/lib/routes/sql/BaseAuthPasskeyRouteSQL.js.map +1 -0
  121. package/dist/lib/routes/sql/BaseAuthTOTPRouteSQL.js +14 -0
  122. package/dist/lib/routes/sql/BaseAuthTOTPRouteSQL.js.map +1 -0
  123. package/dist/lib/routes/sql/BaseProfileRouteSQL.js +20 -0
  124. package/dist/lib/routes/sql/BaseProfileRouteSQL.js.map +1 -0
  125. package/dist/lib/routes/sql/BaseSecretRouteSQL.js +20 -0
  126. package/dist/lib/routes/sql/BaseSecretRouteSQL.js.map +1 -0
  127. package/dist/lib/routes/sql/BaseUserRouteSQL.js +20 -0
  128. package/dist/lib/routes/sql/BaseUserRouteSQL.js.map +1 -0
  129. package/dist/lib/routes/sql/index.js +12 -0
  130. package/dist/lib/routes/sql/index.js.map +1 -0
  131. package/dist/lib/routes/sql.js +2 -0
  132. package/dist/lib/routes/sql.js.map +1 -0
  133. package/dist/lib/sql.js +3 -0
  134. package/dist/lib/sql.js.map +1 -0
  135. package/dist/types/auth/BasicStrategy.d.ts +39 -0
  136. package/dist/types/auth/FIDO2Strategy.d.ts +85 -0
  137. package/dist/types/auth/MFAStrategy.d.ts +110 -0
  138. package/dist/types/auth/OIDCStrategy.d.ts +188 -0
  139. package/dist/types/auth/OTPStrategy.d.ts +88 -0
  140. package/dist/types/auth/PasskeyStrategy.d.ts +81 -0
  141. package/dist/types/auth/TOTPStrategy.d.ts +49 -0
  142. package/dist/types/auth/index.d.ts +9 -0
  143. package/dist/types/auth/shared.d.ts +136 -0
  144. package/dist/types/auth/types.d.ts +127 -0
  145. package/dist/types/index.d.ts +3 -0
  146. package/dist/types/models/index.d.ts +1 -0
  147. package/dist/types/models/mongo/AliasMongo.d.ts +15 -0
  148. package/dist/types/models/mongo/ProfileMongo.d.ts +17 -0
  149. package/dist/types/models/mongo/SecretMongo.d.ts +14 -0
  150. package/dist/types/models/mongo/UserMongo.d.ts +14 -0
  151. package/dist/types/models/mongo/index.d.ts +4 -0
  152. package/dist/types/models/mongo.d.ts +1 -0
  153. package/dist/types/models/sql/AliasSQL.d.ts +15 -0
  154. package/dist/types/models/sql/ProfileSQL.d.ts +17 -0
  155. package/dist/types/models/sql/SecretSQL.d.ts +14 -0
  156. package/dist/types/models/sql/UserSQL.d.ts +14 -0
  157. package/dist/types/models/sql/index.d.ts +4 -0
  158. package/dist/types/models/sql.d.ts +1 -0
  159. package/dist/types/models/types.d.ts +136 -0
  160. package/dist/types/mongo.d.ts +2 -0
  161. package/dist/types/routes/BaseAliasRoute.d.ts +7 -0
  162. package/dist/types/routes/BaseAuthBasicRoute.d.ts +27 -0
  163. package/dist/types/routes/BaseAuthFIDO2Route.d.ts +50 -0
  164. package/dist/types/routes/BaseAuthMFARoute.d.ts +61 -0
  165. package/dist/types/routes/BaseAuthOIDCRoute.d.ts +33 -0
  166. package/dist/types/routes/BaseAuthOTPRoute.d.ts +53 -0
  167. package/dist/types/routes/BaseAuthPasskeyRoute.d.ts +41 -0
  168. package/dist/types/routes/BaseAuthTOTPRoute.d.ts +38 -0
  169. package/dist/types/routes/BaseProfileRoute.d.ts +7 -0
  170. package/dist/types/routes/BaseSecretRoute.d.ts +89 -0
  171. package/dist/types/routes/BaseUserRoute.d.ts +7 -0
  172. package/dist/types/routes/UserUtils.d.ts +21 -0
  173. package/dist/types/routes/index.d.ts +12 -0
  174. package/dist/types/routes/mongo/BaseAliasRouteMongo.d.ts +4 -0
  175. package/dist/types/routes/mongo/BaseAuthBasicRouteMongo.d.ts +7 -0
  176. package/dist/types/routes/mongo/BaseAuthFIDO2RouteMongo.d.ts +7 -0
  177. package/dist/types/routes/mongo/BaseAuthMFARouteMongo.d.ts +7 -0
  178. package/dist/types/routes/mongo/BaseAuthOIDCRouteMongo.d.ts +7 -0
  179. package/dist/types/routes/mongo/BaseAuthOTPRouteMongo.d.ts +7 -0
  180. package/dist/types/routes/mongo/BaseAuthPasskeyRouteMongo.d.ts +7 -0
  181. package/dist/types/routes/mongo/BaseAuthTOTPRouteMongo.d.ts +7 -0
  182. package/dist/types/routes/mongo/BaseProfileRouteMongo.d.ts +4 -0
  183. package/dist/types/routes/mongo/BaseSecretRouteMongo.d.ts +4 -0
  184. package/dist/types/routes/mongo/BaseUserRouteMongo.d.ts +4 -0
  185. package/dist/types/routes/mongo/index.d.ts +11 -0
  186. package/dist/types/routes/mongo.d.ts +1 -0
  187. package/dist/types/routes/sql/BaseAliasRouteSQL.d.ts +4 -0
  188. package/dist/types/routes/sql/BaseAuthBasicRouteSQL.d.ts +7 -0
  189. package/dist/types/routes/sql/BaseAuthFIDO2RouteSQL.d.ts +7 -0
  190. package/dist/types/routes/sql/BaseAuthMFARouteSQL.d.ts +7 -0
  191. package/dist/types/routes/sql/BaseAuthOIDCRouteSQL.d.ts +7 -0
  192. package/dist/types/routes/sql/BaseAuthOTPRouteSQL.d.ts +7 -0
  193. package/dist/types/routes/sql/BaseAuthPasskeyRouteSQL.d.ts +7 -0
  194. package/dist/types/routes/sql/BaseAuthTOTPRouteSQL.d.ts +7 -0
  195. package/dist/types/routes/sql/BaseProfileRouteSQL.d.ts +4 -0
  196. package/dist/types/routes/sql/BaseSecretRouteSQL.d.ts +4 -0
  197. package/dist/types/routes/sql/BaseUserRouteSQL.d.ts +4 -0
  198. package/dist/types/routes/sql/index.d.ts +11 -0
  199. package/dist/types/routes/sql.d.ts +1 -0
  200. package/dist/types/sql.d.ts +2 -0
  201. package/package.json +138 -0
@@ -0,0 +1,185 @@
1
+ import { generatePasskeyChallenge, isPasskeyResponse, verifyPasskeyChallenge } from "./shared.js";
2
+ /**
3
+ * Describes the configuration options that can be used to initialize PasskeyStrategy.
4
+ *
5
+ * @author Jean-Philippe Steinmetz
6
+ */
7
+ export class PasskeyStrategyOptions {
8
+ constructor(config) {
9
+ this.config = config;
10
+ }
11
+ /**
12
+ * Retrieves a previously-registered credential by its ID. Returns `undefined` if no credential
13
+ * with that ID is known.
14
+ * NOTE: You must override this function when using this strategy.
15
+ */
16
+ async getCredentialById(credentialId) {
17
+ throw new Error("Did you forget to override PasskeyStrategyOptions.getCredentialById?");
18
+ }
19
+ /**
20
+ * Retrieves all credentials registered for the given user. Used to build the `allowCredentials`
21
+ * list when a login ceremony is started with a known user hint.
22
+ * NOTE: You must override this function when using this strategy.
23
+ * @param id The unique identifier of the user or alias.
24
+ */
25
+ async getCredentials(id) {
26
+ throw new Error("Did you forget to override PasskeyStrategyOptions.getCredentials?");
27
+ }
28
+ /**
29
+ * Persists the updated signature counter for the given credential after a successful
30
+ * authentication. Must be called on every successful login to guard against cloned authenticators.
31
+ * NOTE: You must override this function when using this strategy.
32
+ */
33
+ async updateCredentialCounter(credentialId, newCounter) {
34
+ throw new Error("Did you forget to override PasskeyStrategyOptions.updateCredentialCounter?");
35
+ }
36
+ /**
37
+ * Retrieves the user data for the given unique identifier after authentication has completed successfully.
38
+ * NOTE: You must override this function when using this strategy.
39
+ * @param id The unique identifier of the user that has been successfully authenticated.
40
+ */
41
+ getUser(uid) {
42
+ throw new Error("Did you forget to override PasskeyStrategyOptions.getUser?");
43
+ }
44
+ }
45
+ /**
46
+ * Implements an authentication strategy for performing WebAuthn/Passkey (FIDO2) login.
47
+ *
48
+ * The login flow has two phases:
49
+ *
50
+ * 1. Challenge - The client requests a challenge. A random challenge is generated and stored in the
51
+ * session, and the resulting options are returned for use with
52
+ * `navigator.credentials.get()`.
53
+ * 2. Verify - The client submits the signed assertion response. The response is verified against the
54
+ * stored challenge and the credential's public key, the credential's signature counter is updated,
55
+ * and the associated user is resolved via `verify()`.
56
+ *
57
+ * NOTE: Requires session support!
58
+ *
59
+ * @author Jean-Philippe Steinmetz <rapidrests@gmail.com>
60
+ */
61
+ export class PasskeyStrategy {
62
+ constructor(options) {
63
+ this.name = "passkey";
64
+ this.options = options;
65
+ }
66
+ async authenticate(req, res, required) {
67
+ if (req.body?.id || req.body?.response) {
68
+ return await this.verify(req, required);
69
+ }
70
+ else {
71
+ return await this.challenge(req, res);
72
+ }
73
+ }
74
+ authenticateSync(req, res, required) {
75
+ throw new Error("Not supported. This auth strategy must be used asynchronously.");
76
+ }
77
+ /**
78
+ * Begins a login ceremony: generates a challenge, stores it in the session, and writes the
79
+ * resulting options directly to the response for the client to pass to `navigator.credentials.get()`.
80
+ *
81
+ * @param req The source HTTP request. May optionally carry a `uid` query parameter to scope the
82
+ * allowed credentials to a known user; omitted entirely for a discoverable/"usernameless" flow.
83
+ * @param res The response to write the generated options to.
84
+ */
85
+ async challenge(req, res) {
86
+ if (!req.session) {
87
+ throw new Error("PasskeyStrategy requires session support. Configure the `session` config block so the " +
88
+ "session middleware is registered.");
89
+ }
90
+ if (!res) {
91
+ throw new Error("PasskeyStrategy requires a response object to begin a ceremony.");
92
+ }
93
+ // If a uid hint is given, scope allowCredentials to that user's registered credentials. If
94
+ // the hint resolves to zero credentials, allowCredentials is left undefined (same as the
95
+ // no-hint case) rather than sent as an empty list. Otherwise the response shape would leak
96
+ // whether a given uid has any passkeys registered, a user-enumeration side channel.
97
+ // NOTE: scoping allowCredentials to a uid hint necessarily discloses to an unauthenticated
98
+ // caller whether the given uid has any registered passkeys (and their credential IDs/
99
+ // transports). The same trade-off inherent to any "enter your username first" login flow.
100
+ // Only the zero-credential case is equalized with the no-hint case below (both leave
101
+ // allowCredentials undefined), so a nonexistent/passkey-less account can't be trivially
102
+ // distinguished from one with zero credentials; an account that DOES have credentials
103
+ // remains distinguishable from one that doesn't by design. Callers that need to avoid this
104
+ // entirely (e.g. a public-facing login form) should not wire a client-suppliable uid hint
105
+ // through to this endpoint at all — rely purely on the discoverable/"usernameless" flow by
106
+ // omitting the hint, and consider rate-limiting this endpoint regardless.
107
+ const uidHint = req.query?.uid;
108
+ let allowCredentials = undefined;
109
+ if (uidHint) {
110
+ const credentials = await this.options.getCredentials(uidHint);
111
+ if (credentials.length > 0) {
112
+ allowCredentials = credentials.map((c) => ({ id: c.id, transports: c.transports }));
113
+ }
114
+ }
115
+ const result = await generatePasskeyChallenge(this.options.config, req, allowCredentials);
116
+ res.status(200);
117
+ res.json(result);
118
+ return undefined;
119
+ }
120
+ /**
121
+ * Finishes a login ceremony: verifies the client-submitted assertion response against the
122
+ * stored challenge and credential, updates the credential's signature counter, and resolves the
123
+ * associated user.
124
+ *
125
+ * @param req The source HTTP request, carrying the assertion response in its body.
126
+ * @param required Set to `true` if authentication is required to pass, otherwise set to `false`.
127
+ */
128
+ async verify(req, required) {
129
+ if (!req.session) {
130
+ throw new Error("PasskeyStrategy requires session support. Configure the `session` config block so the " +
131
+ "session middleware is registered.");
132
+ }
133
+ if (!req.session.challenge) {
134
+ throw new Error("No passkey ceremony in progress for this session.");
135
+ }
136
+ // The challenge is single-use regardless of outcome — cleared as soon as it's read, before
137
+ // verification is even attempted, rather than only on the success path.
138
+ const expectedChallenge = req.session.challenge;
139
+ delete req.session.challenge;
140
+ // Strict shape validation before touching storage or SimpleWebAuthn — a malformed finish
141
+ // attempt should fail with a clean, actionable error rather than crashing deep inside the
142
+ // verification library with a confusing low-level error. This alone doesn't reveal whether
143
+ // any particular account/credential exists, so it's kept distinct from the generic failure
144
+ // message below.
145
+ if (!isPasskeyResponse(req.body)) {
146
+ throw new Error("Malformed passkey authentication response.");
147
+ }
148
+ // Every failure from here on is reported with the same generic message, regardless of
149
+ // whether the credential ID is unknown, the signature failed to verify, the counter
150
+ // regressed, or the resolved user was rejected by verify() — distinguishing between these
151
+ // would let a caller enumerate which credential IDs/accounts are registered on this server.
152
+ const genericFailure = () => new Error("Passkey authentication failed.");
153
+ const credential = await this.options.getCredentialById(req.body.id);
154
+ if (!credential) {
155
+ throw genericFailure();
156
+ }
157
+ const result = await verifyPasskeyChallenge(credential, this.options.config, expectedChallenge, req.body);
158
+ if (!result.verified) {
159
+ throw genericFailure();
160
+ }
161
+ // Counter regression check. SimpleWebAuthn deliberately does not enforce counter monotonicity
162
+ // itself (many multi-device/backed-up passkeys always report 0 and would otherwise be
163
+ // permanently locked out) — a non-zero counter that fails to exceed the stored value is the
164
+ // signal of a cloned authenticator per the WebAuthn spec's guidance.
165
+ const newCounter = result.authenticationInfo.newCounter;
166
+ if (newCounter !== 0 && newCounter <= credential.counter) {
167
+ throw genericFailure();
168
+ }
169
+ await this.options.updateCredentialCounter(credential.id, newCounter);
170
+ const user = await this.options.getUser(credential.uid);
171
+ if (user) {
172
+ return {
173
+ data: req.body,
174
+ method: this.name,
175
+ payload: result.authenticationInfo,
176
+ user,
177
+ };
178
+ }
179
+ if (required) {
180
+ throw genericFailure();
181
+ }
182
+ return undefined;
183
+ }
184
+ }
185
+ //# sourceMappingURL=PasskeyStrategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PasskeyStrategy.js","sourceRoot":"","sources":["../../../src/auth/PasskeyStrategy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import { getRequestData, verifyTOTP } from "./shared.js";
2
+ /**
3
+ * Describes the configuration options that can be used to initialize TOTPStrategy.
4
+ *
5
+ * @author Jean-Philippe Steinmetz
6
+ */
7
+ export class TOTPStrategyOptions {
8
+ constructor() {
9
+ /** The name of the header to look for when performing header based authentication. Default value is `Authorization`. */
10
+ this.headerKey = "authorization";
11
+ /** The authorization scheme type when using header based authentication. Default value is `jwt`. */
12
+ this.headerScheme = "totp";
13
+ /** The name of the request query parameter to retrieve the token from when using query based authentication. Default value is `auth_totp`. */
14
+ this.queryKey = "auth_totp";
15
+ /**
16
+ * Set to `true` to allow credentials to be supplied via the `queryKey` URL parameter.
17
+ * Disabled by default — query parameters appear in server logs, browser history, and
18
+ * Referer headers, which permanently exposes credentials outside the application.
19
+ */
20
+ this.allowQueryParam = false;
21
+ }
22
+ /**
23
+ * Retrieves the stored TOTP secrets for the user with the given unique identifier.
24
+ * NOTE: You must override this function when using this strategy.
25
+ * @param id The unique identifier of the user.
26
+ */
27
+ getSecrets(uid) {
28
+ throw new Error("Did you forget to override TOTPStrategyOptions.getSecrets?");
29
+ }
30
+ /**
31
+ * Retrieves the user data for the given unique identifier.
32
+ * NOTE: You must override this function when using this strategy.
33
+ * @param id The unique id of the user that has been successfully authenticated.
34
+ */
35
+ getUser(id) {
36
+ throw new Error("Did you forget to override TOTPStrategyOptions.getUser?");
37
+ }
38
+ }
39
+ /**
40
+ * Implements an authentication strategy that performs Time-Based One Time Password authentication. This strategy
41
+ * requires an existing user account to have already registered a TOTP secret that will be validated. The strategy does
42
+ * not implement how that secret is to be stored.
43
+ *
44
+ * @author Jean-Philippe Steinmetz <rapidrests@gmail.com>
45
+ */
46
+ export class TOTPStrategy {
47
+ constructor(options = new TOTPStrategyOptions()) {
48
+ this.name = "totp";
49
+ this.options = options;
50
+ }
51
+ async authenticate(req, res, required) {
52
+ const { data, payload } = getRequestData(req, this.options.headerKey, this.options.headerScheme);
53
+ const user = await this.verify(payload);
54
+ if (user) {
55
+ return {
56
+ data,
57
+ method: this.name,
58
+ payload,
59
+ user,
60
+ };
61
+ }
62
+ if (required) {
63
+ throw new Error("Invalid authentiation request.");
64
+ }
65
+ return undefined;
66
+ }
67
+ authenticateSync(req, res, required) {
68
+ throw new Error("Not supported. This auth strategy must be used asynchronously.");
69
+ }
70
+ async verify(payload) {
71
+ const user = await this.options.getUser(payload.id);
72
+ if (user) {
73
+ const secret = await this.options.getSecrets(user.uid);
74
+ if (secret) {
75
+ let result = await verifyTOTP(payload.token, secret);
76
+ if (result && result.valid) {
77
+ return user;
78
+ }
79
+ }
80
+ }
81
+ return undefined;
82
+ }
83
+ }
84
+ //# sourceMappingURL=TOTPStrategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TOTPStrategy.js","sourceRoot":"","sources":["../../../src/auth/TOTPStrategy.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzD;;;;GAIG;AACH,MAAM,OAAO,mBAAmB;IAAhC;QACI,wHAAwH;QACjH,cAAS,GAAW,eAAe,CAAC;QAC3C,oGAAoG;QAC7F,iBAAY,GAAW,MAAM,CAAC;QACrC,8IAA8I;QACvI,aAAQ,GAAW,WAAW,CAAC;QACtC;;;;WAIG;QACI,oBAAe,GAAY,KAAK,CAAC;IAiB5C,CAAC;IAhBG;;;;OAIG;IACI,UAAU,CAAC,GAAW;QACzB,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAClF,CAAC;IACD;;;;OAIG;IACI,OAAO,CAAC,EAAU;QACrB,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC/E,CAAC;CACJ;AAED;;;;;;GAMG;AACH,MAAM,OAAO,YAAY;IAIrB,YAAY,UAA+B,IAAI,mBAAmB,EAAE;QAHpD,SAAI,GAAW,MAAM,CAAC;QAIlC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,YAAY,CACrB,GAAgB,EAChB,GAAiB,EACjB,QAAkB;QAElB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAEjG,MAAM,IAAI,GAAwB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7D,IAAI,IAAI,EAAE,CAAC;YACP,OAAO;gBACH,IAAI;gBACJ,MAAM,EAAE,IAAI,CAAC,IAAI;gBACjB,OAAO;gBACP,IAAI;aACP,CAAC;QACN,CAAC;QAED,IAAI,QAAQ,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,SAAS,CAAC;IACrB,CAAC;IAEM,gBAAgB,CAAC,GAAgB,EAAE,GAAiB,EAAE,QAAkB;QAC3E,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IACtF,CAAC;IAES,KAAK,CAAC,MAAM,CAAC,OAAY;QAC/B,MAAM,IAAI,GAAwB,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAEzE,IAAI,IAAI,EAAE,CAAC;YACP,MAAM,MAAM,GAAiB,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAErE,IAAI,MAAM,EAAE,CAAC;gBACT,IAAI,MAAM,GAAQ,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAC1D,IAAI,MAAM,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;oBACzB,OAAO,IAAI,CAAC;gBAChB,CAAC;YACL,CAAC;QACL,CAAC;QAED,OAAO,SAAS,CAAC;IACrB,CAAC;CACJ"}
@@ -0,0 +1,10 @@
1
+ export * from "./shared.js";
2
+ export * from "./types.js";
3
+ export * from "./BasicStrategy.js";
4
+ export * from "./FIDO2Strategy.js";
5
+ export * from "./MFAStrategy.js";
6
+ export * from "./OIDCStrategy.js";
7
+ export * from "./OTPStrategy.js";
8
+ export * from "./PasskeyStrategy.js";
9
+ export * from "./TOTPStrategy.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAE3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC"}