@node-c/domain-iam 1.0.0-alpha9 → 1.0.0-beta0

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 (104) hide show
  1. package/dist/common/definitions/common.constants.d.ts +6 -1
  2. package/dist/common/definitions/common.constants.js +5 -0
  3. package/dist/common/definitions/common.constants.js.map +1 -1
  4. package/dist/module/iam.module.js.map +1 -1
  5. package/dist/services/authentication/iam.authentication.definitions.d.ts +79 -16
  6. package/dist/services/authentication/iam.authentication.definitions.js +6 -9
  7. package/dist/services/authentication/iam.authentication.definitions.js.map +1 -1
  8. package/dist/services/authentication/iam.authentication.service.d.ts +10 -3
  9. package/dist/services/authentication/iam.authentication.service.js +30 -2
  10. package/dist/services/authentication/iam.authentication.service.js.map +1 -1
  11. package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.definitions.d.ts +38 -0
  12. package/dist/services/{authenticationLocal/iam.authenticationLocal.definitions.js → authenticationOAuth2/iam.authenticationOAuth2.definitions.js} +1 -1
  13. package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.definitions.js.map +1 -0
  14. package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.service.d.ts +24 -0
  15. package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.service.js +299 -0
  16. package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.service.js.map +1 -0
  17. package/dist/services/authenticationOAuth2/index.d.ts +2 -0
  18. package/dist/services/authenticationOAuth2/index.js +19 -0
  19. package/dist/services/authenticationOAuth2/index.js.map +1 -0
  20. package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.definitions.d.ts +12 -0
  21. package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.definitions.js +3 -0
  22. package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.definitions.js.map +1 -0
  23. package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.service.d.ts +14 -0
  24. package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.service.js +141 -0
  25. package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.service.js.map +1 -0
  26. package/dist/services/authenticationUserLocal/index.d.ts +2 -0
  27. package/dist/services/{authenticationLocal → authenticationUserLocal}/index.js +2 -2
  28. package/dist/services/authenticationUserLocal/index.js.map +1 -0
  29. package/dist/services/authorization/iam.authorization.definitions.d.ts +33 -23
  30. package/dist/services/authorization/iam.authorization.definitions.js +7 -0
  31. package/dist/services/authorization/iam.authorization.definitions.js.map +1 -1
  32. package/dist/services/authorization/iam.authorization.service.d.ts +28 -13
  33. package/dist/services/authorization/iam.authorization.service.js +231 -125
  34. package/dist/services/authorization/iam.authorization.service.js.map +1 -1
  35. package/dist/services/index.d.ts +4 -2
  36. package/dist/services/index.js +4 -2
  37. package/dist/services/index.js.map +1 -1
  38. package/dist/services/mfa/iam.mfa.definitions.d.ts +21 -0
  39. package/dist/services/mfa/iam.mfa.definitions.js +8 -0
  40. package/dist/services/mfa/iam.mfa.definitions.js.map +1 -0
  41. package/dist/services/mfa/iam.mfa.service.d.ts +9 -0
  42. package/dist/services/mfa/iam.mfa.service.js +31 -0
  43. package/dist/services/mfa/iam.mfa.service.js.map +1 -0
  44. package/dist/services/mfa/index.d.ts +2 -0
  45. package/dist/services/{users → mfa}/index.js +2 -2
  46. package/dist/services/mfa/index.js.map +1 -0
  47. package/dist/services/tokenManager/iam.tokenManager.definitions.d.ts +14 -3
  48. package/dist/services/tokenManager/iam.tokenManager.definitions.js.map +1 -1
  49. package/dist/services/tokenManager/iam.tokenManager.service.d.ts +23 -9
  50. package/dist/services/tokenManager/iam.tokenManager.service.js +111 -43
  51. package/dist/services/tokenManager/iam.tokenManager.service.js.map +1 -1
  52. package/dist/services/userManager/iam.userManager.definitions.d.ts +45 -0
  53. package/dist/services/userManager/iam.userManager.definitions.js +8 -0
  54. package/dist/services/userManager/iam.userManager.definitions.js.map +1 -0
  55. package/dist/services/userManager/iam.userManager.service.d.ts +32 -0
  56. package/dist/services/userManager/iam.userManager.service.js +331 -0
  57. package/dist/services/userManager/iam.userManager.service.js.map +1 -0
  58. package/dist/services/userManager/index.d.ts +2 -0
  59. package/dist/services/userManager/index.js +19 -0
  60. package/dist/services/userManager/index.js.map +1 -0
  61. package/package.json +9 -8
  62. package/src/common/definitions/common.constants.ts +14 -0
  63. package/src/common/definitions/index.ts +1 -0
  64. package/src/index.ts +3 -0
  65. package/src/module/iam.definitions.ts +15 -0
  66. package/src/module/iam.module.ts +29 -0
  67. package/src/module/index.ts +2 -0
  68. package/src/services/authentication/iam.authentication.definitions.ts +100 -0
  69. package/src/services/authentication/iam.authentication.service.ts +103 -0
  70. package/src/services/authentication/index.ts +2 -0
  71. package/src/services/authenticationOAuth2/iam.authenticationOAuth2.definitions.ts +71 -0
  72. package/src/services/authenticationOAuth2/iam.authenticationOAuth2.service.ts +350 -0
  73. package/src/services/authenticationOAuth2/index.ts +2 -0
  74. package/src/services/authenticationUserLocal/iam.authenticationUserLocal.definitions.ts +29 -0
  75. package/src/services/authenticationUserLocal/iam.authenticationUserLocal.service.ts +171 -0
  76. package/src/services/authenticationUserLocal/index.ts +2 -0
  77. package/src/services/authorization/iam.authorization.definitions.ts +55 -0
  78. package/src/services/authorization/iam.authorization.service.ts +384 -0
  79. package/src/services/authorization/index.ts +2 -0
  80. package/src/services/index.ts +7 -0
  81. package/src/services/mfa/iam.mfa.definitions.ts +28 -0
  82. package/src/services/mfa/iam.mfa.service.ts +38 -0
  83. package/src/services/mfa/index.ts +2 -0
  84. package/src/services/tokenManager/iam.tokenManager.definitions.ts +61 -0
  85. package/src/services/tokenManager/iam.tokenManager.service.ts +290 -0
  86. package/src/services/tokenManager/index.ts +2 -0
  87. package/src/services/userManager/iam.userManager.definitions.ts +73 -0
  88. package/src/services/userManager/iam.userManager.service.ts +461 -0
  89. package/src/services/userManager/index.ts +2 -0
  90. package/dist/services/authenticationLocal/iam.authenticationLocal.definitions.d.ts +0 -11
  91. package/dist/services/authenticationLocal/iam.authenticationLocal.definitions.js.map +0 -1
  92. package/dist/services/authenticationLocal/iam.authenticationLocal.service.d.ts +0 -10
  93. package/dist/services/authenticationLocal/iam.authenticationLocal.service.js +0 -70
  94. package/dist/services/authenticationLocal/iam.authenticationLocal.service.js.map +0 -1
  95. package/dist/services/authenticationLocal/index.d.ts +0 -2
  96. package/dist/services/authenticationLocal/index.js.map +0 -1
  97. package/dist/services/users/iam.users.definitions.d.ts +0 -30
  98. package/dist/services/users/iam.users.definitions.js +0 -8
  99. package/dist/services/users/iam.users.definitions.js.map +0 -1
  100. package/dist/services/users/iam.users.service.d.ts +0 -16
  101. package/dist/services/users/iam.users.service.js +0 -93
  102. package/dist/services/users/iam.users.service.js.map +0 -1
  103. package/dist/services/users/index.d.ts +0 -2
  104. package/dist/services/users/index.js.map +0 -1
