@node-c/domain-iam 1.0.0-beta7 → 1.0.0-beta8

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 (134) hide show
  1. package/dist/common/definitions/common.constants.d.ts +13 -9
  2. package/dist/common/definitions/common.constants.js +13 -10
  3. package/dist/common/definitions/common.constants.js.map +1 -1
  4. package/dist/services/authentication/iam.authentication.definitions.d.ts +11 -2
  5. package/dist/services/authentication/iam.authentication.definitions.js +1 -1
  6. package/dist/services/authentication/iam.authentication.service.d.ts +9 -4
  7. package/dist/services/authentication/iam.authentication.service.js +95 -4
  8. package/dist/services/authentication/iam.authentication.service.js.map +1 -1
  9. package/dist/services/authenticationConsumer/iam.authenticationConsumer.definitions.d.ts +15 -0
  10. package/dist/services/authenticationConsumer/iam.authenticationConsumer.definitions.js +3 -0
  11. package/dist/services/authenticationConsumer/iam.authenticationConsumer.definitions.js.map +1 -0
  12. package/dist/services/authenticationConsumer/iam.authenticationConsumer.service.d.ts +12 -0
  13. package/dist/services/authenticationConsumer/iam.authenticationConsumer.service.js +135 -0
  14. package/dist/services/authenticationConsumer/iam.authenticationConsumer.service.js.map +1 -0
  15. package/dist/services/authenticationConsumer/index.d.ts +2 -0
  16. package/dist/services/authenticationConsumer/index.js +19 -0
  17. package/dist/services/authenticationConsumer/index.js.map +1 -0
  18. package/dist/services/{userManager/iam.userManager.definitions.d.ts → authenticationManager/iam.authenticationManager.definitions.d.ts} +11 -15
  19. package/dist/services/authenticationManager/iam.authenticationManager.definitions.js +8 -0
  20. package/dist/services/authenticationManager/iam.authenticationManager.definitions.js.map +1 -0
  21. package/dist/services/authenticationManager/iam.authenticationManager.service.d.ts +33 -0
  22. package/dist/services/{userManager/iam.userManager.service.js → authenticationManager/iam.authenticationManager.service.js} +140 -72
  23. package/dist/services/authenticationManager/iam.authenticationManager.service.js.map +1 -0
  24. package/dist/services/authenticationManager/index.d.ts +2 -0
  25. package/dist/services/authenticationManager/index.js +19 -0
  26. package/dist/services/authenticationManager/index.js.map +1 -0
  27. package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.definitions.d.ts +5 -2
  28. package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.service.d.ts +2 -14
  29. package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.service.js +53 -95
  30. package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.service.js.map +1 -1
  31. package/dist/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.definitions.d.ts +19 -0
  32. package/dist/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.definitions.js +3 -0
  33. package/dist/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.definitions.js.map +1 -0
  34. package/dist/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.service.d.ts +11 -0
  35. package/dist/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.service.js +69 -0
  36. package/dist/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.service.js.map +1 -0
  37. package/dist/services/authenticationOAuth2Consumer/index.d.ts +2 -0
  38. package/dist/services/authenticationOAuth2Consumer/index.js +19 -0
  39. package/dist/services/authenticationOAuth2Consumer/index.js.map +1 -0
  40. package/dist/services/authenticationPassthrough/iam.authenticationPassthrough.definitions.d.ts +14 -0
  41. package/dist/services/authenticationPassthrough/iam.authenticationPassthrough.definitions.js +3 -0
  42. package/dist/services/authenticationPassthrough/iam.authenticationPassthrough.definitions.js.map +1 -0
  43. package/dist/services/authenticationPassthrough/iam.authenticationPassthrough.service.d.ts +9 -0
  44. package/dist/services/authenticationPassthrough/iam.authenticationPassthrough.service.js +70 -0
  45. package/dist/services/authenticationPassthrough/iam.authenticationPassthrough.service.js.map +1 -0
  46. package/dist/services/authenticationPassthrough/index.d.ts +2 -0
  47. package/dist/services/authenticationPassthrough/index.js +19 -0
  48. package/dist/services/authenticationPassthrough/index.js.map +1 -0
  49. package/dist/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.definitions.d.ts +18 -0
  50. package/dist/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.definitions.js +3 -0
  51. package/dist/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.definitions.js.map +1 -0
  52. package/dist/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.service.d.ts +10 -0
  53. package/dist/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.service.js +68 -0
  54. package/dist/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.service.js.map +1 -0
  55. package/dist/services/authenticationPassthroughConsumer/index.d.ts +2 -0
  56. package/dist/services/authenticationPassthroughConsumer/index.js +19 -0
  57. package/dist/services/authenticationPassthroughConsumer/index.js.map +1 -0
  58. package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.definitions.d.ts +2 -2
  59. package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.service.d.ts +2 -6
  60. package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.service.js +4 -8
  61. package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.service.js.map +1 -1
  62. package/dist/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.definitions.d.ts +8 -0
  63. package/dist/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.definitions.js +3 -0
  64. package/dist/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.definitions.js.map +1 -0
  65. package/dist/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.service.d.ts +8 -0
  66. package/dist/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.service.js +36 -0
  67. package/dist/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.service.js.map +1 -0
  68. package/dist/services/authenticationUserLocalConsumer/index.d.ts +2 -0
  69. package/dist/services/authenticationUserLocalConsumer/index.js +19 -0
  70. package/dist/services/authenticationUserLocalConsumer/index.js.map +1 -0
  71. package/dist/services/authorization/iam.authorization.definitions.d.ts +24 -24
  72. package/dist/services/authorization/iam.authorization.definitions.js +7 -7
  73. package/dist/services/authorization/iam.authorization.definitions.js.map +1 -1
  74. package/dist/services/authorization/iam.authorization.service.d.ts +8 -11
  75. package/dist/services/authorization/iam.authorization.service.js +26 -30
  76. package/dist/services/authorization/iam.authorization.service.js.map +1 -1
  77. package/dist/services/index.d.ts +7 -1
  78. package/dist/services/index.js +7 -1
  79. package/dist/services/index.js.map +1 -1
  80. package/dist/services/tokenManager/iam.tokenManager.definitions.d.ts +4 -1
  81. package/dist/services/tokenManager/iam.tokenManager.definitions.js.map +1 -1
  82. package/dist/services/tokenManager/iam.tokenManager.service.d.ts +2 -2
  83. package/dist/services/tokenManager/iam.tokenManager.service.js +73 -35
  84. package/dist/services/tokenManager/iam.tokenManager.service.js.map +1 -1
  85. package/dist/services/users/index.d.ts +2 -0
  86. package/dist/services/{userManager → users}/index.js +2 -2
  87. package/dist/services/users/index.js.map +1 -0
  88. package/dist/services/users/users.definitions.d.ts +7 -0
  89. package/dist/services/users/users.definitions.js +3 -0
  90. package/dist/services/users/users.definitions.js.map +1 -0
  91. package/dist/services/users/users.service.d.ts +6 -0
  92. package/dist/services/users/users.service.js +39 -0
  93. package/dist/services/users/users.service.js.map +1 -0
  94. package/package.json +2 -2
  95. package/src/common/definitions/common.constants.ts +13 -16
  96. package/src/services/authentication/iam.authentication.definitions.ts +11 -4
  97. package/src/services/authentication/iam.authentication.service.ts +79 -15
  98. package/src/services/authenticationConsumer/iam.authenticationConsumer.definitions.ts +43 -0
  99. package/src/services/authenticationConsumer/iam.authenticationConsumer.service.ts +192 -0
  100. package/src/services/authenticationConsumer/index.ts +2 -0
  101. package/src/services/{userManager/iam.userManager.definitions.ts → authenticationManager/iam.authenticationManager.definitions.ts} +11 -19
  102. package/src/services/{userManager/iam.userManager.service.ts → authenticationManager/iam.authenticationManager.service.ts} +174 -111
  103. package/src/services/authenticationManager/index.ts +2 -0
  104. package/src/services/authenticationOAuth2/iam.authenticationOAuth2.definitions.ts +6 -3
  105. package/src/services/authenticationOAuth2/iam.authenticationOAuth2.service.ts +97 -85
  106. package/src/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.definitions.ts +56 -0
  107. package/src/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.service.ts +93 -0
  108. package/src/services/authenticationOAuth2Consumer/index.ts +2 -0
  109. package/src/services/authenticationPassthrough/iam.authenticationPassthrough.definitions.ts +32 -0
  110. package/src/services/authenticationPassthrough/iam.authenticationPassthrough.service.ts +100 -0
  111. package/src/services/authenticationPassthrough/index.ts +2 -0
  112. package/src/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.definitions.ts +52 -0
  113. package/src/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.service.ts +96 -0
  114. package/src/services/authenticationPassthroughConsumer/index.ts +2 -0
  115. package/src/services/authenticationUserLocal/iam.authenticationUserLocal.definitions.ts +3 -3
  116. package/src/services/authenticationUserLocal/iam.authenticationUserLocal.service.ts +17 -12
  117. package/src/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.definitions.ts +29 -0
  118. package/src/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.service.ts +40 -0
  119. package/src/services/authenticationUserLocalConsumer/index.ts +2 -0
  120. package/src/services/authorization/iam.authorization.definitions.ts +26 -27
  121. package/src/services/authorization/iam.authorization.service.ts +40 -65
  122. package/src/services/index.ts +7 -1
  123. package/src/services/tokenManager/iam.tokenManager.definitions.ts +4 -1
  124. package/src/services/tokenManager/iam.tokenManager.service.ts +98 -45
  125. package/src/services/users/index.ts +2 -0
  126. package/src/services/users/users.definitions.ts +11 -0
  127. package/src/services/users/users.service.ts +46 -0
  128. package/dist/services/userManager/iam.userManager.definitions.js +0 -8
  129. package/dist/services/userManager/iam.userManager.definitions.js.map +0 -1
  130. package/dist/services/userManager/iam.userManager.service.d.ts +0 -33
  131. package/dist/services/userManager/iam.userManager.service.js.map +0 -1
  132. package/dist/services/userManager/index.d.ts +0 -2
  133. package/dist/services/userManager/index.js.map +0 -1
  134. package/src/services/userManager/index.ts +0 -2
