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

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 +7 -1
  2. package/dist/common/definitions/common.constants.js +6 -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 +13 -5
  9. package/dist/services/authentication/iam.authentication.service.js +32 -3
  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 +25 -0
  15. package/dist/services/authenticationOAuth2/iam.authenticationOAuth2.service.js +300 -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 +15 -0
  24. package/dist/services/authenticationUserLocal/iam.authenticationUserLocal.service.js +142 -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 +29 -13
  33. package/dist/services/authorization/iam.authorization.service.js +233 -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 +10 -0
  42. package/dist/services/mfa/iam.mfa.service.js +32 -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 +24 -9
  50. package/dist/services/tokenManager/iam.tokenManager.service.js +113 -44
  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 +33 -0
  56. package/dist/services/userManager/iam.userManager.service.js +332 -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 +10 -8
  62. package/src/common/definitions/common.constants.ts +16 -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 +105 -0
  70. package/src/services/authentication/index.ts +2 -0
  71. package/src/services/authenticationOAuth2/iam.authenticationOAuth2.definitions.ts +72 -0
  72. package/src/services/authenticationOAuth2/iam.authenticationOAuth2.service.ts +352 -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 +173 -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 +387 -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 +40 -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 +292 -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 +463 -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,40 @@
1
+ import { ApplicationError, ConfigProviderService, LoggerService } from '@node-c/core';
2
+
3
+ import {
4
+ IAMMFACompleteData,
5
+ IAMMFACompleteOptions,
6
+ IAMMFACompleteResult,
7
+ IAMMFAInitiateData,
8
+ IAMMFAInitiateOptions,
9
+ IAMMFAInitiateResult
10
+ } from './iam.mfa.definitions';
11
+
12
+ // TODO: local MFA implementation
13
+ export class IAMMFAService<CompleteContext extends object, InitiateContext extends object = object> {
14
+ constructor(
15
+ // eslint-disable-next-line no-unused-vars
16
+ protected configProvider: ConfigProviderService,
17
+ // eslint-disable-next-line no-unused-vars
18
+ protected logger: LoggerService,
19
+ // eslint-disable-next-line no-unused-vars
20
+ protected moduleName: string
21
+ ) {}
22
+
23
+ async complete(
24
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
25
+ _data: IAMMFACompleteData,
26
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
27
+ _options: IAMMFACompleteOptions<CompleteContext>
28
+ ): Promise<IAMMFACompleteResult> {
29
+ throw new ApplicationError(`[${this.moduleName}][IAMMFAService]: Method "complete" not implemented.`);
30
+ }
31
+
32
+ async initiate(
33
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
34
+ _data: IAMMFAInitiateData,
35
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
36
+ _options: IAMMFAInitiateOptions<InitiateContext>
37
+ ): Promise<IAMMFAInitiateResult> {
38
+ throw new ApplicationError(`[${this.moduleName}][IAMMFAService]: Method "initiate" not implemented.`);
39
+ }
40
+ }
@@ -0,0 +1,2 @@
1
+ export * from './iam.mfa.definitions';
2
+ export * from './iam.mfa.service';
@@ -0,0 +1,61 @@
1
+ import { DomainCreateOptions } from '@node-c/core';
2
+
3
+ import { IAMAuthenticationType, IAMAuthenticationVerifyExternalAccessTokenResult } from '../authentication';
4
+
5
+ export interface BaseTokenEntityFields {
6
+ externalToken?: string;
7
+ externalTokenAuthService?: IAMAuthenticationType;
8
+ }
9
+
10
+ export type DecodedTokenContent<TokenEntityFields> = {
11
+ exp?: number;
12
+ iat: number;
13
+ data?: TokenEntityFields & BaseTokenEntityFields;
14
+ };
15
+
16
+ export type TokenEntity<TokenEntityFields extends object> = {
17
+ token: string;
18
+ type: TokenType;
19
+ } & TokenEntityFields &
20
+ BaseTokenEntityFields;
21
+
22
+ export type TokenManagerCreateData<TokenEntityFields extends object> = Partial<
23
+ Omit<TokenEntity<TokenEntityFields>, 'token'>
24
+ >;
25
+
26
+ export type TokenManagerCreateOptions = {
27
+ expiresInMinutes?: number;
28
+ identifierDataField?: string;
29
+ persist?: boolean;
30
+ purgeOldFromData?: boolean;
31
+ tokenContentOnlyFields?: string[];
32
+ ttl?: number;
33
+ } & DomainCreateOptions;
34
+
35
+ export enum TokenType {
36
+ // eslint-disable-next-line no-unused-vars
37
+ Access = 'access',
38
+ // eslint-disable-next-line no-unused-vars
39
+ Refresh = 'refresh'
40
+ }
41
+
42
+ export interface TokenManagerVerifyResult<TokenEntityFields> {
43
+ content?: DecodedTokenContent<TokenEntityFields>;
44
+ externalTokenData?: IAMAuthenticationVerifyExternalAccessTokenResult;
45
+ error?: unknown;
46
+ }
47
+
48
+ export interface VerifyAccessTokenOptions {
49
+ deleteFromStoreIfExpired?: boolean;
50
+ identifierDataField?: string;
51
+ newTokenExpiresInMinutes?: number;
52
+ persistNewToken?: boolean;
53
+ purgeStoreOnRenew?: boolean;
54
+ refreshToken?: string;
55
+ refreshTokenAccessTokenIdentifierDataField?: string;
56
+ }
57
+
58
+ export interface VerifyAccessTokenReturnData<TokenEntityFields> {
59
+ content?: DecodedTokenContent<TokenEntityFields>;
60
+ newToken?: string;
61
+ }
@@ -0,0 +1,292 @@
1
+ import {
2
+ AppConfigDomainIAM,
3
+ ApplicationError,
4
+ ConfigProviderService,
5
+ DataEntityService,
6
+ DomainCreateOptions,
7
+ DomainCreateResult,
8
+ DomainEntityService,
9
+ GenericObject,
10
+ LoggerService,
11
+ setNested
12
+ } from '@node-c/core';
13
+
14
+ import * as jwt from 'jsonwebtoken';
15
+ import ld from 'lodash';
16
+
17
+ import {
18
+ DecodedTokenContent,
19
+ TokenEntity,
20
+ TokenManagerCreateData,
21
+ TokenManagerCreateOptions,
22
+ TokenManagerVerifyResult,
23
+ TokenType,
24
+ VerifyAccessTokenOptions,
25
+ VerifyAccessTokenReturnData
26
+ } from './iam.tokenManager.definitions';
27
+
28
+ import { Constants } from '../../common/definitions';
29
+ import { IAMAuthenticationService, IAMAuthenticationType } from '../authentication';
30
+ import { IAMAuthenticationOAuth2Service } from '../authenticationOAuth2';
31
+ import { IAMAuthenticationUserLocalService } from '../authenticationUserLocal';
32
+
33
+ /*
34
+ * Service for managing local access and refresh JWTs.
35
+ */
36
+ export class IAMTokenManagerService<TokenEntityFields extends object> {
37
+ constructor(
38
+ // eslint-disable-next-line no-unused-vars
39
+ // protected authServices: Record<string, IAMAuthenticationService<object, object>>,
40
+ // eslint-disable-next-line no-unused-vars
41
+ protected authServices: {
42
+ [IAMAuthenticationType.OAuth2]?: IAMAuthenticationOAuth2Service<object, object>;
43
+ [IAMAuthenticationType.UserLocal]?: IAMAuthenticationUserLocalService<object, object>;
44
+ } & { [serviceName: string]: IAMAuthenticationService<object, object> },
45
+ // eslint-disable-next-line no-unused-vars
46
+ protected configProvider: ConfigProviderService,
47
+ // eslint-disable-next-line no-unused-vars
48
+ protected domainTokensEntityService: DomainEntityService<
49
+ TokenEntity<TokenEntityFields>,
50
+ DataEntityService<TokenEntity<TokenEntityFields>>
51
+ >,
52
+ // eslint-disable-next-line no-unused-vars
53
+ protected logger: LoggerService,
54
+ // eslint-disable-next-line no-unused-vars
55
+ protected moduleName: string
56
+ ) {}
57
+
58
+ async create(
59
+ data: TokenManagerCreateData<TokenEntityFields>,
60
+ options: TokenManagerCreateOptions
61
+ ): Promise<DomainCreateResult<TokenEntity<TokenEntityFields>>> {
62
+ const { configProvider, logger, moduleName, domainTokensEntityService } = this;
63
+ const moduleConfig = configProvider.config.domain[moduleName] as AppConfigDomainIAM;
64
+ const { type, ...tokenData } = data;
65
+ const { expiresInMinutes, identifierDataField, persist, purgeOldFromData, tokenContentOnlyFields } = options;
66
+ const signOptions = {} as jwt.SignOptions;
67
+ let secret: string;
68
+ // Leaving this big and ugly if-statement as is, in case we need to expand it in the future.
69
+ if (type === TokenType.Access) {
70
+ secret = moduleConfig.jwtAccessSecret;
71
+ if (expiresInMinutes) {
72
+ signOptions.expiresIn = expiresInMinutes * 60;
73
+ } else if (moduleConfig.accessTokenExpiryTimeInMinutes) {
74
+ signOptions.expiresIn = moduleConfig.accessTokenExpiryTimeInMinutes * 60;
75
+ }
76
+ } else if (type === TokenType.Refresh) {
77
+ secret = moduleConfig.jwtRefreshSecret;
78
+ if (expiresInMinutes) {
79
+ signOptions.expiresIn = expiresInMinutes * 60;
80
+ } else if (moduleConfig.refreshTokenExpiryTimeInMinutes) {
81
+ signOptions.expiresIn = moduleConfig.refreshTokenExpiryTimeInMinutes * 60;
82
+ }
83
+ } else {
84
+ throw new ApplicationError(`[TokenManager.create]: Invalid token type - "${type}".`);
85
+ }
86
+ const token = await new Promise<string>((resolve, reject) => {
87
+ jwt.sign({ data }, secret, signOptions, (err, token) => {
88
+ if (err) {
89
+ logger.error(err);
90
+ reject(new ApplicationError('Failed to sign token.'));
91
+ return;
92
+ }
93
+ resolve(token as string);
94
+ });
95
+ });
96
+ const objectToSave = { ...tokenData, token, type } as TokenEntity<TokenEntityFields>;
97
+ if (tokenContentOnlyFields?.length) {
98
+ tokenContentOnlyFields.forEach(fieldName =>
99
+ setNested(objectToSave, fieldName, undefined, { removeNestedFieldEscapeSign: true })
100
+ );
101
+ }
102
+ // save the token in the data system of choice
103
+ // TODO: multi-data isn't handled well here (or, actually, at all)
104
+ if (persist) {
105
+ if (purgeOldFromData && identifierDataField) {
106
+ const identifierValue = ld.get(data, identifierDataField);
107
+ if (typeof identifierValue !== 'undefined' && typeof identifierValue !== 'object') {
108
+ await domainTokensEntityService.delete(
109
+ {
110
+ filters: { [identifierDataField]: identifierValue, type }
111
+ },
112
+ { requirePrimaryKeys: true }
113
+ );
114
+ }
115
+ }
116
+ await domainTokensEntityService.create(objectToSave, { ttl: signOptions.expiresIn } as DomainCreateOptions);
117
+ }
118
+ return { result: objectToSave };
119
+ }
120
+
121
+ // TODO: delete from store at the end
122
+ async verifyAccessToken(
123
+ token: string,
124
+ options?: VerifyAccessTokenOptions
125
+ ): Promise<VerifyAccessTokenReturnData<TokenEntityFields>> {
126
+ const { configProvider, domainTokensEntityService, logger, moduleName } = this;
127
+ const moduleConfig = configProvider.config.domain[moduleName] as AppConfigDomainIAM;
128
+ const {
129
+ deleteFromStoreIfExpired,
130
+ identifierDataField,
131
+ newTokenExpiresInMinutes,
132
+ persistNewToken,
133
+ purgeStoreOnRenew,
134
+ refreshToken,
135
+ refreshTokenAccessTokenIdentifierDataField
136
+ } = options || {};
137
+ // decode the token
138
+ const { content, error, externalTokenData } = await this.verify(token, moduleConfig.jwtAccessSecret, {
139
+ // TODO: make this configurable
140
+ verifyExternal: true
141
+ });
142
+ const externalAccessTokenExpired = !!externalTokenData?.error;
143
+ const internalAccessTokenExpired = error === Constants.TOKEN_EXPIRED_ERROR;
144
+ let errorMessageToLog: string | undefined;
145
+ let externalRenewEnabled = false;
146
+ let newToken: string | undefined;
147
+ let refreshTokenContent: DecodedTokenContent<object> | undefined;
148
+ let renewEnabled = false;
149
+ let throwError = true;
150
+ // check whether the local and/or external access tokens have expired
151
+ if (internalAccessTokenExpired || externalAccessTokenExpired) {
152
+ // prepare renewal if the necessary data is present
153
+ if (identifierDataField && content?.data) {
154
+ if (refreshToken && refreshTokenAccessTokenIdentifierDataField) {
155
+ // internal refresh token verification
156
+ const { content: rtc, error: refreshTokenError } = await this.verify(
157
+ refreshToken,
158
+ moduleConfig.jwtRefreshSecret
159
+ );
160
+ refreshTokenContent = rtc;
161
+ if (!refreshTokenContent) {
162
+ errorMessageToLog = '[IAMTokenManagerService.verifyAccessToken]: Empty internal refresh token.';
163
+ } else if (refreshTokenError) {
164
+ errorMessageToLog = refreshTokenError as string;
165
+ // delete the refresh token from the store
166
+ if (deleteFromStoreIfExpired && refreshTokenContent.data) {
167
+ const identifierValue = ld.get(refreshTokenContent.data, refreshTokenAccessTokenIdentifierDataField);
168
+ if (typeof identifierValue !== 'undefined' && typeof identifierValue !== 'object') {
169
+ await domainTokensEntityService.delete(
170
+ {
171
+ filters: { [refreshTokenAccessTokenIdentifierDataField]: identifierValue, token: refreshToken }
172
+ },
173
+ { requirePrimaryKeys: true }
174
+ );
175
+ }
176
+ }
177
+ } else {
178
+ const refreshTokenCheckValue = ld.get(content.data, refreshTokenAccessTokenIdentifierDataField);
179
+ if (refreshTokenCheckValue !== refreshToken) {
180
+ errorMessageToLog = '[IAMTokenManagerService.verifyAccessToken]: Mismatched internal refresh token.';
181
+ } else {
182
+ renewEnabled = true;
183
+ throwError = false;
184
+ }
185
+ }
186
+ // external token renewal preparation
187
+ if (externalAccessTokenExpired) {
188
+ if (refreshTokenContent?.data?.externalToken) {
189
+ externalRenewEnabled = true;
190
+ renewEnabled = true;
191
+ throwError = false;
192
+ } else {
193
+ errorMessageToLog = '[IAMTokenManagerService.verifyAccessToken]: Missing external refresh token.';
194
+ }
195
+ }
196
+ }
197
+ // no renewal - delete from store if enabled and prepare to throw an error
198
+ else {
199
+ errorMessageToLog =
200
+ '[IAMTokenManagerService.verifyAccessToken]: Access token expired & no refresh token data present or configured.';
201
+ if (deleteFromStoreIfExpired) {
202
+ const identifierValue = ld.get(content.data, identifierDataField);
203
+ if (typeof identifierValue !== 'undefined' && typeof identifierValue !== 'object') {
204
+ await domainTokensEntityService.delete(
205
+ {
206
+ filters: { [identifierDataField]: identifierValue, token }
207
+ },
208
+ { requirePrimaryKeys: true }
209
+ );
210
+ }
211
+ }
212
+ }
213
+ }
214
+ // otherwise, simply throw an error
215
+ else {
216
+ errorMessageToLog = '[IAMTokenManagerService.verify]: Internal access token expired.';
217
+ }
218
+ } else {
219
+ throwError = false;
220
+ }
221
+ if (throwError) {
222
+ logger.error(errorMessageToLog);
223
+ throw new ApplicationError('Expired access token.');
224
+ }
225
+ // renewal
226
+ if (content?.data && renewEnabled) {
227
+ const tokenData: TokenManagerCreateData<GenericObject<unknown>> = { ...content.data, type: TokenType.Access };
228
+ if (refreshToken && refreshTokenAccessTokenIdentifierDataField) {
229
+ tokenData[refreshTokenAccessTokenIdentifierDataField] = refreshToken;
230
+ }
231
+ if (externalRenewEnabled) {
232
+ const externalAccessTokenRenewalResult = await this.authServices[
233
+ refreshTokenContent!.data!.externalTokenAuthService!
234
+ ]!.refreshExternalAccessToken({
235
+ accessToken: content.data!.externalToken!,
236
+ refreshToken: refreshTokenContent!.data!.externalToken!
237
+ });
238
+ if (externalAccessTokenRenewalResult.error) {
239
+ // TODO: delete from store
240
+ logger.error(errorMessageToLog);
241
+ throw new ApplicationError('Expired access token.');
242
+ }
243
+ // TODO: save the new refresh token, if such exists
244
+ tokenData.externalToken = externalAccessTokenRenewalResult.newAccessToken;
245
+ }
246
+ const { result } = await this.create(tokenData as TokenManagerCreateData<TokenEntityFields>, {
247
+ expiresInMinutes: newTokenExpiresInMinutes,
248
+ identifierDataField,
249
+ persist: persistNewToken,
250
+ purgeOldFromData: purgeStoreOnRenew
251
+ });
252
+ newToken = result.token;
253
+ }
254
+ return { content, newToken };
255
+ }
256
+
257
+ protected async verify(
258
+ token: string,
259
+ secret: string,
260
+ options?: { forceVerifyExternal?: boolean; verifyExternal?: boolean }
261
+ ): Promise<TokenManagerVerifyResult<TokenEntityFields>> {
262
+ const { configProvider, moduleName } = this;
263
+ const moduleConfig = configProvider.config.domain[moduleName] as AppConfigDomainIAM;
264
+ const { forceVerifyExternal, verifyExternal } = options || {};
265
+ const data = await new Promise<{ content?: DecodedTokenContent<TokenEntityFields>; error?: unknown }>(resolve => {
266
+ jwt.verify(token, secret, (err, decoded) => {
267
+ if (err) {
268
+ resolve({ content: decoded as DecodedTokenContent<TokenEntityFields>, error: err });
269
+ }
270
+ resolve({ content: decoded as DecodedTokenContent<TokenEntityFields> });
271
+ });
272
+ });
273
+ // TODO: move this logic to the verifyAccessToken method.
274
+ const returnData: TokenManagerVerifyResult<TokenEntityFields> = { ...data };
275
+ const tokenPayload = data.content?.data;
276
+ if (verifyExternal && tokenPayload?.externalToken && tokenPayload?.externalTokenAuthService) {
277
+ const authServiceConfig = moduleConfig.authServiceSettings?.[tokenPayload?.externalTokenAuthService];
278
+ if (authServiceConfig?.processExternalTokensOnVerify || forceVerifyExternal) {
279
+ const authService = this.authServices[tokenPayload?.externalTokenAuthService];
280
+ if (!authService) {
281
+ throw new ApplicationError(
282
+ `[IAMTokenManagerService.verify]: Auth service ${tokenPayload?.externalTokenAuthService} not configured.`
283
+ );
284
+ }
285
+ returnData.externalTokenData = await authService.verifyExternalAccessToken({
286
+ accessToken: tokenPayload?.externalToken
287
+ });
288
+ }
289
+ }
290
+ return returnData;
291
+ }
292
+ }
@@ -0,0 +1,2 @@
1
+ export * from './iam.tokenManager.definitions';
2
+ export * from './iam.tokenManager.service';
@@ -0,0 +1,73 @@
1
+ import {
2
+ AppConfigCommonDomainIAMAuthServiceConfigCompleteSettings,
3
+ AppConfigCommonDomainIAMAuthServiceConfigInitiateSettings,
4
+ AppConfigDomainIAMAuthenticationStep,
5
+ DomainFindOnePrivateOptions,
6
+ GenericObject
7
+ } from '@node-c/core';
8
+
9
+ import {
10
+ IAMAuthenticationCompleteResult,
11
+ IAMAuthenticationInitiateResult,
12
+ IAMAuthenticationService,
13
+ IAMAuthenticationType
14
+ } from '../authentication';
15
+ import { AuthorizationUser } from '../authorization';
16
+ import { IAMMFAType } from '../mfa';
17
+
18
+ export interface IAMUserManagerCreateAccessTokenOptions<AuthData = unknown> {
19
+ auth: {
20
+ mfaType?: IAMMFAType;
21
+ type: IAMAuthenticationType | string;
22
+ } & AuthData;
23
+ filters?: GenericObject;
24
+ mainFilterField: string;
25
+ rememberUser?: boolean;
26
+ step?: AppConfigDomainIAMAuthenticationStep;
27
+ }
28
+
29
+ export type IAMUserManagerCreateAccessTokenReturnData<UserData> =
30
+ | {
31
+ accessToken: string;
32
+ refreshToken?: string;
33
+ user: UserData;
34
+ }
35
+ | { nextStepsRequired: boolean };
36
+
37
+ export type IAMUserManagerExecuteStepData<AuthData = unknown> = Omit<
38
+ IAMUserManagerCreateAccessTokenOptions<AuthData>,
39
+ 'rememberUser' | 'step'
40
+ >;
41
+
42
+ export interface IAMUserManagerExecuteStepOptions<User extends object> {
43
+ authService: IAMAuthenticationService<User, User>;
44
+ name: AppConfigDomainIAMAuthenticationStep;
45
+ stepConfig:
46
+ | AppConfigCommonDomainIAMAuthServiceConfigCompleteSettings
47
+ | AppConfigCommonDomainIAMAuthServiceConfigInitiateSettings;
48
+ }
49
+
50
+ export interface IAMUserManagerExecuteStepResult<User extends object> {
51
+ stepResult: IAMAuthenticationCompleteResult | IAMAuthenticationInitiateResult;
52
+ user: IAMUserManagerUserWithPermissionsData<User, unknown> | null;
53
+ userFilterField?: string | undefined;
54
+ userFilterValue?: unknown | undefined;
55
+ }
56
+
57
+ export interface IAMUserManagerGetUserWithPermissionsDataOptions extends DomainFindOnePrivateOptions {
58
+ keepPassword?: boolean;
59
+ }
60
+
61
+ export type IAMUserManagerUserWithPermissionsData<UserData, AuthorizationPointId> =
62
+ AuthorizationUser<AuthorizationPointId> & UserData;
63
+
64
+ export interface IAMUserManagerUserTokenEnityFields<UserId = unknown> {
65
+ refreshToken?: string;
66
+ userId: UserId;
67
+ user?: IAMUserManagerUserWithPermissionsData<object, unknown>;
68
+ }
69
+
70
+ export enum IAMUserManagerUserTokenUserIdentifier {
71
+ // eslint-disable-next-line no-unused-vars
72
+ FieldName = 'userId'
73
+ }