@@ -0,0 +1,461 @@
1
+ import {
2
+ AppConfigDomainIAM,
3
+ AppConfigDomainIAMAuthenticationStep,
4
+ ApplicationError,
5
+ ConfigProviderService,
6
+ DataDefaultData,
7
+ DataEntityService,
8
+ DataFindOneOptions,
9
+ DomainEntityService,
10
+ DomainEntityServiceDefaultData,
11
+ GenericObject,
12
+ getNested,
13
+ setNested
14
+ } from '@node-c/core';
15
+
16
+ import ld from 'lodash';
17
+
18
+ import {
19
+ IAMUserManagerCreateAccessTokenOptions,
20
+ IAMUserManagerCreateAccessTokenReturnData,
21
+ IAMUserManagerExecuteStepData,
22
+ IAMUserManagerExecuteStepOptions,
23
+ IAMUserManagerExecuteStepResult,
24
+ IAMUserManagerGetUserWithPermissionsDataOptions,
25
+ IAMUserManagerUserTokenEnityFields,
26
+ IAMUserManagerUserTokenUserIdentifier,
27
+ IAMUserManagerUserWithPermissionsData
28
+ } from './iam.userManager.definitions';
29
+
30
+ import {
31
+ IAMAuthenticationCompleteData,
32
+ IAMAuthenticationCompleteOptions,
33
+ IAMAuthenticationGetUserDataFromExternalTokenPayloadsData,
34
+ IAMAuthenticationService,
35
+ IAMAuthenticationType
36
+ } from '../authentication';
37
+ import { IAMAuthenticationOAuth2CompleteResult, IAMAuthenticationOAuth2Service } from '../authenticationOAuth2';
38
+ import {
39
+ IAMAuthenticationUserLocalCompleteResult,
40
+ IAMAuthenticationUserLocalService
41
+ } from '../authenticationUserLocal';
42
+ import { IAMTokenManagerService, TokenType } from '../tokenManager';
43
+
44
+ // TODO: create user (signup); this should include password hashing
45
+ // TODO: update password (incl. hashing)
46
+ // TODO: reset password
47
+ // TODO: console.info -> logger
48
+ // TODO: periodic checking of external access tokens and their revoking
49
+ export class IAMUserManagerService<
50
+ User extends object,
51
+ Data extends DomainEntityServiceDefaultData<Partial<User>> = DomainEntityServiceDefaultData<Partial<User>>,
52
+ DataEntityServiceData extends DataDefaultData<Partial<User>> = DataDefaultData<Partial<User>>
53
+ > {
54
+ constructor(
55
+ // eslint-disable-next-line no-unused-vars
56
+ protected authServices: {
57
+ [IAMAuthenticationType.OAuth2]?: IAMAuthenticationOAuth2Service<object, object>;
58
+ [IAMAuthenticationType.UserLocal]?: IAMAuthenticationUserLocalService<object, object>;
59
+ } & { [serviceName: string]: IAMAuthenticationService<object, object> },
60
+ // eslint-disable-next-line no-unused-vars
61
+ protected configProvider: ConfigProviderService,
62
+ // eslint-disable-next-line no-unused-vars
63
+ protected dataUsersAuthCacheService: DataEntityService<GenericObject>,
64
+ // eslint-disable-next-line no-unused-vars
65
+ protected domainUsersEntityService: DomainEntityService<
66
+ User,
67
+ DataEntityService<User, DataEntityServiceData>,
68
+ Data,
69
+ Record<string, DataEntityService<Partial<User>, DataDefaultData<object>>> | undefined
70
+ >,
71
+ // eslint-disable-next-line no-unused-vars
72
+ protected moduleName: string,
73
+ // eslint-disable-next-line no-unused-vars
74
+ protected tokenManager: IAMTokenManagerService<IAMUserManagerUserTokenEnityFields>
75
+ ) {}
76
+
77
+ // TODO: clear the cache from the previous steps
78
+ // TODO: make the issuing of local tokens work with purgeOldFromStore = false
79
+ async createAccessToken<AuthData = unknown>(
80
+ options: IAMUserManagerCreateAccessTokenOptions<AuthData>
81
+ ): Promise<IAMUserManagerCreateAccessTokenReturnData<User>> {
82
+ const { configProvider, moduleName } = this;
83
+ const moduleConfig = configProvider.config.domain[moduleName] as AppConfigDomainIAM;
84
+ const { accessTokenExpiryTimeInMinutes, defaultUserIdentifierField, refreshTokenExpiryTimeInMinutes } =
85
+ moduleConfig;
86
+ const {
87
+ auth: { type: authType },
88
+ rememberUser
89
+ } = options;
90
+ console.info(
91
+ `[Domain.${moduleName}.UserManager]: Login attempt started${options.step ? ` for step ${options.step}` : ''}.`
92
+ );
93
+ // 1. Make sure the auth service actually exists - local, oauth2, etc.
94
+ const authService = this.authServices[authType] as IAMAuthenticationService<object, object>;
95
+ if (!authService) {
96
+ console.info(`[Domain.${moduleName}.UserManager]: No authService ${authType} found.`);
97
+ throw new ApplicationError('Authentication failed.');
98
+ }
99
+ // 2. Get the user-specific configuration from the authService.
100
+ const authServiceBehaviorConfig = authService.getUserCreateAccessTokenConfig();
101
+ let externalAccessToken: string | undefined;
102
+ let externalRefreshToken: string | undefined;
103
+ let issueTokens = false;
104
+ let step: AppConfigDomainIAMAuthenticationStep;
105
+ let userFilterField: string | undefined;
106
+ let userFilterValue: unknown | undefined;
107
+ // 3. Prepare the step behavior based on the configuration.
108
+ // 3.1. Complete step
109
+ if (options.step === AppConfigDomainIAMAuthenticationStep.Complete) {
110
+ issueTokens = true;
111
+ step = AppConfigDomainIAMAuthenticationStep.Complete;
112
+ }
113
+ // 3.2. Initiate step - assumed implicitly.
114
+ else {
115
+ step = AppConfigDomainIAMAuthenticationStep.Initiate;
116
+ }
117
+ let stepConfig = authServiceBehaviorConfig[step];
118
+ // 3. Run the authentication method itself.
119
+ // eslint-disable-next-line prefer-const
120
+ let { stepResult, user, ...otherStepData } = await this.executeStep(options, {
121
+ authService,
122
+ name: step,
123
+ stepConfig
124
+ });
125
+ // 4. Run the final step, if this is the first step no mfa has been used.
126
+ if (step === AppConfigDomainIAMAuthenticationStep.Initiate && !stepResult.mfaUsed) {
127
+ issueTokens = true;
128
+ step = AppConfigDomainIAMAuthenticationStep.Complete;
129
+ stepConfig = authServiceBehaviorConfig[step];
130
+ const finalStepData = await this.executeStep(options, {
131
+ authService,
132
+ name: step,
133
+ stepConfig: ld.omit(stepConfig, 'cache')
134
+ });
135
+ stepResult = finalStepData.stepResult;
136
+ user = user ?? finalStepData.user;
137
+ userFilterField = finalStepData.userFilterField;
138
+ userFilterValue = finalStepData.userFilterValue;
139
+ }
140
+ // 5. Process the external access, refresh and, optionally, id tokens that are returned by the step execution.
141
+ const actualStepResult = stepResult as
142
+ | IAMAuthenticationOAuth2CompleteResult
143
+ | IAMAuthenticationUserLocalCompleteResult;
144
+ if (!userFilterField && otherStepData.userFilterField) {
145
+ userFilterField = otherStepData.userFilterField;
146
+ }
147
+ if (!userFilterValue && otherStepData.userFilterValue) {
148
+ userFilterValue = otherStepData.userFilterValue;
149
+ }
150
+ if ('useReturnedTokens' in stepConfig && stepConfig.useReturnedTokens && stepConfig.authReturnsTokens) {
151
+ // Make sure we have an accessToken in the response and set the access and refresh tokens in variables for later use.
152
+ if (!actualStepResult.accessToken) {
153
+ console.info(
154
+ `[Domain.${moduleName}.UserManager]: Login attempt failed for ${userFilterField} ${userFilterValue} - no accessToken returned from the authService and useReturnedTokens is set to true.`
155
+ );
156
+ throw new ApplicationError('Authentication failed.');
157
+ }
158
+ externalAccessToken = actualStepResult.accessToken;
159
+ if (actualStepResult.refreshToken) {
160
+ externalRefreshToken = actualStepResult.refreshToken;
161
+ }
162
+ }
163
+ // 6. Token management. In this case, we will definitely have the user, or will be force to create it.
164
+ if (issueTokens) {
165
+ if (!user) {
166
+ console.info(
167
+ `[Domain.${moduleName}.UserManager]: Login attempt failed at step ${step} - user is required when issueTokens is set to true.`
168
+ );
169
+ throw new ApplicationError('Authentication failed.');
170
+ }
171
+ let refreshToken: string | undefined;
172
+ // 6.1. Create a local refresh token and save it. The payload contains the external refresh token, if it exists.
173
+ const userIdentifierValue = user[defaultUserIdentifierField as keyof User];
174
+ if (externalRefreshToken || !externalAccessToken) {
175
+ const {
176
+ result: { token: localRefreshToken }
177
+ } = await this.tokenManager.create(
178
+ {
179
+ type: TokenType.Refresh,
180
+ [IAMUserManagerUserTokenUserIdentifier.FieldName]: userIdentifierValue,
181
+ ...(externalRefreshToken
182
+ ? {
183
+ externalToken: externalRefreshToken,
184
+ externalTokenAuthService: authType as IAMAuthenticationType
185
+ }
186
+ : {})
187
+ },
188
+ {
189
+ expiresInMinutes:
190
+ (externalRefreshToken &&
191
+ 'refreshTokenExpiresIn' in actualStepResult &&
192
+ actualStepResult.refreshTokenExpiresIn) ||
193
+ (rememberUser ? undefined : refreshTokenExpiryTimeInMinutes),
194
+ identifierDataField: IAMUserManagerUserTokenUserIdentifier.FieldName,
195
+ persist: true,
196
+ purgeOldFromData: true,
197
+ tokenContentOnlyFields: ['externalToken']
198
+ }
199
+ );
200
+ refreshToken = localRefreshToken;
201
+ }
202
+ // 6.2. Create a local access token and save it. The payload contains the external access token, if it exists.
203
+ const {
204
+ result: { token: accessToken }
205
+ } = await this.tokenManager.create(
206
+ {
207
+ refreshToken,
208
+ type: TokenType.Access,
209
+ user,
210
+ [IAMUserManagerUserTokenUserIdentifier.FieldName]: userIdentifierValue,
211
+ ...(externalAccessToken
212
+ ? {
213
+ externalToken: externalAccessToken,
214
+ externalTokenAuthService: authType as IAMAuthenticationType
215
+ }
216
+ : {})
217
+ },
218
+ {
219
+ expiresInMinutes:
220
+ (externalAccessToken &&
221
+ 'accessTokenExpiresIn' in actualStepResult &&
222
+ actualStepResult.accessTokenExpiresIn) ||
223
+ accessTokenExpiryTimeInMinutes,
224
+ identifierDataField: IAMUserManagerUserTokenUserIdentifier.FieldName,
225
+ persist: true,
226
+ purgeOldFromData: true,
227
+ tokenContentOnlyFields: ['externalToken', 'refreshToken', 'user']
228
+ }
229
+ );
230
+ console.info(
231
+ `[Domain.${moduleName}.UserManager]: Login attempt successful for ${userFilterField} ${userFilterValue}.`
232
+ );
233
+ return { accessToken, refreshToken, user };
234
+ }
235
+ const returnData: IAMUserManagerCreateAccessTokenReturnData<User> = { nextStepsRequired: true };
236
+ if (stepConfig.stepResultPublicFields?.length) {
237
+ stepConfig.stepResultPublicFields.forEach(fieldName => {
238
+ setNested(
239
+ returnData,
240
+ fieldName,
241
+ getNested(stepResult, fieldName, { removeNestedFieldEscapeSign: true }).unifiedValue
242
+ );
243
+ });
244
+ }
245
+ return returnData;
246
+ }
247
+
248
+ private async executeStep<AuthData>(
249
+ data: IAMUserManagerExecuteStepData<AuthData>,
250
+ options: IAMUserManagerExecuteStepOptions<User>
251
+ ): Promise<IAMUserManagerExecuteStepResult<User>> {
252
+ const { configProvider, domainUsersEntityService, moduleName } = this;
253
+ const { defaultUserIdentifierField } = configProvider.config.domain[moduleName] as AppConfigDomainIAM;
254
+ const {
255
+ // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
256
+ auth: { type: _authType, ...authData },
257
+ filters: userFilters,
258
+ mainFilterField
259
+ } = data;
260
+ const { authService, stepConfig, name: stepName } = options;
261
+ const { cache: cacheSettings, findUser, findUserBeforeAuth, validWithoutUser } = stepConfig;
262
+ const hasFilters = userFilters && Object.keys(userFilters).length;
263
+ const stepInputData: { data: unknown; options?: unknown } = { data: ld.cloneDeep(authData) };
264
+ let user: IAMUserManagerUserWithPermissionsData<User, unknown> | null = null;
265
+ let userFilterField: string | undefined;
266
+ let userFilterValue: unknown | undefined;
267
+ // 1. Find the user based on the provided filters, if enabled.
268
+ if (findUser && findUserBeforeAuth) {
269
+ if (!hasFilters) {
270
+ console.info(`[Domain.${moduleName}.UserManager]: No filters provided for findUserBeforeToken=true.`);
271
+ throw new ApplicationError('Authentication failed.');
272
+ }
273
+ userFilterField = mainFilterField;
274
+ userFilterValue = userFilters[userFilterField];
275
+ user = await this.getUserForStepExecution({ filters: userFilters, mainFilterField: userFilterField });
276
+ if (!user) {
277
+ console.info(
278
+ `[Domain.${moduleName}.UserManager]: Login attempt failed for ${userFilterField} ${userFilterValue} - user not found.`
279
+ );
280
+ throw new ApplicationError('Authentication failed.');
281
+ }
282
+ }
283
+ stepInputData.options = {
284
+ context: user || ({} as IAMUserManagerUserWithPermissionsData<User, unknown>),
285
+ contextIdentifierField: defaultUserIdentifierField
286
+ };
287
+ // 2. Restore the cache, if configured
288
+ if (cacheSettings && 'use' in cacheSettings && cacheSettings.use) {
289
+ const cacheInput: { data: unknown; options: unknown } = {
290
+ data: stepInputData.data,
291
+ options: stepInputData.options
292
+ };
293
+ const cacheResult = await this.dataUsersAuthCacheService.findOne({
294
+ filters: {
295
+ [cacheSettings.settings.cacheFieldName]: getNested(cacheInput, cacheSettings.settings.inputFieldName)
296
+ .unifiedValue
297
+ }
298
+ });
299
+ if (cacheResult) {
300
+ for (const inputName in cacheSettings.use) {
301
+ const { overwrite, use } = cacheSettings.use[inputName as keyof typeof cacheSettings.use]!;
302
+ if (!use) {
303
+ continue;
304
+ }
305
+ const valueFromCache =
306
+ getNested(cacheResult, inputName, { removeNestedFieldEscapeSign: true }).unifiedValue || {};
307
+ const inputNameKey = inputName as keyof typeof stepInputData;
308
+ if (overwrite) {
309
+ stepInputData[inputNameKey] = ld.merge(stepInputData[inputNameKey], valueFromCache);
310
+ continue;
311
+ }
312
+ stepInputData[inputNameKey] = ld.merge(valueFromCache, stepInputData[inputNameKey]);
313
+ }
314
+ }
315
+ }
316
+ // 3. Run the step method itself.
317
+ let stepResult = await authService[stepName as 'complete' | 'initiate'](
318
+ stepInputData.data as IAMAuthenticationCompleteData,
319
+ stepInputData.options as IAMAuthenticationCompleteOptions<User>
320
+ );
321
+ // 4. Process the step result
322
+ if (!stepResult.valid || (stepResult.mfaUsed && !stepResult.mfaValid)) {
323
+ console.info(`[Domain.${moduleName}.UserManager]: Bad step result:`, stepResult);
324
+ throw new ApplicationError('Authentication failed.');
325
+ }
326
+ // 5. If the step returns tokens and decoding is enabled, decode the reutrned tokens for payloads
327
+ if ('decodeReturnedTokens' in stepConfig && stepConfig.decodeReturnedTokens) {
328
+ const tokensForDecoding: Record<string, string> = {};
329
+ const tokenKeys = ['accessToken', 'idToken', 'refreshToken'];
330
+ tokenKeys.forEach(tokenKey => {
331
+ const resultForKey = stepResult[tokenKey as keyof typeof stepResult] as unknown as string;
332
+ if (!resultForKey) {
333
+ return;
334
+ }
335
+ tokensForDecoding[tokenKey] = resultForKey;
336
+ });
337
+ const externalTokenPayloads = await authService.getPayloadsFromExternalTokens(tokensForDecoding);
338
+ stepResult = { ...stepResult, ...externalTokenPayloads };
339
+ }
340
+ // 6. Find the user based on either the provided filters, or on the stepResult data, if enabled
341
+ if (findUser && !findUserBeforeAuth) {
342
+ if ('findUserInAuthResultBy' in stepConfig && stepConfig.findUserInAuthResultBy) {
343
+ const { userFieldName, resultFieldName } = stepConfig.findUserInAuthResultBy;
344
+ const payloadFilterValue = getNested(stepResult, resultFieldName, {
345
+ removeNestedFieldEscapeSign: true
346
+ }).unifiedValue;
347
+ userFilterField = userFieldName;
348
+ if (typeof payloadFilterValue !== 'undefined') {
349
+ userFilterValue = payloadFilterValue;
350
+ }
351
+ if (typeof userFilterValue !== 'undefined') {
352
+ user = await this.getUserForStepExecution({
353
+ filters: { [userFieldName]: userFilterValue },
354
+ mainFilterField: userFieldName
355
+ });
356
+ }
357
+ } else if (hasFilters) {
358
+ userFilterField = mainFilterField;
359
+ userFilterValue = userFilters[userFilterField];
360
+ user = await this.getUserForStepExecution({
361
+ filters: userFilters,
362
+ mainFilterField: userFilterField
363
+ });
364
+ }
365
+ }
366
+ // 7. Create a user using the data from the tokens returned by the step execution, if enabled and there is no user found.
367
+ if (!user && 'createUser' in stepConfig && stepConfig.createUser) {
368
+ const userData = await authService.getUserDataFromExternalTokenPayloads(
369
+ stepResult as IAMAuthenticationGetUserDataFromExternalTokenPayloadsData
370
+ );
371
+ if (userData) {
372
+ const { result: createdUser } = await domainUsersEntityService.create(userData as unknown as Data['Create']);
373
+ user = await this.getUserWithPermissionsData(
374
+ {
375
+ filters: {
376
+ [defaultUserIdentifierField]: createdUser[defaultUserIdentifierField as keyof typeof createdUser]
377
+ }
378
+ },
379
+ { keepPassword: false }
380
+ );
381
+ }
382
+ }
383
+ if (validWithoutUser !== true && !user) {
384
+ console.info(
385
+ `[Domain.${moduleName}.UserManager]: Login attempt failed ${userFilterField && userFilterValue ? `for ${userFilterField} ${userFilterValue} ` : ''}- user not found.`
386
+ );
387
+ throw new ApplicationError('Authentication failed.');
388
+ }
389
+ if (user && 'password' in user) {
390
+ delete user.password;
391
+ }
392
+ // 8. Populate the cache, if configured
393
+ if (stepResult.mfaUsed && cacheSettings && 'populate' in cacheSettings && cacheSettings.populate) {
394
+ const cacheInput: GenericObject = {
395
+ data: stepInputData.data,
396
+ options: stepInputData.options,
397
+ result: stepResult
398
+ };
399
+ const cacheData: GenericObject = {};
400
+ for (const inputName in cacheSettings.populate) {
401
+ const inputSettings = cacheSettings.populate[inputName as keyof typeof cacheSettings.populate];
402
+ if (inputSettings instanceof Array) {
403
+ const innerInputItem: GenericObject = {};
404
+ inputSettings.forEach(inputItemSettings => {
405
+ const { cacheFieldName, inputFieldName } = inputItemSettings;
406
+ setNested(
407
+ innerInputItem,
408
+ cacheFieldName,
409
+ getNested(cacheInput, inputFieldName, { removeNestedFieldEscapeSign: true }).unifiedValue
410
+ );
411
+ });
412
+ cacheData[inputName] = innerInputItem;
413
+ continue;
414
+ }
415
+ cacheData[inputName] = cacheInput[inputName];
416
+ }
417
+ await this.dataUsersAuthCacheService.create({
418
+ ...cacheData,
419
+ [cacheSettings.settings.cacheFieldName]: getNested(cacheInput, cacheSettings.settings.inputFieldName)
420
+ .unifiedValue
421
+ });
422
+ }
423
+ return { stepResult, user, userFilterField, userFilterValue };
424
+ }
425
+
426
+ protected async getUserForStepExecution(options: {
427
+ filters: GenericObject;
428
+ mainFilterField: string;
429
+ }): Promise<IAMUserManagerUserWithPermissionsData<User, unknown> | null> {
430
+ const { configProvider, moduleName } = this;
431
+ const { defaultUserIdentifierField } = configProvider.config.domain[moduleName] as AppConfigDomainIAM;
432
+ const { mainFilterField } = options;
433
+ let filters: GenericObject = options.filters;
434
+ let user: IAMUserManagerUserWithPermissionsData<User, unknown> | null = null;
435
+ if (mainFilterField !== defaultUserIdentifierField) {
436
+ const mainFilterFieldResult = await this.domainUsersEntityService.findOne({ filters });
437
+ if (!mainFilterFieldResult.result) {
438
+ return null;
439
+ }
440
+ filters = {
441
+ [defaultUserIdentifierField]:
442
+ mainFilterFieldResult.result[defaultUserIdentifierField as keyof typeof mainFilterFieldResult.result]
443
+ };
444
+ } else {
445
+ filters = options.filters;
446
+ }
447
+ user = await this.getUserWithPermissionsData({ filters }, { keepPassword: true });
448
+ return user;
449
+ }
450
+
451
+ async getUserWithPermissionsData(
452
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
453
+ _options: DataFindOneOptions,
454
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
455
+ _privateOptions?: IAMUserManagerGetUserWithPermissionsDataOptions
456
+ ): Promise<IAMUserManagerUserWithPermissionsData<User, unknown> | null> {
457
+ throw new ApplicationError(
458
+ `Method ${this.moduleName}.IAMUserManagerService.getUserWithPermissionsData not implemented.`
459
+ );
460
+ }
461
+ }
@@ -0,0 +1,2 @@
1
+ export * from './iam.userManager.definitions';
2
+ export * from './iam.userManager.service';
@@ -1,11 +0,0 @@
1
- import { AuthenticateUserAuthData, AuthenticateUserResult, AuthenticateUserUserData } from '../authentication';
2
- export type LocalAuthenticateUserUserData<UserFields extends object> = AuthenticateUserUserData<{
3
- password: string;
4
- } & UserFields>;
5
- export interface LocalAuthenticateUserAuthData extends AuthenticateUserAuthData {
6
- password: string;
7
- }
8
- export type LocalAuthenticateUserResult = AuthenticateUserResult;
9
- export type LocalAuthenticationUserMFAEntity<UserMFAFields extends object | undefined> = {
10
- code: string;
11
- } & UserMFAFields;
@@ -1 +0,0 @@
1
- {"version":3,"file":"iam.authenticationLocal.definitions.js","sourceRoot":"","sources":["../../../src/services/authenticationLocal/iam.authenticationLocal.definitions.ts"],"names":[],"mappings":""}
@@ -1,10 +0,0 @@
1
- import { ConfigProviderService, PersistanceEntityService } from '@node-c/core';
2
- import { LocalAuthenticateUserAuthData, LocalAuthenticateUserResult, LocalAuthenticateUserUserData, LocalAuthenticationUserMFAEntity } from './iam.authenticationLocal.definitions';
3
- import { IAMAuthenticationService } from '../authentication';
4
- export declare class IAMAuthenticationLocalService<AuthenticationUserFields extends object, UserMFAEntityFields extends object | undefined = undefined> extends IAMAuthenticationService<AuthenticationUserFields> {
5
- protected configProvider: ConfigProviderService;
6
- protected moduleName: string;
7
- protected persistanceUsersMFAService?: PersistanceEntityService<LocalAuthenticationUserMFAEntity<UserMFAEntityFields>> | undefined;
8
- constructor(configProvider: ConfigProviderService, moduleName: string, persistanceUsersMFAService?: PersistanceEntityService<LocalAuthenticationUserMFAEntity<UserMFAEntityFields>> | undefined);
9
- authenticateUser(userData: LocalAuthenticateUserUserData<AuthenticationUserFields>, authData: LocalAuthenticateUserAuthData): Promise<LocalAuthenticateUserResult>;
10
- }
@@ -1,70 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.IAMAuthenticationLocalService = void 0;
16
- const crypto_1 = __importDefault(require("crypto"));
17
- const core_1 = require("@node-c/core");
18
- const authentication_1 = require("../authentication");
19
- class IAMAuthenticationLocalService extends authentication_1.IAMAuthenticationService {
20
- constructor(configProvider, moduleName, persistanceUsersMFAService) {
21
- super(configProvider, moduleName);
22
- this.configProvider = configProvider;
23
- this.moduleName = moduleName;
24
- this.persistanceUsersMFAService = persistanceUsersMFAService;
25
- }
26
- authenticateUser(userData, authData) {
27
- return __awaiter(this, void 0, void 0, function* () {
28
- const { configProvider, moduleName, persistanceUsersMFAService } = this;
29
- const { defaultUserIdentifierField, userPasswordHMACAlgorithm, userPasswordSecret } = configProvider.config.domain[moduleName];
30
- const { mfaEnabled, password: userPassword } = userData;
31
- const { mfaCode, mfaType, password: authPassword } = authData;
32
- const userIdentifierField = authData.userIdentifierField || defaultUserIdentifierField;
33
- const userIdentifierValue = userData[userIdentifierField];
34
- const userMFAIdentifierField = authData.userMFAIdentifierField || userIdentifierField;
35
- let wrongPassword = false;
36
- if (!userPasswordHMACAlgorithm || !userPasswordSecret || !userPassword) {
37
- wrongPassword = true;
38
- }
39
- else {
40
- const computedPassword = crypto_1.default
41
- .createHmac(userPasswordHMACAlgorithm, userPasswordSecret)
42
- .update(`${authPassword}`)
43
- .digest('hex')
44
- .toString();
45
- if (computedPassword !== userPassword) {
46
- wrongPassword = true;
47
- }
48
- }
49
- if (wrongPassword) {
50
- console.info(`[IAMAuthenticationLocalService]: Login attempt failed for user "${userIdentifierValue}" - wrong password.`);
51
- throw new core_1.ApplicationError('Invalid user identifier or password.');
52
- }
53
- if (mfaEnabled) {
54
- if (!mfaCode || mfaType !== authentication_1.UserMFAKnownType.Local || !persistanceUsersMFAService) {
55
- throw new core_1.ApplicationError('Invalid MFA code.');
56
- }
57
- const storedCodeData = yield persistanceUsersMFAService.findOne({
58
- filters: { [userMFAIdentifierField]: userIdentifierValue }
59
- });
60
- if (!(storedCodeData === null || storedCodeData === void 0 ? void 0 : storedCodeData.code) || mfaCode !== (storedCodeData === null || storedCodeData === void 0 ? void 0 : storedCodeData.code)) {
61
- console.info(`[IAMAuthenticationLocalService]: Login attempt failed for user ${userIdentifierValue} - missing or wrong mfa code.`);
62
- throw new core_1.ApplicationError('Invalid MFA code.');
63
- }
64
- }
65
- return { valid: true };
66
- });
67
- }
68
- }
69
- exports.IAMAuthenticationLocalService = IAMAuthenticationLocalService;
70
- //# sourceMappingURL=iam.authenticationLocal.service.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"iam.authenticationLocal.service.js","sourceRoot":"","sources":["../../../src/services/authenticationLocal/iam.authenticationLocal.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,oDAA4B;AAE5B,uCAAqH;AASrH,sDAA+E;AAE/E,MAAa,6BAGX,SAAQ,yCAAkD;IAC1D,YACY,cAAqC,EACrC,UAAkB,EAElB,0BAET;QAED,KAAK,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;QAPxB,mBAAc,GAAd,cAAc,CAAuB;QACrC,eAAU,GAAV,UAAU,CAAQ;QAElB,+BAA0B,GAA1B,0BAA0B,CAEnC;IAGH,CAAC;IAEK,gBAAgB,CACpB,QAAiE,EACjE,QAAuC;;YAEvC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,0BAA0B,EAAE,GAAG,IAAI,CAAC;YACxE,MAAM,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,MAAM,CAChH,UAAU,CACW,CAAC;YACxB,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAC;YACxD,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAC;YAC9D,MAAM,mBAAmB,GAAG,QAAQ,CAAC,mBAAmB,IAAI,0BAA0B,CAAC;YACvF,MAAM,mBAAmB,GAAG,QAAQ,CAAC,mBAAqD,CAAC,CAAC;YAC5F,MAAM,sBAAsB,GAAG,QAAQ,CAAC,sBAAsB,IAAI,mBAAmB,CAAC;YACtF,IAAI,aAAa,GAAG,KAAK,CAAC;YAC1B,IAAI,CAAC,yBAAyB,IAAI,CAAC,kBAAkB,IAAI,CAAC,YAAY,EAAE,CAAC;gBACvE,aAAa,GAAG,IAAI,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,MAAM,gBAAgB,GAAG,gBAAM;qBAC5B,UAAU,CAAC,yBAAyB,EAAE,kBAAkB,CAAC;qBACzD,MAAM,CAAC,GAAG,YAAY,EAAE,CAAC;qBACzB,MAAM,CAAC,KAAK,CAAC;qBACb,QAAQ,EAAE,CAAC;gBACd,IAAI,gBAAgB,KAAK,YAAY,EAAE,CAAC;oBACtC,aAAa,GAAG,IAAI,CAAC;gBACvB,CAAC;YACH,CAAC;YACD,IAAI,aAAa,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CACV,mEAAmE,mBAAmB,qBAAqB,CAC5G,CAAC;gBACF,MAAM,IAAI,uBAAgB,CAAC,sCAAsC,CAAC,CAAC;YACrE,CAAC;YAED,IAAI,UAAU,EAAE,CAAC;gBACf,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,iCAAgB,CAAC,KAAK,IAAI,CAAC,0BAA0B,EAAE,CAAC;oBAClF,MAAM,IAAI,uBAAgB,CAAC,mBAAmB,CAAC,CAAC;gBAClD,CAAC;gBACD,MAAM,cAAc,GAAG,MAAM,0BAA0B,CAAC,OAAO,CAAC;oBAC9D,OAAO,EAAE,EAAE,CAAC,sBAAsB,CAAC,EAAE,mBAAmB,EAAE;iBAC3D,CAAC,CAAC;gBACH,IAAI,CAAC,CAAA,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,IAAI,CAAA,IAAI,OAAO,MAAK,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,IAAI,CAAA,EAAE,CAAC;oBAC9D,OAAO,CAAC,IAAI,CACV,kEAAkE,mBAAmB,+BAA+B,CACrH,CAAC;oBACF,MAAM,IAAI,uBAAgB,CAAC,mBAAmB,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;KAAA;CACF;AAhED,sEAgEC"}
@@ -1,2 +0,0 @@
1
- export * from './iam.authenticationLocal.definitions';
2
- export * from './iam.authenticationLocal.service';
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/authenticationLocal/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wEAAsD;AACtD,oEAAkD"}
@@ -1,30 +0,0 @@
1
- import { GenericObject } from '@node-c/core';
2
- import { UserAuthType, UserMFAType } from '../authentication';
3
- import { AuthorizationPoint } from '../authorization';
4
- export interface CreateAccessTokenOptions<AuthData = unknown> {
5
- auth: {
6
- mfaType?: UserMFAType;
7
- type: UserAuthType;
8
- } & AuthData;
9
- filters: GenericObject;
10
- mainFilterField: string;
11
- rememberUser?: boolean;
12
- }
13
- export interface CreateAccessTokenReturnData<UserData> {
14
- accessToken: string;
15
- refreshToken: string;
16
- user: UserData;
17
- }
18
- export interface GetUserWithPermissionsDataOptions {
19
- keepPassword?: boolean;
20
- }
21
- export type UserWithPermissionsData<UserData, AuthorizationPointId> = {
22
- currentAuthorizationPoints: GenericObject<AuthorizationPoint<AuthorizationPointId>>;
23
- } & UserData;
24
- export interface UserTokenEnityFields<UserId = unknown> {
25
- refreshToken?: string;
26
- userId: UserId;
27
- }
28
- export declare enum UserTokenUserIdentifier {
29
- FieldName = "userId"
30
- }
@@ -1,8 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.UserTokenUserIdentifier = void 0;
4
- var UserTokenUserIdentifier;
5
- (function (UserTokenUserIdentifier) {
6
- UserTokenUserIdentifier["FieldName"] = "userId";
7
- })(UserTokenUserIdentifier || (exports.UserTokenUserIdentifier = UserTokenUserIdentifier = {}));
8
- //# sourceMappingURL=iam.users.definitions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"iam.users.definitions.js","sourceRoot":"","sources":["../../../src/services/users/iam.users.definitions.ts"],"names":[],"mappings":";;;AAkCA,IAAY,uBAGX;AAHD,WAAY,uBAAuB;IAEjC,+CAAoB,CAAA;AACtB,CAAC,EAHW,uBAAuB,uCAAvB,uBAAuB,QAGlC"}
@@ -1,16 +0,0 @@
1
- import { ConfigProviderService, DomainEntityService, DomainEntityServiceDefaultData, PersistanceEntityService, PersistanceFindOneOptions } from '@node-c/core';
2
- import { CreateAccessTokenOptions, CreateAccessTokenReturnData, GetUserWithPermissionsDataOptions, UserTokenEnityFields, UserWithPermissionsData } from './iam.users.definitions';
3
- import { IAMAuthenticationService, UserAuthType } from '../authentication';
4
- import { IAMTokenManagerService } from '../tokenManager';
5
- export declare class IAMUsersService<User extends object, Data extends DomainEntityServiceDefaultData<Partial<User>> = DomainEntityServiceDefaultData<Partial<User>>> extends DomainEntityService<User, PersistanceEntityService<User>, Data, Record<string, PersistanceEntityService<Partial<User>>> | undefined> {
6
- protected configProvider: ConfigProviderService;
7
- protected moduleName: string;
8
- protected persistanceUsersService: PersistanceEntityService<User>;
9
- protected tokenManager: IAMTokenManagerService<UserTokenEnityFields>;
10
- protected userAuthServices: Record<UserAuthType, IAMAuthenticationService<User>>;
11
- protected defaultMethods: string[];
12
- protected additionalPersistanceEntityServices?: Record<string, PersistanceEntityService<Partial<User>>> | undefined;
13
- constructor(configProvider: ConfigProviderService, moduleName: string, persistanceUsersService: PersistanceEntityService<User>, tokenManager: IAMTokenManagerService<UserTokenEnityFields>, userAuthServices: Record<UserAuthType, IAMAuthenticationService<User>>, defaultMethods?: string[], additionalPersistanceEntityServices?: Record<string, PersistanceEntityService<Partial<User>>> | undefined);
14
- createAccessToken(options: CreateAccessTokenOptions): Promise<CreateAccessTokenReturnData<User>>;
15
- getUserWithPermissionsData(_options: PersistanceFindOneOptions, _privateOptions?: GetUserWithPermissionsDataOptions): Promise<UserWithPermissionsData<User, unknown> | null>;
16
- }