@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.
- package/dist/common/definitions/common.constants.d.ts +13 -9
- package/dist/common/definitions/common.constants.js +13 -10
- package/dist/common/definitions/common.constants.js.map +1 -1
- package/dist/services/authentication/iam.authentication.definitions.d.ts +11 -2
- package/dist/services/authentication/iam.authentication.definitions.js +1 -1
- package/dist/services/authentication/iam.authentication.service.d.ts +9 -4
- package/dist/services/authentication/iam.authentication.service.js +95 -4
- package/dist/services/authentication/iam.authentication.service.js.map +1 -1
- package/dist/services/authenticationConsumer/iam.authenticationConsumer.definitions.d.ts +15 -0
- package/dist/services/authenticationConsumer/iam.authenticationConsumer.definitions.js +3 -0
- package/dist/services/authenticationConsumer/iam.authenticationConsumer.definitions.js.map +1 -0
- package/dist/services/authenticationConsumer/iam.authenticationConsumer.service.d.ts +12 -0
- package/dist/services/authenticationConsumer/iam.authenticationConsumer.service.js +135 -0
- package/dist/services/authenticationConsumer/iam.authenticationConsumer.service.js.map +1 -0
- package/dist/services/authenticationConsumer/index.d.ts +2 -0
- package/dist/services/authenticationConsumer/index.js +19 -0
- package/dist/services/authenticationConsumer/index.js.map +1 -0
- package/dist/services/{userManager/iam.userManager.definitions.d.ts → authenticationManager/iam.authenticationManager.definitions.d.ts} +11 -15
- package/dist/services/authenticationManager/iam.authenticationManager.definitions.js +8 -0
- package/dist/services/authenticationManager/iam.authenticationManager.definitions.js.map +1 -0
- package/dist/services/authenticationManager/iam.authenticationManager.service.d.ts +33 -0
- package/dist/services/{userManager/iam.userManager.service.js → authenticationManager/iam.authenticationManager.service.js} +140 -72
- package/dist/services/authenticationManager/iam.authenticationManager.service.js.map +1 -0
- package/dist/services/authenticationManager/index.d.ts +2 -0
- package/dist/services/authenticationManager/index.js +19 -0
- package/dist/services/authenticationManager/index.js.map +1 -0
- package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.definitions.d.ts +5 -2
- package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.service.d.ts +2 -14
- package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.service.js +53 -95
- package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.service.js.map +1 -1
- package/dist/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.definitions.d.ts +19 -0
- package/dist/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.definitions.js +3 -0
- package/dist/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.definitions.js.map +1 -0
- package/dist/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.service.d.ts +11 -0
- package/dist/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.service.js +69 -0
- package/dist/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.service.js.map +1 -0
- package/dist/services/authenticationOAuth2Consumer/index.d.ts +2 -0
- package/dist/services/authenticationOAuth2Consumer/index.js +19 -0
- package/dist/services/authenticationOAuth2Consumer/index.js.map +1 -0
- package/dist/services/authenticationPassthrough/iam.authenticationPassthrough.definitions.d.ts +14 -0
- package/dist/services/authenticationPassthrough/iam.authenticationPassthrough.definitions.js +3 -0
- package/dist/services/authenticationPassthrough/iam.authenticationPassthrough.definitions.js.map +1 -0
- package/dist/services/authenticationPassthrough/iam.authenticationPassthrough.service.d.ts +9 -0
- package/dist/services/authenticationPassthrough/iam.authenticationPassthrough.service.js +70 -0
- package/dist/services/authenticationPassthrough/iam.authenticationPassthrough.service.js.map +1 -0
- package/dist/services/authenticationPassthrough/index.d.ts +2 -0
- package/dist/services/authenticationPassthrough/index.js +19 -0
- package/dist/services/authenticationPassthrough/index.js.map +1 -0
- package/dist/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.definitions.d.ts +18 -0
- package/dist/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.definitions.js +3 -0
- package/dist/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.definitions.js.map +1 -0
- package/dist/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.service.d.ts +10 -0
- package/dist/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.service.js +68 -0
- package/dist/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.service.js.map +1 -0
- package/dist/services/authenticationPassthroughConsumer/index.d.ts +2 -0
- package/dist/services/authenticationPassthroughConsumer/index.js +19 -0
- package/dist/services/authenticationPassthroughConsumer/index.js.map +1 -0
- package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.definitions.d.ts +2 -2
- package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.service.d.ts +2 -6
- package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.service.js +4 -8
- package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.service.js.map +1 -1
- package/dist/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.definitions.d.ts +8 -0
- package/dist/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.definitions.js +3 -0
- package/dist/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.definitions.js.map +1 -0
- package/dist/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.service.d.ts +8 -0
- package/dist/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.service.js +36 -0
- package/dist/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.service.js.map +1 -0
- package/dist/services/authenticationUserLocalConsumer/index.d.ts +2 -0
- package/dist/services/authenticationUserLocalConsumer/index.js +19 -0
- package/dist/services/authenticationUserLocalConsumer/index.js.map +1 -0
- package/dist/services/authorization/iam.authorization.definitions.d.ts +24 -24
- package/dist/services/authorization/iam.authorization.definitions.js +7 -7
- package/dist/services/authorization/iam.authorization.definitions.js.map +1 -1
- package/dist/services/authorization/iam.authorization.service.d.ts +8 -11
- package/dist/services/authorization/iam.authorization.service.js +26 -30
- package/dist/services/authorization/iam.authorization.service.js.map +1 -1
- package/dist/services/index.d.ts +7 -1
- package/dist/services/index.js +7 -1
- package/dist/services/index.js.map +1 -1
- package/dist/services/tokenManager/iam.tokenManager.definitions.d.ts +4 -1
- package/dist/services/tokenManager/iam.tokenManager.definitions.js.map +1 -1
- package/dist/services/tokenManager/iam.tokenManager.service.d.ts +2 -2
- package/dist/services/tokenManager/iam.tokenManager.service.js +73 -35
- package/dist/services/tokenManager/iam.tokenManager.service.js.map +1 -1
- package/dist/services/users/index.d.ts +2 -0
- package/dist/services/{userManager → users}/index.js +2 -2
- package/dist/services/users/index.js.map +1 -0
- package/dist/services/users/users.definitions.d.ts +7 -0
- package/dist/services/users/users.definitions.js +3 -0
- package/dist/services/users/users.definitions.js.map +1 -0
- package/dist/services/users/users.service.d.ts +6 -0
- package/dist/services/users/users.service.js +39 -0
- package/dist/services/users/users.service.js.map +1 -0
- package/package.json +2 -2
- package/src/common/definitions/common.constants.ts +13 -16
- package/src/services/authentication/iam.authentication.definitions.ts +11 -4
- package/src/services/authentication/iam.authentication.service.ts +79 -15
- package/src/services/authenticationConsumer/iam.authenticationConsumer.definitions.ts +43 -0
- package/src/services/authenticationConsumer/iam.authenticationConsumer.service.ts +192 -0
- package/src/services/authenticationConsumer/index.ts +2 -0
- package/src/services/{userManager/iam.userManager.definitions.ts → authenticationManager/iam.authenticationManager.definitions.ts} +11 -19
- package/src/services/{userManager/iam.userManager.service.ts → authenticationManager/iam.authenticationManager.service.ts} +174 -111
- package/src/services/authenticationManager/index.ts +2 -0
- package/src/services/authenticationOAuth2/iam.authenticationOAuth2.definitions.ts +6 -3
- package/src/services/authenticationOAuth2/iam.authenticationOAuth2.service.ts +97 -85
- package/src/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.definitions.ts +56 -0
- package/src/services/authenticationOAuth2Consumer/iam.authenticationOAuth2Consumer.service.ts +93 -0
- package/src/services/authenticationOAuth2Consumer/index.ts +2 -0
- package/src/services/authenticationPassthrough/iam.authenticationPassthrough.definitions.ts +32 -0
- package/src/services/authenticationPassthrough/iam.authenticationPassthrough.service.ts +100 -0
- package/src/services/authenticationPassthrough/index.ts +2 -0
- package/src/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.definitions.ts +52 -0
- package/src/services/authenticationPassthroughConsumer/iam.authenticationPassthroughConsumer.service.ts +96 -0
- package/src/services/authenticationPassthroughConsumer/index.ts +2 -0
- package/src/services/authenticationUserLocal/iam.authenticationUserLocal.definitions.ts +3 -3
- package/src/services/authenticationUserLocal/iam.authenticationUserLocal.service.ts +17 -12
- package/src/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.definitions.ts +29 -0
- package/src/services/authenticationUserLocalConsumer/iam.authenticationUserLocalConsumer.service.ts +40 -0
- package/src/services/authenticationUserLocalConsumer/index.ts +2 -0
- package/src/services/authorization/iam.authorization.definitions.ts +26 -27
- package/src/services/authorization/iam.authorization.service.ts +40 -65
- package/src/services/index.ts +7 -1
- package/src/services/tokenManager/iam.tokenManager.definitions.ts +4 -1
- package/src/services/tokenManager/iam.tokenManager.service.ts +98 -45
- package/src/services/users/index.ts +2 -0
- package/src/services/users/users.definitions.ts +11 -0
- package/src/services/users/users.service.ts +46 -0
- package/dist/services/userManager/iam.userManager.definitions.js +0 -8
- package/dist/services/userManager/iam.userManager.definitions.js.map +0 -1
- package/dist/services/userManager/iam.userManager.service.d.ts +0 -33
- package/dist/services/userManager/iam.userManager.service.js.map +0 -1
- package/dist/services/userManager/index.d.ts +0 -2
- package/dist/services/userManager/index.js.map +0 -1
- 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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
82
|
-
options:
|
|
83
|
-
): Promise<
|
|
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}.
|
|
91
|
+
`[Domain.${moduleName}.AuthenticationManager][${authType}]: Login attempt started${options.step ? ` for step ${options.step}` : ''}.`
|
|
93
92
|
);
|
|
94
|
-
// 1. Make sure the
|
|
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}.
|
|
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.
|
|
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
|
|
130
|
-
stepConfig
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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}.
|
|
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}.
|
|
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
|
|
216
|
+
} = await tokenManager.create(
|
|
179
217
|
{
|
|
180
218
|
type: TokenType.Refresh,
|
|
181
|
-
[
|
|
182
|
-
...
|
|
183
|
-
? {
|
|
184
|
-
externalToken: externalRefreshToken,
|
|
185
|
-
externalTokenAuthService: authType as IAMAuthenticationType
|
|
186
|
-
}
|
|
187
|
-
: {})
|
|
219
|
+
[IAMAuthenticationManagerUserTokenUserIdentifier.FieldName]: userIdentifierValue,
|
|
220
|
+
...externalTokenData
|
|
188
221
|
},
|
|
189
222
|
{
|
|
190
|
-
expiresInMinutes:
|
|
191
|
-
|
|
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
|
|
245
|
+
} = await tokenManager.create(
|
|
210
246
|
{
|
|
211
247
|
refreshToken,
|
|
212
248
|
type: TokenType.Access,
|
|
213
|
-
[
|
|
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:
|
|
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
|
|
270
|
+
} = await tokenManager.create(
|
|
233
271
|
{
|
|
234
272
|
accessToken,
|
|
235
273
|
type: TokenType.Id,
|
|
236
274
|
user,
|
|
237
|
-
[
|
|
275
|
+
[IAMAuthenticationManagerUserTokenUserIdentifier.FieldName]: userIdentifierValue
|
|
238
276
|
},
|
|
239
277
|
{
|
|
240
278
|
expiresInMinutes: accessTokenExpiresIn,
|
|
241
|
-
identifierDataField:
|
|
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}.
|
|
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:
|
|
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:
|
|
267
|
-
options:
|
|
268
|
-
): Promise<
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
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
|
|
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 (
|
|
340
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 (
|
|
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
|
|
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<
|
|
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:
|
|
522
|
+
let user: IAMUserWithPermissionsData<User, unknown> | null = null;
|
|
452
523
|
if (mainFilterField !== defaultUserIdentifierField) {
|
|
453
|
-
|
|
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
|
|
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
|
}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
IAMAuthenticationCompleteResult,
|
|
5
5
|
IAMAuthenticationGetPayloadsFromExternalTokensData,
|
|
6
6
|
IAMAuthenticationGetPayloadsFromExternalTokensResult,
|
|
7
|
-
|
|
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
|
|
44
|
-
|
|
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<
|