@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,310 @@
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
+ ///////////////////////////////////////////////////////////////////////////////
14
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
15
+ ///////////////////////////////////////////////////////////////////////////////
16
+ import { JWTUtils, MessagingUtils, ObjectDecorators } from "@rapidrest/core";
17
+ import { RouteDecorators, DocDecorators, RepoUtils, AuthMiddleware, ObjectFactory } from "@rapidrest/service-core";
18
+ import { AliasType, AuthResult, SecretType } from "../models/types.js";
19
+ import { MFAMethodType, MFAStrategy, MFAStrategyOptions } from "../auth/MFAStrategy.js";
20
+ import { OTPContactType } from "../auth/types.js";
21
+ import { importArgon2 } from "../auth/shared.js";
22
+ import { UserUtils } from "./UserUtils.js";
23
+ const { Config, Init, Inject } = ObjectDecorators;
24
+ const { Summary, Description, Returns } = DocDecorators;
25
+ const { Auth, Get, Post } = RouteDecorators;
26
+ const AuthUser = RouteDecorators.User;
27
+ /**
28
+ *
29
+ *
30
+ * @author Jean-Philippe Steinmetz
31
+ */
32
+ export class BaseAuthMFARoute {
33
+ constructor() {
34
+ /** The name of the messaging template to use for sending notifications. */
35
+ this.template = "login-otp";
36
+ }
37
+ /**
38
+ * Called on server startup to initialize the route with any defaults.
39
+ */
40
+ async initialize() {
41
+ if (!this.authMiddleware) {
42
+ throw new Error("authMiddleware is not set.");
43
+ }
44
+ if (!this.objectFactory) {
45
+ throw new Error("objectFactory is not set.");
46
+ }
47
+ if (!this.aliasRepo && this.aliasClass) {
48
+ this.aliasRepo = await this.objectFactory.newInstance(RepoUtils, {
49
+ name: this.aliasClass.name,
50
+ args: [this.aliasClass],
51
+ });
52
+ }
53
+ if (!this.secretRepo && this.secretClass) {
54
+ this.secretRepo = await this.objectFactory.newInstance(RepoUtils, {
55
+ name: this.secretClass.name,
56
+ args: [this.secretClass],
57
+ });
58
+ }
59
+ if (!this.userRepo && this.userClass) {
60
+ this.userRepo = await this.objectFactory.newInstance(RepoUtils, {
61
+ name: this.userClass.name,
62
+ args: [this.userClass],
63
+ });
64
+ }
65
+ if (!this.userUtils && this.userClass && this.aliasClass) {
66
+ this.userUtils = await this.objectFactory.newInstance(UserUtils, {
67
+ name: "default",
68
+ args: [this.userClass, this.aliasClass],
69
+ });
70
+ }
71
+ const options = new MFAStrategyOptions();
72
+ options.getMethod = this.getMethod.bind(this);
73
+ options.getMethods = this.getMethods.bind(this);
74
+ options.getUser = this.getUser.bind(this);
75
+ options.notifyContact = this.notifyContact.bind(this);
76
+ options.verify = this.verify.bind(this);
77
+ const strategy = await this.objectFactory.newInstance(MFAStrategy, {
78
+ name: "default",
79
+ args: [options],
80
+ });
81
+ this.authMiddleware.register(strategy.name, strategy);
82
+ }
83
+ /**
84
+ * Authenticates the user using HTTP MFA and returns a JSON Web Token access token to be used with future API requests.
85
+ */
86
+ async authenticate(user) {
87
+ const token = await JWTUtils.createToken(this.jwtConfig, user);
88
+ return new AuthResult({
89
+ token,
90
+ user,
91
+ });
92
+ }
93
+ convertAliasToMethod(alias, obfuscate) {
94
+ switch (alias.type) {
95
+ case AliasType.EMAIL:
96
+ return {
97
+ id: alias.uid,
98
+ data: {
99
+ contact: obfuscate ? this.obfuscateAlias(alias.alias, alias.type) : alias.alias,
100
+ type: OTPContactType.EMAIL,
101
+ verified: alias.verified,
102
+ },
103
+ type: MFAMethodType.OTP,
104
+ };
105
+ case AliasType.PHONE:
106
+ return {
107
+ id: alias.uid,
108
+ data: {
109
+ contact: obfuscate ? this.obfuscateAlias(alias.alias, alias.type) : alias.alias,
110
+ type: OTPContactType.SMS,
111
+ verified: alias.verified,
112
+ },
113
+ type: MFAMethodType.OTP,
114
+ };
115
+ }
116
+ return undefined;
117
+ }
118
+ convertSecretToMethod(secret) {
119
+ switch (secret.type) {
120
+ case SecretType.FIDO2:
121
+ return {
122
+ id: secret.uid,
123
+ data: secret.data,
124
+ type: MFAMethodType.FIDO2,
125
+ };
126
+ case SecretType.TOTP:
127
+ return {
128
+ id: secret.uid,
129
+ data: secret.data,
130
+ type: MFAMethodType.TOTP,
131
+ };
132
+ }
133
+ return undefined;
134
+ }
135
+ /**
136
+ * Retrieves the user's secondary authentication method for a given id.
137
+ * @param id The unique id of the secondary auth method to retrieve.
138
+ */
139
+ async getMethod(id) {
140
+ if (!this.aliasRepo) {
141
+ throw new Error("aliasRepo is not set.");
142
+ }
143
+ if (!this.secretRepo) {
144
+ throw new Error("secretRepo is not set.");
145
+ }
146
+ // The 2fa auth method may be a secret or an alias (OTP). First look for a secret
147
+ // with the matching id. If not found, look for an alias.
148
+ const secret = await this.secretRepo.findOne(id, { ignoreACL: true });
149
+ if (secret) {
150
+ return this.convertSecretToMethod(secret);
151
+ }
152
+ // It's not a secret, let's try alias
153
+ const alias = await this.aliasRepo.findOne(id, { ignoreACL: true });
154
+ if (alias) {
155
+ return this.convertAliasToMethod(alias);
156
+ }
157
+ return undefined;
158
+ }
159
+ /**
160
+ * Retrieves the list of secondary authentication methods for the user with the given id. This list is sent to
161
+ * the user and so should be obfuscated where reasonable so as to limit discovery when a password has been
162
+ * compromised.
163
+ * @param uid The unique identifier of the user.
164
+ */
165
+ async getMethods(uid) {
166
+ if (!this.aliasRepo) {
167
+ throw new Error("aliasRepo is not set.");
168
+ }
169
+ if (!this.secretRepo) {
170
+ throw new Error("secretRepo is not set.");
171
+ }
172
+ if (!this.userRepo) {
173
+ throw new Error("userRepo is not set.");
174
+ }
175
+ const results = [];
176
+ // Search for secrets for the user and add each to our list of methods. Not all secrets
177
+ // will be added, only those that are valid for MFA.
178
+ const secrets = await this.secretRepo.find({ userUid: uid }, { ignoreACL: true });
179
+ for (const secret of secrets) {
180
+ const method = this.convertSecretToMethod(secret);
181
+ if (method) {
182
+ results.push(method);
183
+ }
184
+ }
185
+ // Now search for the user's aliases that serve as OTP contacts
186
+ const aliases = await this.aliasRepo.find({ userUid: uid }, {
187
+ ignoreACL: true,
188
+ });
189
+ // Filter aliases to only those that can be notified
190
+ aliases.filter((alias) => [AliasType.EMAIL, AliasType.PHONE].includes(alias.type));
191
+ // Now add all eligible aliases to our list of methods (e.g. email, phone).
192
+ for (const alias of aliases) {
193
+ const method = this.convertAliasToMethod(alias);
194
+ if (method) {
195
+ results.push(method);
196
+ }
197
+ }
198
+ return results;
199
+ }
200
+ /**
201
+ * Retrieves the user with the given unique id.
202
+ * @param uid The unique id of the user to retrieve.
203
+ * @returns The user if found, otherwise `undefined`.
204
+ */
205
+ async getUser(uid) {
206
+ if (!this.userUtils) {
207
+ throw new Error("userRepo is not set.");
208
+ }
209
+ return this.userUtils.lookup(uid);
210
+ }
211
+ async notifyContact(contact, totp) {
212
+ switch (contact.type) {
213
+ case OTPContactType.EMAIL:
214
+ void this.messagingUtils?.sendEmail(this.template, { totp }, {
215
+ to: contact.contact,
216
+ });
217
+ break;
218
+ case OTPContactType.SMS:
219
+ void this.messagingUtils?.sendSMS(this.template, { totp }, {
220
+ to: contact.contact,
221
+ });
222
+ break;
223
+ }
224
+ }
225
+ /**
226
+ * Obfuscates the given alias and returns the obfuscated value.
227
+ * @param contact The contact to obfuscate.
228
+ */
229
+ obfuscateAlias(alias, type) {
230
+ let result = alias;
231
+ switch (type) {
232
+ case AliasType.EMAIL:
233
+ result = result.replace(/^(.).*(.{2})(@)/, "$1***$2$3");
234
+ break;
235
+ case AliasType.NAME:
236
+ result = result.replace(/.(?=.{3})/g, "*");
237
+ break;
238
+ case AliasType.PHONE:
239
+ result = result.replace(/.(?=.{4})/g, "*");
240
+ break;
241
+ }
242
+ return result;
243
+ }
244
+ async verify(name, password) {
245
+ if (!this.secretRepo) {
246
+ throw new Error("Secret repository not set.");
247
+ }
248
+ if (!this.userUtils) {
249
+ throw new Error("User repository not set.");
250
+ }
251
+ const user = await this.userUtils.lookup(name);
252
+ if (!user) {
253
+ throw new Error("Invalid authorization request.");
254
+ }
255
+ let secrets = await this.secretRepo.find({
256
+ userUid: user.uid,
257
+ type: SecretType.PASSWORD,
258
+ }, {
259
+ ignoreACL: true,
260
+ });
261
+ // Try all known passwords until at least one succeeds
262
+ let success = false;
263
+ for (const secret of secrets) {
264
+ const argon = await importArgon2();
265
+ success = await argon.verify(secret.data, password);
266
+ if (success) {
267
+ break;
268
+ }
269
+ }
270
+ if (!success) {
271
+ throw new Error("Invalid authorization request.");
272
+ }
273
+ return user;
274
+ }
275
+ }
276
+ __decorate([
277
+ Inject(AuthMiddleware),
278
+ __metadata("design:type", AuthMiddleware)
279
+ ], BaseAuthMFARoute.prototype, "authMiddleware", void 0);
280
+ __decorate([
281
+ Config("auth"),
282
+ __metadata("design:type", Object)
283
+ ], BaseAuthMFARoute.prototype, "jwtConfig", void 0);
284
+ __decorate([
285
+ Inject(ObjectFactory),
286
+ __metadata("design:type", ObjectFactory)
287
+ ], BaseAuthMFARoute.prototype, "objectFactory", void 0);
288
+ __decorate([
289
+ Inject(MessagingUtils),
290
+ __metadata("design:type", MessagingUtils)
291
+ ], BaseAuthMFARoute.prototype, "messagingUtils", void 0);
292
+ __decorate([
293
+ Init,
294
+ __metadata("design:type", Function),
295
+ __metadata("design:paramtypes", []),
296
+ __metadata("design:returntype", Promise)
297
+ ], BaseAuthMFARoute.prototype, "initialize", null);
298
+ __decorate([
299
+ Summary("Authenticate MFA"),
300
+ Description("Authenticates the user using HTTP MFA and returns a JSON Web Token access token to be used with future API requests."),
301
+ Returns([AuthResult, undefined]),
302
+ Auth(["mfa"]),
303
+ Get(),
304
+ Post(),
305
+ __param(0, AuthUser),
306
+ __metadata("design:type", Function),
307
+ __metadata("design:paramtypes", [Object]),
308
+ __metadata("design:returntype", Promise)
309
+ ], BaseAuthMFARoute.prototype, "authenticate", null);
310
+ //# sourceMappingURL=BaseAuthMFARoute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseAuthMFARoute.js","sourceRoot":"","sources":["../../../src/routes/BaseAuthMFARoute.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+EAA+E;AAC/E,6CAA6C;AAC7C,+EAA+E;AAC/E,OAAO,EAAW,QAAQ,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACnH,OAAO,EAAS,SAAS,EAAE,UAAU,EAAU,UAAU,EAAQ,MAAM,oBAAoB,CAAC;AAC5F,OAAO,EAAa,aAAa,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACnG,OAAO,EAAc,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAAC;AAClD,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC;AACxD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;AAC5C,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC;AAEtC;;;;GAIG;AACH,MAAM,OAAgB,gBAAgB;IAAtC;QAqBI,2EAA2E;QACjE,aAAQ,GAAW,WAAW,CAAC;IA0S7C,CAAC;IApSG;;OAEG;IAEa,AAAN,KAAK,CAAC,UAAU;QACtB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACrC,IAAI,CAAC,SAAS,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,SAAS,EAAE;gBAC7D,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI;gBAC1B,IAAI,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC;aAC1B,CAAC,CAAC;QACP,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACvC,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,SAAS,EAAE;gBAC9D,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI;gBAC3B,IAAI,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;aAC3B,CAAC,CAAC;QACP,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,SAAS,EAAE;gBAC5D,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI;gBACzB,IAAI,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;aACzB,CAAC,CAAC;QACP,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACvD,IAAI,CAAC,SAAS,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,SAAS,EAAE;gBAC7D,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC;aAC1C,CAAC,CAAC;QACP,CAAC;QAED,MAAM,OAAO,GAAuB,IAAI,kBAAkB,EAAE,CAAC;QAC7D,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAgB,MAAM,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,WAAW,EAAE;YAC5E,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,CAAC,OAAO,CAAC;SAClB,CAAC,CAAC;QACH,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC1D,CAAC;IAED;;OAEG;IASU,AAAN,KAAK,CAAC,YAAY,CAAW,IAAa;QAC7C,MAAM,KAAK,GAAW,MAAM,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACvE,OAAO,IAAI,UAAU,CAAC;YAClB,KAAK;YACL,IAAI;SACP,CAAC,CAAC;IACP,CAAC;IAES,oBAAoB,CAAC,KAAY,EAAE,SAAmB;QAC5D,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,SAAS,CAAC,KAAK;gBAChB,OAAO;oBACH,EAAE,EAAE,KAAK,CAAC,GAAG;oBACb,IAAI,EAAE;wBACF,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK;wBAC/E,IAAI,EAAE,cAAc,CAAC,KAAK;wBAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;qBAC3B;oBACD,IAAI,EAAE,aAAa,CAAC,GAAG;iBAC1B,CAAC;YACN,KAAK,SAAS,CAAC,KAAK;gBAChB,OAAO;oBACH,EAAE,EAAE,KAAK,CAAC,GAAG;oBACb,IAAI,EAAE;wBACF,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK;wBAC/E,IAAI,EAAE,cAAc,CAAC,GAAG;wBACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;qBAC3B;oBACD,IAAI,EAAE,aAAa,CAAC,GAAG;iBAC1B,CAAC;QACV,CAAC;QAED,OAAO,SAAS,CAAC;IACrB,CAAC;IAES,qBAAqB,CAAC,MAAS;QACrC,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,UAAU,CAAC,KAAK;gBACjB,OAAO;oBACH,EAAE,EAAE,MAAM,CAAC,GAAG;oBACd,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,IAAI,EAAE,aAAa,CAAC,KAAK;iBAC5B,CAAC;YACN,KAAK,UAAU,CAAC,IAAI;gBAChB,OAAO;oBACH,EAAE,EAAE,MAAM,CAAC,GAAG;oBACd,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,IAAI,EAAE,aAAa,CAAC,IAAI;iBAC3B,CAAC;QACV,CAAC;QAED,OAAO,SAAS,CAAC;IACrB,CAAC;IAED;;;OAGG;IACO,KAAK,CAAC,SAAS,CAAC,EAAU;QAChC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC9C,CAAC;QAED,iFAAiF;QACjF,yDAAyD;QACzD,MAAM,MAAM,GAAkB,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrF,IAAI,MAAM,EAAE,CAAC;YACT,OAAO,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC;QAED,qCAAqC;QACrC,MAAM,KAAK,GAAkB,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnF,IAAI,KAAK,EAAE,CAAC;YACR,OAAO,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,SAAS,CAAC;IACrB,CAAC;IAED;;;;;OAKG;IACO,KAAK,CAAC,UAAU,CAAC,GAAW;QAClC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,OAAO,GAAgB,EAAE,CAAC;QAEhC,uFAAuF;QACvF,oDAAoD;QACpD,MAAM,OAAO,GAAQ,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC3B,MAAM,MAAM,GAA0B,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;YACzE,IAAI,MAAM,EAAE,CAAC;gBACT,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzB,CAAC;QACL,CAAC;QAED,+DAA+D;QAC/D,MAAM,OAAO,GAAQ,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAC1C,EAAE,OAAO,EAAE,GAAG,EAAE,EAChB;YACI,SAAS,EAAE,IAAI;SAClB,CACJ,CAAC;QAEF,oDAAoD;QACpD,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAEnF,2EAA2E;QAC3E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,MAAM,GAA0B,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;YACvE,IAAI,MAAM,EAAE,CAAC;gBACT,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzB,CAAC;QACL,CAAC;QAED,OAAO,OAAO,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACO,KAAK,CAAC,OAAO,CAAC,GAAW;QAC/B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC;IAES,KAAK,CAAC,aAAa,CAAC,OAAmB,EAAE,IAAY;QAC3D,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,cAAc,CAAC,KAAK;gBACrB,KAAK,IAAI,CAAC,cAAc,EAAE,SAAS,CAC/B,IAAI,CAAC,QAAQ,EACb,EAAE,IAAI,EAAE,EACR;oBACI,EAAE,EAAE,OAAO,CAAC,OAAO;iBACtB,CACJ,CAAC;gBACF,MAAM;YACV,KAAK,cAAc,CAAC,GAAG;gBACnB,KAAK,IAAI,CAAC,cAAc,EAAE,OAAO,CAC7B,IAAI,CAAC,QAAQ,EACb,EAAE,IAAI,EAAE,EACR;oBACI,EAAE,EAAE,OAAO,CAAC,OAAO;iBACtB,CACJ,CAAC;gBACF,MAAM;QACd,CAAC;IACL,CAAC;IAED;;;OAGG;IACO,cAAc,CAAC,KAAa,EAAE,IAAe;QACnD,IAAI,MAAM,GAAW,KAAK,CAAC;QAE3B,QAAQ,IAAI,EAAE,CAAC;YACX,KAAK,SAAS,CAAC,KAAK;gBAChB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC;gBACxD,MAAM;YACV,KAAK,SAAS,CAAC,IAAI;gBACf,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;gBAC3C,MAAM;YACV,KAAK,SAAS,CAAC,KAAK;gBAChB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;gBAC3C,MAAM;QACd,CAAC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;IAES,KAAK,CAAC,MAAM,CAAC,IAAY,EAAE,QAAgB;QACjD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,IAAI,GAAkB,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9D,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACtD,CAAC;QAED,IAAI,OAAO,GAAQ,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CACzC;YACI,OAAO,EAAE,IAAI,CAAC,GAAG;YACjB,IAAI,EAAE,UAAU,CAAC,QAAQ;SAC5B,EACD;YACI,SAAS,EAAE,IAAI;SAClB,CACJ,CAAC;QAEF,sDAAsD;QACtD,IAAI,OAAO,GAAY,KAAK,CAAC;QAC7B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,CAAC;YACnC,OAAO,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACpD,IAAI,OAAO,EAAE,CAAC;gBACV,MAAM;YACV,CAAC;QACL,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ;AAxTa;IADT,MAAM,CAAC,cAAc,CAAC;8BACI,cAAc;wDAAC;AAGhC;IADT,MAAM,CAAC,MAAM,CAAC;;mDACW;AAGhB;IADT,MAAM,CAAC,aAAa,CAAC;8BACI,aAAa;uDAAC;AAG9B;IADT,MAAM,CAAC,cAAc,CAAC;8BACI,cAAc;wDAAC;AAe1B;IADf,IAAI;;;;kDAgDJ;AAaY;IARZ,OAAO,CAAC,kBAAkB,CAAC;IAC3B,WAAW,CACR,sHAAsH,CACzH;IACA,OAAO,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAChC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC;IACb,GAAG,EAAE;IACL,IAAI,EAAE;IACoB,WAAA,QAAQ,CAAA;;;;oDAMlC"}
@@ -0,0 +1,231 @@
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
+ ///////////////////////////////////////////////////////////////////////////////
14
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
15
+ ///////////////////////////////////////////////////////////////////////////////
16
+ import "reflect-metadata";
17
+ import { JWTUtils, MessagingUtils, ObjectDecorators } from "@rapidrest/core";
18
+ import { RouteDecorators, DocDecorators, RepoUtils, AuthMiddleware, ObjectFactory } from "@rapidrest/service-core";
19
+ import { AliasType, AuthResult, ContactType } from "../models/types.js";
20
+ import { OIDCStrategy, OIDCStrategyOptions } from "../auth/OIDCStrategy.js";
21
+ import * as uuid from "uuid";
22
+ import { UserUtils } from "./UserUtils.js";
23
+ const { Config, Init, Inject } = ObjectDecorators;
24
+ const { Summary, Description, Returns } = DocDecorators;
25
+ const { Auth, Get, Post } = RouteDecorators;
26
+ const AuthUser = RouteDecorators.User;
27
+ /**
28
+ *
29
+ *
30
+ * @author Jean-Philippe Steinmetz
31
+ */
32
+ export class BaseAuthOIDCRoute {
33
+ /**
34
+ * Called on server startup to initialize the route with any defaults.
35
+ */
36
+ async initialize() {
37
+ if (!this.authMiddleware) {
38
+ throw new Error("authMiddleware is not set.");
39
+ }
40
+ if (!this.objectFactory) {
41
+ throw new Error("objectFactory is not set.");
42
+ }
43
+ if (!this.aliasRepo && this.aliasClass) {
44
+ this.aliasRepo = await this.objectFactory.newInstance(RepoUtils, {
45
+ name: this.aliasClass.name,
46
+ args: [this.aliasClass],
47
+ });
48
+ }
49
+ if (!this.profileRepo && this.profileClass) {
50
+ this.profileRepo = await this.objectFactory.newInstance(RepoUtils, {
51
+ name: this.profileClass.name,
52
+ args: [this.profileClass],
53
+ });
54
+ }
55
+ if (!this.userRepo && this.userClass) {
56
+ this.userRepo = await this.objectFactory.newInstance(RepoUtils, {
57
+ name: this.userClass.name,
58
+ args: [this.userClass],
59
+ });
60
+ }
61
+ if (!this.userUtils && this.userClass && this.aliasClass) {
62
+ this.userUtils = await this.objectFactory.newInstance(UserUtils, {
63
+ name: "default",
64
+ args: [this.userClass, this.aliasClass],
65
+ });
66
+ }
67
+ const options = new OIDCStrategyOptions("oauth", this.providerConfig);
68
+ options.getUser = async (token, profile) => {
69
+ if (!this.aliasRepo) {
70
+ throw new Error("aliasRepo is not set.");
71
+ }
72
+ if (!this.profileRepo) {
73
+ throw new Error("profileRepo is not set.");
74
+ }
75
+ if (!this.userRepo) {
76
+ throw new Error("userRepo is not set.");
77
+ }
78
+ if (!this.userUtils) {
79
+ throw new Error("userUtils is not set.");
80
+ }
81
+ // The provider-scoped external id (`<provider>:<id>`) is the most reliable way to recognize
82
+ // a returning user across logins — unlike email, it doesn't depend on the provider actually
83
+ // returning a (verified) email address, it can't collide with another provider's namespace,
84
+ // and it can't change if the user updates their email with the provider.
85
+ const oauthAlias = `${profile.provider}:${profile.id}`;
86
+ let user = await this.userUtils.lookup(oauthAlias);
87
+ const foundByOAuthAlias = user !== undefined;
88
+ // Fall back to the (verified) email alias — this recognizes an account that either
89
+ // registered before this provider-id lookup existed, or was created via another method
90
+ // (e.g. password) and is now authenticating with this provider for the first time.
91
+ if (!user) {
92
+ user = await this.userUtils.lookup(profile.email ?? profile.id);
93
+ }
94
+ if (!user) {
95
+ // Create a new user for the given profile
96
+ const newUser = {
97
+ uid: uuid.v4(),
98
+ dateCreated: new Date(),
99
+ dateModified: new Date(),
100
+ version: 0,
101
+ roles: [],
102
+ scopes: [],
103
+ };
104
+ user = await this.userRepo.create(newUser, { ignoreACL: true });
105
+ // Now create a profile for the user
106
+ const newProfile = {
107
+ avatar: profile.avatar ?? "",
108
+ birthdate: profile.birthdate ? new Date(profile.birthdate) : undefined,
109
+ contacts: [],
110
+ givenName: profile.givenName ?? "",
111
+ familyName: profile.familyName ?? "",
112
+ preferences: {
113
+ contact: [],
114
+ },
115
+ uid: user.uid,
116
+ dateCreated: new Date(),
117
+ dateModified: new Date(),
118
+ version: 0,
119
+ };
120
+ if (profile.email) {
121
+ newProfile.contacts.push({
122
+ contact: profile.email,
123
+ type: ContactType.EMAIL,
124
+ verified: profile.email_verified ?? false,
125
+ });
126
+ }
127
+ if (profile.email && profile.email_verified) {
128
+ const newAlias = {
129
+ alias: profile.email,
130
+ type: AliasType.EMAIL,
131
+ userUid: user.uid,
132
+ verified: true,
133
+ uid: uuid.v4(),
134
+ dateCreated: new Date(),
135
+ dateModified: new Date(),
136
+ version: 0,
137
+ };
138
+ await this.aliasRepo.create(newAlias, { ignoreACL: true });
139
+ }
140
+ if (profile.phone) {
141
+ newProfile.contacts.push({
142
+ contact: profile.phone,
143
+ type: ContactType.PHONE,
144
+ verified: profile.phone_verified ?? false,
145
+ });
146
+ }
147
+ if (profile.phone && profile.phone_verified) {
148
+ const newAlias = {
149
+ alias: profile.phone,
150
+ type: AliasType.PHONE,
151
+ userUid: user.uid,
152
+ verified: true,
153
+ uid: uuid.v4(),
154
+ dateCreated: new Date(),
155
+ dateModified: new Date(),
156
+ version: 0,
157
+ };
158
+ await this.aliasRepo.create(newAlias, { ignoreACL: true });
159
+ }
160
+ await this.profileRepo.create(newProfile, { ignoreACL: true });
161
+ }
162
+ // Persist the provider-scoped alias so this user is recognized by it on future logins,
163
+ // regardless of how they were resolved above. Skipped when that's exactly how `user` was
164
+ // just found, since the alias is already there.
165
+ if (!foundByOAuthAlias) {
166
+ const newOAuthAlias = {
167
+ alias: oauthAlias,
168
+ type: AliasType.OAUTH,
169
+ userUid: user.uid,
170
+ verified: true,
171
+ uid: uuid.v4(),
172
+ dateCreated: new Date(),
173
+ dateModified: new Date(),
174
+ version: 0,
175
+ };
176
+ await this.aliasRepo.create(newOAuthAlias, { ignoreACL: true });
177
+ }
178
+ return user;
179
+ };
180
+ const strategy = await this.objectFactory.newInstance(OIDCStrategy, {
181
+ name: "default",
182
+ args: [options],
183
+ });
184
+ this.authMiddleware.register(strategy.name, strategy);
185
+ }
186
+ /**
187
+ * Authenticates the user using OIDC and returns a JSON Web Token access token to be used with future API requests.
188
+ */
189
+ async login(user) {
190
+ const token = await JWTUtils.createToken(this.jwtConfig, user);
191
+ return new AuthResult({
192
+ token,
193
+ user,
194
+ });
195
+ }
196
+ }
197
+ __decorate([
198
+ Inject(AuthMiddleware),
199
+ __metadata("design:type", AuthMiddleware)
200
+ ], BaseAuthOIDCRoute.prototype, "authMiddleware", void 0);
201
+ __decorate([
202
+ Config("auth"),
203
+ __metadata("design:type", Object)
204
+ ], BaseAuthOIDCRoute.prototype, "jwtConfig", void 0);
205
+ __decorate([
206
+ Inject(ObjectFactory),
207
+ __metadata("design:type", ObjectFactory)
208
+ ], BaseAuthOIDCRoute.prototype, "objectFactory", void 0);
209
+ __decorate([
210
+ Inject(MessagingUtils),
211
+ __metadata("design:type", MessagingUtils)
212
+ ], BaseAuthOIDCRoute.prototype, "messagingUtils", void 0);
213
+ __decorate([
214
+ Init,
215
+ __metadata("design:type", Function),
216
+ __metadata("design:paramtypes", []),
217
+ __metadata("design:returntype", Promise)
218
+ ], BaseAuthOIDCRoute.prototype, "initialize", null);
219
+ __decorate([
220
+ Summary("Login OIDC"),
221
+ Description("Authenticates the user using OAuth 2.0 / OpenID Connect and returns a JSON Web Token access token to be used with future API requests."),
222
+ Returns([AuthResult, undefined]),
223
+ Auth(["oauth"]),
224
+ Get(),
225
+ Post(),
226
+ __param(0, AuthUser),
227
+ __metadata("design:type", Function),
228
+ __metadata("design:paramtypes", [Object]),
229
+ __metadata("design:returntype", Promise)
230
+ ], BaseAuthOIDCRoute.prototype, "login", null);
231
+ //# sourceMappingURL=BaseAuthOIDCRoute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseAuthOIDCRoute.js","sourceRoot":"","sources":["../../../src/routes/BaseAuthOIDCRoute.ts"],"names":[],"mappings":"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"}