@ibgib/node-gib 0.0.19 → 0.0.21

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 (58) hide show
  1. package/dist/email/verify/email-verify-helpers.d.mts +6 -1
  2. package/dist/email/verify/email-verify-helpers.d.mts.map +1 -1
  3. package/dist/email/verify/email-verify-helpers.mjs +6 -2
  4. package/dist/email/verify/email-verify-helpers.mjs.map +1 -1
  5. package/dist/identity/sso/sso-custodian-service.d.mts +8 -0
  6. package/dist/identity/sso/sso-custodian-service.d.mts.map +1 -1
  7. package/dist/identity/sso/sso-custodian-service.mjs +126 -77
  8. package/dist/identity/sso/sso-custodian-service.mjs.map +1 -1
  9. package/dist/serve-gib/handlers/api/email/email-verification-code.handler.d.mts.map +1 -1
  10. package/dist/serve-gib/handlers/api/email/email-verification-code.handler.mjs +50 -4
  11. package/dist/serve-gib/handlers/api/email/email-verification-code.handler.mjs.map +1 -1
  12. package/dist/serve-gib/handlers/api/identity/keystone-custodian-add-master-password.handler.d.mts +42 -0
  13. package/dist/serve-gib/handlers/api/identity/keystone-custodian-add-master-password.handler.d.mts.map +1 -0
  14. package/dist/serve-gib/handlers/api/identity/keystone-custodian-add-master-password.handler.mjs +201 -0
  15. package/dist/serve-gib/handlers/api/identity/keystone-custodian-add-master-password.handler.mjs.map +1 -0
  16. package/dist/serve-gib/handlers/api/identity/keystone-custodian-register-delegate.handler.d.mts.map +1 -1
  17. package/dist/serve-gib/handlers/api/identity/keystone-custodian-register-delegate.handler.mjs +5 -1
  18. package/dist/serve-gib/handlers/api/identity/keystone-custodian-register-delegate.handler.mjs.map +1 -1
  19. package/dist/serve-gib/handlers/api/keystone/keystone-evolve.handler.d.mts.map +1 -1
  20. package/dist/serve-gib/handlers/api/keystone/keystone-evolve.handler.mjs +6 -1
  21. package/dist/serve-gib/handlers/api/keystone/keystone-evolve.handler.mjs.map +1 -1
  22. package/dist/serve-gib/handlers/api/keystone/sso-config.handler.d.mts.map +1 -1
  23. package/dist/serve-gib/handlers/api/keystone/sso-config.handler.mjs +2 -11
  24. package/dist/serve-gib/handlers/api/keystone/sso-config.handler.mjs.map +1 -1
  25. package/dist/serve-gib/handlers/api/keystone/sso-link.handler.d.mts.map +1 -1
  26. package/dist/serve-gib/handlers/api/keystone/sso-link.handler.mjs +66 -26
  27. package/dist/serve-gib/handlers/api/keystone/sso-link.handler.mjs.map +1 -1
  28. package/dist/serve-gib/handlers/api/keystone/sso-login.handler.d.mts.map +1 -1
  29. package/dist/serve-gib/handlers/api/keystone/sso-login.handler.mjs +3 -10
  30. package/dist/serve-gib/handlers/api/keystone/sso-login.handler.mjs.map +1 -1
  31. package/dist/serve-gib/identity-index/identity-index-service.d.mts +5 -1
  32. package/dist/serve-gib/identity-index/identity-index-service.d.mts.map +1 -1
  33. package/dist/serve-gib/identity-index/identity-index-service.mjs +44 -20
  34. package/dist/serve-gib/identity-index/identity-index-service.mjs.map +1 -1
  35. package/dist/serve-gib/index.d.mts +1 -0
  36. package/dist/serve-gib/index.d.mts.map +1 -1
  37. package/dist/serve-gib/index.mjs +3 -0
  38. package/dist/serve-gib/index.mjs.map +1 -1
  39. package/dist/serve-gib/path-constants.d.mts +4 -0
  40. package/dist/serve-gib/path-constants.d.mts.map +1 -1
  41. package/dist/serve-gib/path-constants.mjs +4 -0
  42. package/dist/serve-gib/path-constants.mjs.map +1 -1
  43. package/e2e/identity-custodian-lifecycle.e2e.md +37 -0
  44. package/package.json +2 -2
  45. package/src/email/verify/email-verify-helpers.mts +13 -2
  46. package/src/identity/sso/sso-custodian-service.mts +129 -84
  47. package/src/serve-gib/handlers/api/email/email-verification-code.handler.mts +52 -5
  48. package/src/serve-gib/handlers/api/identity/keystone-custodian-add-master-password.handler.mts +252 -0
  49. package/src/serve-gib/handlers/api/identity/keystone-custodian-add-master-password.respec.mts +167 -0
  50. package/src/serve-gib/handlers/api/identity/keystone-custodian-register-delegate.handler.mts +6 -1
  51. package/src/serve-gib/handlers/api/identity/keystone-custodian-register-delegate.respec.mts +2 -2
  52. package/src/serve-gib/handlers/api/keystone/keystone-evolve.handler.mts +6 -1
  53. package/src/serve-gib/handlers/api/keystone/sso-config.handler.mts +2 -12
  54. package/src/serve-gib/handlers/api/keystone/sso-link.handler.mts +61 -26
  55. package/src/serve-gib/handlers/api/keystone/sso-login.handler.mts +3 -11
  56. package/src/serve-gib/identity-index/identity-index-service.mts +39 -19
  57. package/src/serve-gib/index.mts +3 -0
  58. package/src/serve-gib/path-constants.mts +5 -0