@@ -5,8 +5,6 @@ import {
5
5
  ConfigProviderService,
6
6
  DataDefaultData,
7
7
  DataEntityService,
8
- DataFindOneOptions,
9
- DomainEntityService,
10
8
  DomainEntityServiceDefaultData,
11
9
  GenericObject,
12
10
  LoggerService,
@@ -17,17 +15,16 @@ import {
17
15
  import ld from 'lodash';
18
16
 
19
17
  import {
20
- IAMUserManagerCreateAccessTokenOptions,
21
- IAMUserManagerCreateAccessTokenReturnData,
22
- IAMUserManagerExecuteStepData,
23
- IAMUserManagerExecuteStepOptions,
24
- IAMUserManagerExecuteStepResult,
25
- IAMUserManagerGetUserWithPermissionsDataOptions,
26
- IAMUserManagerUserTokenEnityFields,
27
- IAMUserManagerUserTokenUserIdentifier,
28
- IAMUserManagerUserWithPermissionsData
29
- } from './iam.userManager.definitions';
18
+ IAMAuthenticationManagerAuthenticateOptions,
19
+ IAMAuthenticationManagerAuthenticateReturnData,
20
+ IAMAuthenticationManagerExecuteStepData,
21
+ IAMAuthenticationManagerExecuteStepOptions,
22
+ IAMAuthenticationManagerExecuteStepResult,
23
+ IAMAuthenticationManagerUserTokenEnityFields,
24
+ IAMAuthenticationManagerUserTokenUserIdentifier
25
+ } from './iam.authenticationManager.definitions';
30
26
 
27
+ import { Constants } from '../../common/definitions';
31
28
  import {
32
29
  IAMAuthenticationCompleteData,
33
30
  IAMAuthenticationCompleteOptions,
@@ -41,13 +38,14 @@ import {
41
38
  IAMAuthenticationUserLocalService
42
39
  } from '../authenticationUserLocal';
43
40
  import { IAMTokenManagerService, TokenType } from '../tokenManager';
41
+ import { IAMUserWithPermissionsData, IAMUsersService } from '../users';
44
42
 
45
43
  // TODO: create user (signup); this should include password hashing
46
44
  // TODO: update password (incl. hashing)
47
45
  // TODO: reset password
48
46
  // TODO: periodic checking of external access tokens and their revoking
49
- export class IAMUserManagerService<
50
- User extends object,
47
+ export class IAMAuthenticationManagerService<
48
+ User extends object = object,
51
49
  Data extends DomainEntityServiceDefaultData<Partial<User>> = DomainEntityServiceDefaultData<Partial<User>>,
52
50
  DataEntityServiceData extends DataDefaultData<Partial<User>> = DataDefaultData<Partial<User>>
53
51
  > {
@@ -60,28 +58,29 @@ export class IAMUserManagerService<
60
58
  // eslint-disable-next-line no-unused-vars
61
59
  protected configProvider: ConfigProviderService,
62
60
  // eslint-disable-next-line no-unused-vars
63
- protected dataUsersAuthCacheService: DataEntityService<GenericObject>,
61
+ protected logger: LoggerService,
62
+ // eslint-disable-next-line no-unused-vars
63
+ protected moduleName: string,
64
+ // eslint-disable-next-line no-unused-vars
65
+ protected dataUsersAuthCacheService?: DataEntityService<GenericObject>,
64
66
  // eslint-disable-next-line no-unused-vars
65
- protected domainUsersEntityService: DomainEntityService<
67
+ public domainUsersEntityService?: IAMUsersService<
66
68
  User,
67
69
  DataEntityService<User, DataEntityServiceData>,
68
70
  Data,
69
71
  Record<string, DataEntityService<Partial<User>, DataDefaultData<object>>> | undefined
70
72
  >,
71
73
  // eslint-disable-next-line no-unused-vars
72
- protected logger: LoggerService,
73
- // eslint-disable-next-line no-unused-vars
74
- protected moduleName: string,
75
- // eslint-disable-next-line no-unused-vars
76
- protected tokenManager: IAMTokenManagerService<IAMUserManagerUserTokenEnityFields>
74
+ protected tokenManager?: IAMTokenManagerService<IAMAuthenticationManagerUserTokenEnityFields>
77
75
  ) {}
78
76
 
77
+ // TODO: fix expiry vs TTL
79
78
  // TODO: clear the cache from the previous steps
80
79
  // TODO: make the issuing of local tokens work with purgeOldFromStore = false
81
- async createAccessToken<AuthData = unknown>(
82
- options: IAMUserManagerCreateAccessTokenOptions<AuthData>
83
- ): Promise<IAMUserManagerCreateAccessTokenReturnData<User>> {
84
- const { configProvider, logger, moduleName } = this;
80
+ async authenticate<AuthData = unknown>(
81
+ options: IAMAuthenticationManagerAuthenticateOptions<AuthData>
82
+ ): Promise<IAMAuthenticationManagerAuthenticateReturnData<User>> {
83
+ const { configProvider, logger, moduleName, tokenManager } = this;
85
84
  const moduleConfig = configProvider.config.domain[moduleName] as AppConfigDomainIAM;
86
85
  const { accessTokenExpiryTimeInMinutes, defaultUserIdentifierField, refreshTokenExpiryTimeInHours } = moduleConfig;
87
86
  const {
@@ -89,16 +88,16 @@ export class IAMUserManagerService<
89
88
  rememberUser
90
89
  } = options;
91
90
  logger.info(
92
- `[Domain.${moduleName}.UserManager]: Login attempt started${options.step ? ` for step ${options.step}` : ''}.`
91
+ `[Domain.${moduleName}.AuthenticationManager][${authType}]: Login attempt started${options.step ? ` for step ${options.step}` : ''}.`
93
92
  );
94
- // 1. Make sure the auth service actually exists - local, oauth2, etc.
93
+ // 1. Make sure the authentication service actually exists - local, oauth2, etc.
95
94
  const authService = this.authServices[authType] as IAMAuthenticationService<object, object>;
96
95
  if (!authService) {
97
- logger.info(`[Domain.${moduleName}.UserManager]: No authService ${authType} found.`);
96
+ logger.info(`[Domain.${moduleName}.AuthenticationManager][${authType}]: No authService ${authType} found.`);
98
97
  throw new ApplicationError('Authentication failed.');
99
98
  }
100
99
  // 2. Get the user-specific configuration from the authService.
101
- const authServiceBehaviorConfig = authService.getUserCreateAccessTokenConfig();
100
+ const authServiceBehaviorConfig = authService.getUserAuthenticationConfig();
102
101
  let externalAccessToken: string | undefined;
103
102
  let externalRefreshToken: string | undefined;
104
103
  let issueTokens = false;
@@ -126,17 +125,27 @@ export class IAMUserManagerService<
126
125
  // 4. Run the final step, if this is the first step no mfa has been used.
127
126
  if (step === AppConfigDomainIAMAuthenticationStep.Initiate && !stepResult.mfaUsed) {
128
127
  issueTokens = true;
129
- step = AppConfigDomainIAMAuthenticationStep.Complete;
130
- stepConfig = authServiceBehaviorConfig[step];
131
- const finalStepData = await this.executeStep(options, {
132
- authService,
133
- name: step,
134
- stepConfig: ld.omit(stepConfig, 'cache')
135
- });
136
- stepResult = finalStepData.stepResult;
137
- user = user ?? finalStepData.user;
138
- userFilterField = finalStepData.userFilterField;
139
- userFilterValue = finalStepData.userFilterValue;
128
+ // check whether skipping the complete step if mfaUsed is allowed and run the complete step if it isn't
129
+ if (!('skipCompleteStepAllowedOnNoMFA' in stepConfig && stepConfig.skipCompleteStepAllowedOnNoMFA)) {
130
+ step = AppConfigDomainIAMAuthenticationStep.Complete;
131
+ stepConfig = authServiceBehaviorConfig[step];
132
+ const finalStepData = await this.executeStep(options, {
133
+ authService,
134
+ name: step,
135
+ stepConfig: ld.omit(stepConfig, 'cache')
136
+ });
137
+ stepResult = ld.merge(ld.omit(stepResult, ['mfaUsed', 'mfaValid', 'valid']), finalStepData.stepResult);
138
+ user = user ?? finalStepData.user;
139
+ userFilterField = finalStepData.userFilterField;
140
+ userFilterValue = finalStepData.userFilterValue;
141
+ } else {
142
+ if ('userFilterField' in stepResult) {
143
+ userFilterField = stepResult.userFilterField as string;
144
+ }
145
+ if ('userFilterValue' in stepResult) {
146
+ userFilterValue = stepResult.userFilterValue as string;
147
+ }
148
+ }
140
149
  }
141
150
  // 5. Process the external access, refresh and, optionally, id tokens that are returned by the step execution.
142
151
  const actualStepResult = stepResult as
@@ -152,7 +161,7 @@ export class IAMUserManagerService<
152
161
  // Make sure we have an accessToken in the response and set the access and refresh tokens in variables for later use.
153
162
  if (!actualStepResult.accessToken) {
154
163
  logger.info(
155
- `[Domain.${moduleName}.UserManager]: Login attempt failed for ${userFilterField} ${userFilterValue} - no accessToken returned from the authService and useReturnedTokens is set to true.`
164
+ `[Domain.${moduleName}.AuthenticationManager][${authType}]: Login attempt failed for ${userFilterField} ${userFilterValue} - no accessToken returned from the authService and useReturnedTokens is set to true.`
156
165
  );
157
166
  throw new ApplicationError('Authentication failed.');
158
167
  }
@@ -163,39 +172,61 @@ export class IAMUserManagerService<
163
172
  }
164
173
  // 6. Token management. In this case, we will definitely have the user, or will be force to create it.
165
174
  if (issueTokens) {
175
+ if (!tokenManager) {
176
+ throw new ApplicationError(`[${moduleName}][AuthenticationManager] tokenManager not configured.`);
177
+ }
166
178
  if (!user) {
167
179
  logger.info(
168
- `[Domain.${moduleName}.UserManager]: Login attempt failed at step ${step} - user is required when issueTokens is set to true.`
180
+ `[Domain.${moduleName}.AuthenticationManager][${authType}]: Login attempt failed at step ${step} - user is required when issueTokens is set to true.`
169
181
  );
170
182
  throw new ApplicationError('Authentication failed.');
171
183
  }
184
+ const useExternalTokenAsLocal = 'useReturnedTokensAsLocal' in stepConfig && stepConfig.useReturnedTokensAsLocal;
185
+ const userIdentifierValue = user[defaultUserIdentifierField as keyof User];
172
186
  let refreshToken: string | undefined;
187
+ let refreshTokenExpiresIn: number | undefined;
188
+ let refreshTokenTTL: number | undefined;
173
189
  // 6.1. Create a local refresh token and save it. The payload contains the external refresh token, if it exists.
174
- const userIdentifierValue = user[defaultUserIdentifierField as keyof User];
175
190
  if (externalRefreshToken || !externalAccessToken) {
191
+ let externalTokenData: GenericObject = {};
192
+ if (
193
+ externalRefreshToken &&
194
+ 'refreshTokenExpiresIn' in actualStepResult &&
195
+ actualStepResult.refreshTokenExpiresIn
196
+ ) {
197
+ externalTokenData = {
198
+ externalToken: externalRefreshToken,
199
+ externalTokenAuthService: authType as IAMAuthenticationType
200
+ };
201
+ refreshTokenExpiresIn = actualStepResult.refreshTokenExpiresIn;
202
+ } else if (!rememberUser) {
203
+ refreshTokenExpiresIn =
204
+ (refreshTokenExpiryTimeInHours
205
+ ? refreshTokenExpiryTimeInHours
206
+ : Constants.DEFAULT_REFRESH_TOKEN_EXPIRY_TIME_IN_HOURS) * 60;
207
+ }
208
+ if (refreshTokenExpiresIn) {
209
+ refreshTokenTTL =
210
+ refreshTokenExpiresIn *
211
+ (moduleConfig.refreshTokenExpiryStorageTTLMultiplier ||
212
+ Constants.DEFAULT_REFRESH_TOKEN_STORAGE_TTL_MULTIPLIER);
213
+ }
176
214
  const {
177
215
  result: { token: localRefreshToken }
178
- } = await this.tokenManager.create(
216
+ } = await tokenManager.create(
179
217
  {
180
218
  type: TokenType.Refresh,
181
- [IAMUserManagerUserTokenUserIdentifier.FieldName]: userIdentifierValue,
182
- ...(externalRefreshToken
183
- ? {
184
- externalToken: externalRefreshToken,
185
- externalTokenAuthService: authType as IAMAuthenticationType
186
- }
187
- : {})
219
+ [IAMAuthenticationManagerUserTokenUserIdentifier.FieldName]: userIdentifierValue,
220
+ ...externalTokenData
188
221
  },
189
222
  {
190
- expiresInMinutes:
191
- (externalRefreshToken &&
192
- 'refreshTokenExpiresIn' in actualStepResult &&
193
- actualStepResult.refreshTokenExpiresIn) ||
194
- (rememberUser || !refreshTokenExpiryTimeInHours ? undefined : refreshTokenExpiryTimeInHours * 60),
195
- identifierDataField: IAMUserManagerUserTokenUserIdentifier.FieldName,
223
+ expiresInMinutes: refreshTokenExpiresIn,
224
+ identifierDataField: IAMAuthenticationManagerUserTokenUserIdentifier.FieldName,
196
225
  persist: true,
197
226
  purgeOldFromData: true,
198
- tokenContentOnlyFields: ['externalToken']
227
+ tokenContentOnlyFields: ['externalToken'],
228
+ ttl: refreshTokenTTL,
229
+ useExternalTokenAsLocal
199
230
  }
200
231
  );
201
232
  refreshToken = localRefreshToken;
@@ -203,14 +234,19 @@ export class IAMUserManagerService<
203
234
  // 6.2. Create a local access token and save it. The payload contains the external access token, if it exists.
204
235
  const accessTokenExpiresIn =
205
236
  (externalAccessToken && 'accessTokenExpiresIn' in actualStepResult && actualStepResult.accessTokenExpiresIn) ||
206
- accessTokenExpiryTimeInMinutes;
237
+ accessTokenExpiryTimeInMinutes ||
238
+ Constants.DEFAULT_ACCESS_TOKEN_EXPIRY_TIME_IN_HOURS;
239
+ const accessTokenTTL =
240
+ refreshTokenExpiresIn ||
241
+ accessTokenExpiresIn *
242
+ (moduleConfig.accessTokenExpiryStorageTTLMultiplier || Constants.DEFAULT_ACCESS_TOKEN_STORAGE_TTL_MULTIPLIER);
207
243
  const {
208
244
  result: { token: accessToken }
209
- } = await this.tokenManager.create(
245
+ } = await tokenManager.create(
210
246
  {
211
247
  refreshToken,
212
248
  type: TokenType.Access,
213
- [IAMUserManagerUserTokenUserIdentifier.FieldName]: userIdentifierValue,
249
+ [IAMAuthenticationManagerUserTokenUserIdentifier.FieldName]: userIdentifierValue,
214
250
  ...(externalAccessToken
215
251
  ? {
216
252
  externalToken: externalAccessToken,
@@ -220,42 +256,46 @@ export class IAMUserManagerService<
220
256
  },
221
257
  {
222
258
  expiresInMinutes: accessTokenExpiresIn,
223
- identifierDataField: IAMUserManagerUserTokenUserIdentifier.FieldName,
259
+ identifierDataField: IAMAuthenticationManagerUserTokenUserIdentifier.FieldName,
224
260
  persist: true,
225
261
  purgeOldFromData: true,
226
- tokenContentOnlyFields: ['externalToken', 'refreshToken']
262
+ tokenContentOnlyFields: ['externalToken', 'refreshToken'],
263
+ ttl: accessTokenTTL,
264
+ useExternalTokenAsLocal
227
265
  }
228
266
  );
229
267
  // 6.3. Create an idToken. The payload contains the user with permissions data
230
268
  const {
231
269
  result: { token: idToken }
232
- } = await this.tokenManager.create(
270
+ } = await tokenManager.create(
233
271
  {
234
272
  accessToken,
235
273
  type: TokenType.Id,
236
274
  user,
237
- [IAMUserManagerUserTokenUserIdentifier.FieldName]: userIdentifierValue
275
+ [IAMAuthenticationManagerUserTokenUserIdentifier.FieldName]: userIdentifierValue
238
276
  },
239
277
  {
240
278
  expiresInMinutes: accessTokenExpiresIn,
241
- identifierDataField: IAMUserManagerUserTokenUserIdentifier.FieldName,
279
+ identifierDataField: IAMAuthenticationManagerUserTokenUserIdentifier.FieldName,
242
280
  persist: true,
243
281
  purgeOldFromData: true,
244
- tokenContentOnlyFields: ['accessToken', 'user']
282
+ tokenContentOnlyFields: ['accessToken', 'user'],
283
+ ttl: accessTokenTTL
245
284
  }
246
285
  );
247
286
  logger.info(
248
- `[Domain.${moduleName}.UserManager]: Login attempt successful for ${userFilterField} ${userFilterValue}.`
287
+ `[Domain.${moduleName}.AuthenticationManager][${authType}]: Login attempt successful for ${userFilterField} ${userFilterValue}.`
249
288
  );
250
289
  return { accessToken, idToken, refreshToken, user };
251
290
  }
252
- const returnData: IAMUserManagerCreateAccessTokenReturnData<User> = { nextStepsRequired: true };
291
+ const returnData: IAMAuthenticationManagerAuthenticateReturnData<User> = { nextStepsRequired: true };
253
292
  if (stepConfig.stepResultPublicFields?.length) {
254
293
  stepConfig.stepResultPublicFields.forEach(fieldName => {
255
294
  setNested(
256
295
  returnData,
257
296
  fieldName,
258
- getNested(stepResult, fieldName, { removeNestedFieldEscapeSign: true }).unifiedValue
297
+ getNested(stepResult, fieldName, { removeNestedFieldEscapeSign: true }).unifiedValue,
298
+ { removeNestedFieldEscapeSign: true }
259
299
  );
260
300
  });
261
301
  }
@@ -263,28 +303,29 @@ export class IAMUserManagerService<
263
303
  }
264
304
 
265
305
  private async executeStep<AuthData>(
266
- data: IAMUserManagerExecuteStepData<AuthData>,
267
- options: IAMUserManagerExecuteStepOptions<User>
268
- ): Promise<IAMUserManagerExecuteStepResult<User>> {
269
- const { configProvider, domainUsersEntityService, logger, moduleName } = this;
306
+ data: IAMAuthenticationManagerExecuteStepData<AuthData>,
307
+ options: IAMAuthenticationManagerExecuteStepOptions<User>
308
+ ): Promise<IAMAuthenticationManagerExecuteStepResult<User>> {
309
+ const { configProvider, dataUsersAuthCacheService, domainUsersEntityService, logger, moduleName } = this;
270
310
  const { defaultUserIdentifierField } = configProvider.config.domain[moduleName] as AppConfigDomainIAM;
271
311
  const {
272
- // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
273
- auth: { type: _authType, ...authData },
312
+ auth: { type: authType, ...authData },
274
313
  filters: userFilters,
275
314
  mainFilterField
276
315
  } = data;
277
316
  const { authService, stepConfig, name: stepName } = options;
278
317
  const { cache: cacheSettings, findUser, findUserBeforeAuth, validWithoutUser } = stepConfig;
279
318
  const hasFilters = userFilters && Object.keys(userFilters).length;
319
+ const logPrefix = `[Domain.${moduleName}.AuthenticationManager][executeStep][${authType}][${stepName}]`;
280
320
  const stepInputData: { data: unknown; options?: unknown } = { data: ld.cloneDeep(authData) };
281
- let user: IAMUserManagerUserWithPermissionsData<User, unknown> | null = null;
321
+ let runFindUserInExternalTokenPayloads = false;
322
+ let user: IAMUserWithPermissionsData<User, unknown> | null = null;
282
323
  let userFilterField: string | undefined;
283
324
  let userFilterValue: unknown | undefined;
284
325
  // 1. Find the user based on the provided filters, if enabled.
285
326
  if (findUser && findUserBeforeAuth) {
286
327
  if (!hasFilters) {
287
- logger.info(`[Domain.${moduleName}.UserManager]: No filters provided for findUserBeforeToken=true.`);
328
+ logger.info(`${logPrefix}[Part 1]: No filters provided for findUserBeforeToken=true.`);
288
329
  throw new ApplicationError('Authentication failed.');
289
330
  }
290
331
  userFilterField = mainFilterField;
@@ -292,22 +333,33 @@ export class IAMUserManagerService<
292
333
  user = await this.getUserForStepExecution({ filters: userFilters, mainFilterField: userFilterField });
293
334
  if (!user) {
294
335
  logger.info(
295
- `[Domain.${moduleName}.UserManager]: Login attempt failed for ${userFilterField} ${userFilterValue} - user not found.`
336
+ `${logPrefix}[Part 1]: Login attempt failed for ${userFilterField} ${userFilterValue} - user not found.`
296
337
  );
297
338
  throw new ApplicationError('Authentication failed.');
298
339
  }
299
340
  }
300
- stepInputData.options = {
301
- context: user || ({} as IAMUserManagerUserWithPermissionsData<User, unknown>),
302
- contextIdentifierField: defaultUserIdentifierField
303
- };
304
- // 2. Restore the cache, if configured
341
+ if (user) {
342
+ stepInputData.options = {
343
+ context: user,
344
+ contextIdentifierField: defaultUserIdentifierField
345
+ };
346
+ } else if (userFilters) {
347
+ stepInputData.options = {
348
+ context: userFilters,
349
+ contextIdentifierField: mainFilterField
350
+ };
351
+ }
352
+ // 2. Restore the cache, if configured.
305
353
  if (cacheSettings && 'use' in cacheSettings && cacheSettings.use) {
354
+ if (!dataUsersAuthCacheService) {
355
+ logger.info(`${logPrefix}[Part 2]: dataUsersAuthCacheService not configured.`);
356
+ throw new ApplicationError('Authentication failed.');
357
+ }
306
358
  const cacheInput: { data: unknown; options: unknown } = {
307
359
  data: stepInputData.data,
308
360
  options: stepInputData.options
309
361
  };
310
- const cacheResult = await this.dataUsersAuthCacheService.findOne({
362
+ const cacheResult = await dataUsersAuthCacheService.findOne({
311
363
  filters: {
312
364
  [cacheSettings.settings.cacheFieldName]: getNested(cacheInput, cacheSettings.settings.inputFieldName)
313
365
  .unifiedValue
@@ -336,11 +388,14 @@ export class IAMUserManagerService<
336
388
  stepInputData.options as IAMAuthenticationCompleteOptions<User>
337
389
  );
338
390
  // 4. Process the step result
339
- if (!stepResult.valid || (stepResult.mfaUsed && !stepResult.mfaValid)) {
340
- logger.info(`[Domain.${moduleName}.UserManager]: Bad step result:`, stepResult);
391
+ if (
392
+ (!stepResult.valid && !(stepResult as unknown as { nextStepsRequired: boolean }).nextStepsRequired) ||
393
+ (stepResult.mfaUsed && !stepResult.mfaValid)
394
+ ) {
395
+ logger.info(`${logPrefix}[Part 4]: Bad step result:`, stepResult);
341
396
  throw new ApplicationError('Authentication failed.');
342
397
  }
343
- // 5. If the step returns tokens and decoding is enabled, decode the reutrned tokens for payloads
398
+ // 5. If the step returns tokens and decoding is enabled, decode the reutrned tokens for payloads.
344
399
  if ('decodeReturnedTokens' in stepConfig && stepConfig.decodeReturnedTokens) {
345
400
  const tokensForDecoding: Record<string, string> = {};
346
401
  const tokenKeys = ['accessToken', 'idToken', 'refreshToken'];
@@ -354,7 +409,7 @@ export class IAMUserManagerService<
354
409
  const externalTokenPayloads = await authService.getPayloadsFromExternalTokens(tokensForDecoding);
355
410
  stepResult = { ...stepResult, ...externalTokenPayloads };
356
411
  }
357
- // 6. Find the user based on either the provided filters, or on the stepResult data, if enabled
412
+ // 6. Find the user based on either the provided filters, or on the stepResult data, if enabled.
358
413
  if (findUser && !findUserBeforeAuth) {
359
414
  if ('findUserInAuthResultBy' in stepConfig && stepConfig.findUserInAuthResultBy) {
360
415
  const { userFieldName, resultFieldName } = stepConfig.findUserInAuthResultBy;
@@ -371,6 +426,8 @@ export class IAMUserManagerService<
371
426
  mainFilterField: userFieldName
372
427
  });
373
428
  }
429
+ } else if ('findUserInExternalTokenPayloads' in stepConfig && stepConfig.findUserInExternalTokenPayloads) {
430
+ runFindUserInExternalTokenPayloads = true;
374
431
  } else if (hasFilters) {
375
432
  userFilterField = mainFilterField;
376
433
  userFilterValue = userFilters[userFilterField];
@@ -381,13 +438,18 @@ export class IAMUserManagerService<
381
438
  }
382
439
  }
383
440
  // 7. Create a user using the data from the tokens returned by the step execution, if enabled and there is no user found.
384
- if (!user && 'createUser' in stepConfig && stepConfig.createUser) {
441
+ const createUser = 'createUser' in stepConfig && stepConfig.createUser;
442
+ if (!user && (createUser || runFindUserInExternalTokenPayloads)) {
385
443
  const userData = await authService.getUserDataFromExternalTokenPayloads(
386
444
  stepResult as IAMAuthenticationGetUserDataFromExternalTokenPayloadsData
387
445
  );
388
- if (userData) {
446
+ if (createUser && userData) {
447
+ if (!domainUsersEntityService) {
448
+ logger.info(`${logPrefix}[Part 7]: domainUsersEntityService not configured.`);
449
+ throw new ApplicationError('Authentication failed.');
450
+ }
389
451
  const { result: createdUser } = await domainUsersEntityService.create(userData as unknown as Data['Create']);
390
- user = await this.getUserWithPermissionsData(
452
+ user = await domainUsersEntityService.getUserWithPermissionsData(
391
453
  {
392
454
  filters: {
393
455
  [defaultUserIdentifierField]: createdUser[defaultUserIdentifierField as keyof typeof createdUser]
@@ -395,11 +457,13 @@ export class IAMUserManagerService<
395
457
  },
396
458
  { keepPassword: false }
397
459
  );
460
+ } else if (runFindUserInExternalTokenPayloads) {
461
+ user = userData as unknown as IAMUserWithPermissionsData<User, unknown>;
398
462
  }
399
463
  }
400
464
  if (validWithoutUser !== true && !user) {
401
465
  logger.info(
402
- `[Domain.${moduleName}.UserManager]: Login attempt failed ${userFilterField && userFilterValue ? `for ${userFilterField} ${userFilterValue} ` : ''}- user not found.`
466
+ `${logPrefix}[Part 7]: Login attempt failed ${userFilterField && userFilterValue ? `for ${userFilterField} ${userFilterValue} ` : ''}- user not found.`
403
467
  );
404
468
  throw new ApplicationError('Authentication failed.');
405
469
  }
@@ -407,7 +471,11 @@ export class IAMUserManagerService<
407
471
  delete user.password;
408
472
  }
409
473
  // 8. Populate the cache, if configured
410
- if (stepResult.mfaUsed && cacheSettings && 'populate' in cacheSettings && cacheSettings.populate) {
474
+ if (cacheSettings && 'populate' in cacheSettings && cacheSettings.populate) {
475
+ if (!dataUsersAuthCacheService) {
476
+ logger.info(`${logPrefix}[Part 7]: dataUsersAuthCacheService not configured.`);
477
+ throw new ApplicationError('Authentication failed.');
478
+ }
411
479
  const cacheInput: GenericObject = {
412
480
  data: stepInputData.data,
413
481
  options: stepInputData.options,
@@ -431,7 +499,7 @@ export class IAMUserManagerService<
431
499
  }
432
500
  cacheData[inputName] = cacheInput[inputName];
433
501
  }
434
- await this.dataUsersAuthCacheService.create({
502
+ await dataUsersAuthCacheService.create({
435
503
  ...cacheData,
436
504
  [cacheSettings.settings.cacheFieldName]: getNested(cacheInput, cacheSettings.settings.inputFieldName)
437
505
  .unifiedValue
@@ -443,14 +511,20 @@ export class IAMUserManagerService<
443
511
  protected async getUserForStepExecution(options: {
444
512
  filters: GenericObject;
445
513
  mainFilterField: string;
446
- }): Promise<IAMUserManagerUserWithPermissionsData<User, unknown> | null> {
447
- const { configProvider, moduleName } = this;
514
+ }): Promise<IAMUserWithPermissionsData<User, unknown> | null> {
515
+ const { configProvider, domainUsersEntityService, moduleName } = this;
516
+ if (!domainUsersEntityService) {
517
+ throw new ApplicationError(`[${moduleName}][AuthenticationManager] domainUsersEntityService not configured.`);
518
+ }
448
519
  const { defaultUserIdentifierField } = configProvider.config.domain[moduleName] as AppConfigDomainIAM;
449
520
  const { mainFilterField } = options;
450
521
  let filters: GenericObject = options.filters;
451
- let user: IAMUserManagerUserWithPermissionsData<User, unknown> | null = null;
522
+ let user: IAMUserWithPermissionsData<User, unknown> | null = null;
452
523
  if (mainFilterField !== defaultUserIdentifierField) {
453
- const mainFilterFieldResult = await this.domainUsersEntityService.findOne({ filters });
524
+ // Allow search by an extended range of filters, directly in the database.
525
+ // This is needed because getUserWithPermissionsData will usually query the cache, where a
526
+ // prmary key filter is mandatory.
527
+ const mainFilterFieldResult = await domainUsersEntityService.findOne({ filters });
454
528
  if (!mainFilterFieldResult.result) {
455
529
  return null;
456
530
  }
@@ -461,18 +535,7 @@ export class IAMUserManagerService<
461
535
  } else {
462
536
  filters = options.filters;
463
537
  }
464
- user = await this.getUserWithPermissionsData({ filters }, { keepPassword: true });
538
+ user = await domainUsersEntityService.getUserWithPermissionsData({ filters }, { keepPassword: true });
465
539
  return user;
466
540
  }
467
-
468
- async getUserWithPermissionsData(
469
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
470
- _options: DataFindOneOptions,
471
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
472
- _privateOptions?: IAMUserManagerGetUserWithPermissionsDataOptions
473
- ): Promise<IAMUserManagerUserWithPermissionsData<User, unknown> | null> {
474
- throw new ApplicationError(
475
- `Method ${this.moduleName}.IAMUserManagerService.getUserWithPermissionsData not implemented.`
476
- );
477
- }
478
541
  }
@@ -0,0 +1,2 @@
1
+ export * from './iam.authenticationManager.definitions';
2
+ export * from './iam.authenticationManager.service';
@@ -4,7 +4,7 @@ import {
4
4
  IAMAuthenticationCompleteResult,
5
5
  IAMAuthenticationGetPayloadsFromExternalTokensData,
6
6
  IAMAuthenticationGetPayloadsFromExternalTokensResult,
7
- IAMAuthenticationGetUserCreateAccessTokenConfigResult,
7
+ IAMAuthenticationGetUserAuthenticationConfigResult,
8
8
  IAMAuthenticationInitiateData,
9
9
  IAMAuthenticationInitiateOptions,
10
10
  IAMAuthenticationInitiateResult,
@@ -24,6 +24,7 @@ export interface IAMAuthenticationOAuth2AccessTokenProviderResponseData {
24
24
  export interface IAMAuthenticationOAuth2CompleteData extends IAMAuthenticationCompleteData {
25
25
  code: string;
26
26
  codeVerifier: string;
27
+ redirectUri?: string;
27
28
  state: string;
28
29
  }
29
30
 
@@ -40,10 +41,11 @@ export type IAMAuthenticationOAuth2GetPayloadsFromExternalTokensData =
40
41
  export type IAMAuthenticationOAuth2GetPayloadsFromExternalTokensResult =
41
42
  IAMAuthenticationGetPayloadsFromExternalTokensResult;
42
43
 
43
- export type IAMAuthenticationOAuth2GetUserCreateAccessTokenConfigResult =
44
- IAMAuthenticationGetUserCreateAccessTokenConfigResult;
44
+ export type IAMAuthenticationOAuth2GetUserAuthenticationConfigResult =
45
+ IAMAuthenticationGetUserAuthenticationConfigResult;
45
46
 
46
47
  export interface IAMAuthenticationOAuth2InitiateData extends IAMAuthenticationInitiateData {
48
+ redirectUri?: string;
47
49
  scope?: string;
48
50
  }
49
51
 
@@ -60,6 +62,7 @@ export interface IAMAuthenticationOAuth2InitiateResult extends IAMAuthentication
60
62
  codeVerifier?: string;
61
63
  nonce?: string;
62
64
  state: string;
65
+ redirectUri: string;
63
66
  }
64
67
 
65
68
  export type IAMAuthenticationOAuth2VerifyExternalAccessTokenData = Pick<