@@ -1,26 +1,20 @@
1
1
  import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
2
- import { loadSsoServerConfig } from '../../../../identity/sso/sso-config-helper.mjs';
3
- import { SsoCustodianService } from '../../../../identity/sso/sso-custodian-service.mjs';
2
+ import { getIbAndGib, getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
3
+ import { getGibInfo } from '@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs';
4
+ import { getSsoCustodianService } from '../../../../identity/sso/sso-custodian-service.mjs';
4
5
  import { SsoProviderId } from '../../../../identity/sso/sso-types.mjs';
5
6
  import { isSsoProviderLinked } from '@ibgib/web-gib/dist/identity/sso/sso-helpers.mjs';
6
7
  import { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
7
8
  import { getIdentityIndexService } from '../../../identity-index/identity-index-service.mjs';
9
+ import { loadSsoServerConfig } from '../../../../identity/sso/sso-config-helper.mjs';
10
+ import { generateCustodianRequirements } from '../../../../identity/sso/custodian-auth-helpers.mjs';
8
11
 
9
12
  import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
10
13
  import { ServeGibHandlerWithMetaspaceBase } from '../../handler-base.mjs';
11
14
  import { API_PATH_REGEXES } from '../../../path-constants.mjs';
12
15
  import { ParamsWithDomain, RequestContext, ResponseResult, ServeGibHttpMethod } from '../../../types.mjs';
13
16
 
14
- const logalot = GLOBAL_LOG_A_LOT;
15
-
16
- let custodian: SsoCustodianService | undefined;
17
- function getCustodian(): SsoCustodianService {
18
- if (!custodian) {
19
- const config = loadSsoServerConfig();
20
- custodian = new SsoCustodianService(config);
21
- }
22
- return custodian;
23
- }
17
+ const logalot = GLOBAL_LOG_A_LOT || true;
24
18
 
25
19
  interface LinkParams extends ParamsWithDomain {
26
20
  parentTjpAddr: string;
@@ -46,18 +40,33 @@ export class SsoLinkHandler extends ServeGibHandlerWithMetaspaceBase<LinkParams,
46
40
  protected override regex = API_PATH_REGEXES.IDENTITY_SSO_LINK;
47
41
 
48
42
  protected override async parseParamsImpl(reqCtx: RequestContext<LinkParams, any>): Promise<LinkParams | undefined> {
49
- let parsed: any;
43
+ const lc = `${this.lc}[${this.parseParamsImpl.name}]`;
50
44
  try {
51
- parsed = JSON.parse(reqCtx.body);
52
- } catch {
53
- return undefined;
45
+ if (logalot) { console.log(`${lc} starting... (I: a38f2cee647c127b48ec6ad1e8d1e826)`); }
46
+
47
+ let parsed: any;
48
+ try {
49
+ parsed = JSON.parse(reqCtx.body);
50
+ } catch {
51
+ return undefined;
52
+ }
53
+ let parentTjpAddr = parsed?.parentTjpAddr;
54
+ if (!parentTjpAddr) { return undefined; }
55
+ const { ib } = getIbAndGib({ ibGibAddr: parentTjpAddr });
56
+ const { tjpGib } = getGibInfo({ ibGibAddr: parentTjpAddr });
57
+ if (tjpGib && ib) {
58
+ parentTjpAddr = `${ib}^${tjpGib}`;
59
+ }
60
+ return {
61
+ parentTjpAddr,
62
+ domainInfo: this.getDomainInfo({ domainAddr: parentTjpAddr })
63
+ };
64
+ } catch (error) {
65
+ console.error(`${lc} ${extractErrorMsg(error)}`);
66
+ throw error;
67
+ } finally {
68
+ if (logalot) { console.log(`${lc} complete.`); }
54
69
  }
55
- const parentTjpAddr = parsed?.parentTjpAddr;
56
- if (!parentTjpAddr) { return undefined; }
57
- return {
58
- parentTjpAddr,
59
- domainInfo: this.getDomainInfo({ domainAddr: parentTjpAddr })
60
- };
61
70
  }
62
71
 
63
72
  protected override async validateQueryParams({ queryParams }: { queryParams: any }): Promise<string[]> {
@@ -83,11 +92,19 @@ export class SsoLinkHandler extends ServeGibHandlerWithMetaspaceBase<LinkParams,
83
92
  return this.error(400, 'Request body must be valid JSON (E: e1b2c3d4e5f67890a1b2c3d4e5f67890)');
84
93
  }
85
94
 
86
- const { code, providerId, parentTjpAddr, userNonce, redirectUri } = parsed;
95
+ let { code, providerId, parentTjpAddr, userNonce, redirectUri } = parsed;
87
96
  if (!code || !providerId || !parentTjpAddr || !userNonce || !redirectUri) {
88
97
  return this.error(400, 'Body missing required parameters (code, providerId, parentTjpAddr, userNonce, redirectUri) (E: f2c3d4e5f6789012a3b4c5d6e7f89012)');
89
98
  }
90
99
 
100
+ if (logalot) { console.log(`${lc} LinkBody parsed (I: 7525b8bd29c8504e989e918825d4e826)`); }
101
+
102
+ const { ib } = getIbAndGib({ ibGibAddr: parentTjpAddr });
103
+ const { tjpGib } = getGibInfo({ ibGibAddr: parentTjpAddr });
104
+ if (tjpGib && ib) {
105
+ parentTjpAddr = `${ib}^${tjpGib}`;
106
+ }
107
+
91
108
  const space = await reqCtx.metaspace.getLocalUserSpace({ lock: false });
92
109
  if (!space) {
93
110
  return this.error(500, 'No local user space found in domain metaspace (E: 03d4e5f678901234b5c6d7e8f9012345)');
@@ -104,12 +121,22 @@ export class SsoLinkHandler extends ServeGibHandlerWithMetaspaceBase<LinkParams,
104
121
  return this.error(400, `Keystone not found for address: ${parentTjpAddr} (E: 14e5f67890123456c7d8e9f012345678)`);
105
122
  }
106
123
 
107
- if (isSsoProviderLinked({ keystone: targetKeystone, providerId })) {
124
+ if (logalot) {
125
+ console.log(`${lc} targetKeystone gotten. addr: ${getIbGibAddr({ ibGib: targetKeystone })}, pools: ${JSON.stringify(targetKeystone.data?.challengePools?.map(p => p.id))}, frameDetails: ${JSON.stringify(targetKeystone.data?.frameDetails)} (I: 3d2068e16cb4da0428d601a7a74e3826)`);
126
+ }
127
+
128
+ const isLinked = isSsoProviderLinked({ keystone: targetKeystone, providerId });
129
+ if (logalot) {
130
+ console.log(`${lc} isSsoProviderLinked for ${providerId}: ${isLinked}`);
131
+ }
132
+
133
+ if (isLinked) {
108
134
  return this.error(400, `SSO provider "${providerId}" is already linked to this keystone. (E: 25f6789012345678d9e0f12345678901)`);
109
135
  }
110
136
 
111
137
  // 1. Authenticate with provider and retrieve user info
112
- const service = getCustodian();
138
+ const service = getSsoCustodianService();
139
+ if (logalot) { console.log(`${lc} getSsoCustodianService returned (I: f7e0b290ed2a2dcde807ff2853016226)`); }
113
140
  const userInfo = await service.getOAuthUserInfo(providerId, code, redirectUri);
114
141
 
115
142
  if (userInfo.email) {
@@ -136,9 +163,17 @@ export class SsoLinkHandler extends ServeGibHandlerWithMetaspaceBase<LinkParams,
136
163
 
137
164
  console.log(`${lc} created custodian pool for: ${userInfo.providerKey} (I: 4718901234567890f1a2b34567890123)`);
138
165
 
166
+ const ssoConfig = loadSsoServerConfig();
167
+ const serverSecret = ssoConfig.ssoServerKdfSecret;
168
+ const custodianReqs = await generateCustodianRequirements({
169
+ primaryTjpAddr: parentTjpAddr,
170
+ serverSecret
171
+ });
172
+
139
173
  return this.ok({
140
174
  success: true,
141
- custodianPool
175
+ custodianPool,
176
+ custodianReqs
142
177
  }, 200);
143
178
 
144
179
  } catch (error) {
@@ -19,22 +19,13 @@ import { API_PATH_REGEXES } from '../../../path-constants.mjs';
19
19
  import { RequestContext, ResponseResult, ServeGibHttpMethod } from '../../../types.mjs';
20
20
  import { bootstrapDomainMetaspace } from '../../../bootstrap-helper.mjs';
21
21
  import { loadSsoServerConfig } from '../../../../identity/sso/sso-config-helper.mjs';
22
- import { SsoCustodianService } from '../../../../identity/sso/sso-custodian-service.mjs';
22
+ import { getSsoCustodianService } from '../../../../identity/sso/sso-custodian-service.mjs';
23
23
  import { SsoProviderId } from '../../../../identity/sso/sso-types.mjs';
24
24
  import { getIdentityIndexService } from '../../../identity-index/identity-index-service.mjs';
25
25
  import { generateCustodianRequirements } from '../../../../identity/sso/custodian-auth-helpers.mjs';
26
26
 
27
27
  const logalot = GLOBAL_LOG_A_LOT;
28
28
 
29
- let custodian: SsoCustodianService | undefined;
30
- function getCustodian(): SsoCustodianService {
31
- if (!custodian) {
32
- const config = loadSsoServerConfig();
33
- custodian = new SsoCustodianService(config);
34
- }
35
- return custodian;
36
- }
37
-
38
29
  export interface SsoLoginBody {
39
30
  code: string;
40
31
  providerId: SsoProviderId;
@@ -95,7 +86,7 @@ export class SsoLoginHandler extends ServeGibHandlerBase<undefined, undefined> {
95
86
  }
96
87
 
97
88
  // 1. Authenticate code with provider and retrieve normalized user info
98
- const service = getCustodian();
89
+ const service = getSsoCustodianService();
99
90
  const userInfo = await service.getOAuthUserInfo(providerId, code, redirectUri);
100
91
 
101
92
  if (!userInfo || !userInfo.email) {
@@ -149,6 +140,7 @@ export class SsoLoginHandler extends ServeGibHandlerBase<undefined, undefined> {
149
140
  client: 'space-gib-server',
150
141
  role: 'custodian-primary',
151
142
  custodianProvider: providerId,
143
+ custodyMode: 'full',
152
144
  [`rawSSOName-${providerId}`]: rawSSOName,
153
145
  });
154
146
 
@@ -83,29 +83,39 @@ export class IdentityIndexService {
83
83
  tjpAddr?: IbGibAddr;
84
84
  primaryTjpAddr?: IbGibAddr;
85
85
  }): Promise<RegisterEmailIndexResult> {
86
- const targetAddr = tjpAddr || primaryTjpAddr;
87
- if (!targetAddr) { throw new Error('Either tjpAddr or primaryTjpAddr must be provided. (E: 62f15851b9a8c8d718279ab84e426826)'); }
88
- const emailHash = await getIdentityEmailHash({ email, salt: this.salt });
89
- const { folderPath, filePath } = getShardedIndexPath({
90
- baseDir: this.baseDir,
91
- emailHash
92
- });
86
+ const lc = `${this.lc}[${this.registerEmailIndex.name}]`;
87
+ try {
88
+ if (logalot) { console.log(`${lc} starting... (I: 5d1728a955657616a8cf6ce8b5afa226)`); }
93
89
 
94
- await fs.mkdir(folderPath, { recursive: true });
90
+ const targetAddr = tjpAddr || primaryTjpAddr;
91
+ if (!targetAddr) { throw new Error('Either tjpAddr or primaryTjpAddr must be provided. (E: 62f15851b9a8c8d718279ab84e426826)'); }
92
+ const emailHash = await getIdentityEmailHash({ email, salt: this.salt });
93
+ const { folderPath, filePath } = getShardedIndexPath({
94
+ baseDir: this.baseDir,
95
+ emailHash
96
+ });
95
97
 
96
- const record: IdentityIndexRecord = {
97
- tjpAddr: targetAddr,
98
- createdAt: Date.now(),
99
- };
98
+ await fs.mkdir(folderPath, { recursive: true });
100
99
 
101
- try {
102
- await fs.writeFile(filePath, JSON.stringify(record, null, 2), { flag: 'wx' });
103
- return { emailHash, filePath, record };
104
- } catch (error: any) {
105
- if (error.code === 'EEXIST') {
106
- throw new Error(`Email is already registered (E: duplicate_identity_409)`);
100
+ const record: IdentityIndexRecord = {
101
+ tjpAddr: targetAddr,
102
+ createdAt: Date.now(),
103
+ };
104
+
105
+ try {
106
+ await fs.writeFile(filePath, JSON.stringify(record, null, 2), { flag: 'wx' });
107
+ return { emailHash, filePath, record };
108
+ } catch (error: any) {
109
+ if (error.code === 'EEXIST') {
110
+ throw new Error(`Email is already registered (E: duplicate_identity_409)`);
111
+ }
112
+ throw error;
107
113
  }
114
+ } catch (error) {
115
+ console.error(`${lc} ${extractErrorMsg(error)}`);
108
116
  throw error;
117
+ } finally {
118
+ if (logalot) { console.log(`${lc} complete.`); }
109
119
  }
110
120
  }
111
121
 
@@ -218,9 +228,19 @@ let _identityIndexService: IdentityIndexService | undefined;
218
228
  /**
219
229
  * Singleton factory getter for the IdentityIndexService.
220
230
  */
221
- export function getIdentityIndexService(): IdentityIndexService {
231
+ export function getIdentityIndexService(opts?: IdentityIndexServiceOptions): IdentityIndexService {
232
+ if (opts) {
233
+ return new IdentityIndexService(opts);
234
+ }
222
235
  if (!_identityIndexService) {
223
236
  _identityIndexService = new IdentityIndexService();
224
237
  }
225
238
  return _identityIndexService;
226
239
  }
240
+
241
+ /**
242
+ * Resets the cached singleton instance (useful during testing across different data directories).
243
+ */
244
+ export function resetIdentityIndexService(): void {
245
+ _identityIndexService = undefined;
246
+ }
@@ -36,6 +36,7 @@ export * from './handlers/api/keystone/sso-link.handler.mjs';
36
36
  export * from './handlers/api/keystone/sso-login.handler.mjs';
37
37
  export * from './handlers/api/identity/keystone-custodian-genesis.handler.mjs';
38
38
  export * from './handlers/api/identity/keystone-custodian-register-delegate.handler.mjs';
39
+ export * from './handlers/api/identity/keystone-custodian-add-master-password.handler.mjs';
39
40
  export * from './handlers/api/email/email-inbound.handler.mjs';
40
41
  export * from './handlers/api/email/email-outbound.handler.mjs';
41
42
  export * from './handlers/api/email/email-verification-code.handler.mjs';
@@ -60,6 +61,7 @@ import { SsoLoginHandler } from './handlers/api/keystone/sso-login.handler.mjs';
60
61
  import { SsoConfigHandler } from './handlers/api/keystone/sso-config.handler.mjs';
61
62
  import { KeystoneCustodianGenesisHandler } from './handlers/api/identity/keystone-custodian-genesis.handler.mjs';
62
63
  import { KeystoneCustodianRegisterDelegateHandler } from './handlers/api/identity/keystone-custodian-register-delegate.handler.mjs';
64
+ import { KeystoneCustodianAddMasterPasswordHandler } from './handlers/api/identity/keystone-custodian-add-master-password.handler.mjs';
63
65
  import { EmailInboundHandler } from './handlers/api/email/email-inbound.handler.mjs';
64
66
  import { EmailOutboundHandler } from './handlers/api/email/email-outbound.handler.mjs';
65
67
  import { EmailVerificationCodeHandler } from './handlers/api/email/email-verification-code.handler.mjs';
@@ -89,6 +91,7 @@ export function getStandardServeGibHandlers(opts: StandardHandlersOptions = {}):
89
91
  new SsoConfigHandler(),
90
92
  new KeystoneCustodianGenesisHandler(),
91
93
  new KeystoneCustodianRegisterDelegateHandler(),
94
+ new KeystoneCustodianAddMasterPasswordHandler(),
92
95
  new EmailInboundHandler(),
93
96
  new EmailOutboundHandler(),
94
97
  new EmailVerificationCodeHandler(),
@@ -134,6 +134,11 @@ export const API_PATH_REGEXES = {
134
134
  * /api/identity/custodian/register-delegate
135
135
  */
136
136
  KEYSTONE_CUSTODIAN_REGISTER_DELEGATE: /^\/api\/identity\/custodian\/register-delegate\/?$/i,
137
+
138
+ /**
139
+ * /api/identity/custodian/add-master-password
140
+ */
141
+ KEYSTONE_CUSTODIAN_ADD_MASTER_PASSWORD: /^\/api\/identity\/custodian\/add-master-password\/?$/i,
137
142
  };
138
143
 
139
144
  export const VALID_STATIC_PATH_REGEX = /^\/[a-zA-Z0-9\-_\.\/]*$/;