@abtnode/auth 1.8.67-beta-794a8082 → 1.8.68-beta-500af7e5

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 (3) hide show
  1. package/lib/auth.js +4 -0
  2. package/lib/server.js +120 -10
  3. package/package.json +14 -14
package/lib/auth.js CHANGED
@@ -164,6 +164,10 @@ const messages = {
164
164
  en: 'Missing blocklet url',
165
165
  zh: '缺少应用下载地址',
166
166
  },
167
+ missingBlockletDid: {
168
+ en: 'Missing blocklet did',
169
+ zh: '缺少应用 ID',
170
+ },
167
171
  missingChainHost: {
168
172
  en: 'Missing chain host',
169
173
  zh: '缺少链的端点地址',
package/lib/server.js CHANGED
@@ -9,6 +9,8 @@ const { fromBase58, toAddress, toHex } = require('@ocap/util');
9
9
  const { toTypeInfo, isFromPublicKey } = require('@arcblock/did');
10
10
  const urlFriendly = require('@blocklet/meta/lib/url-friendly').default;
11
11
  const { slugify } = require('transliteration');
12
+ const { getChainInfo } = require('@blocklet/meta/lib/util');
13
+ const getBlockletInfo = require('@blocklet/meta/lib/info');
12
14
  const formatContext = require('@abtnode/util/lib/format-context');
13
15
  const {
14
16
  ROLES,
@@ -17,6 +19,7 @@ const {
17
19
  NFT_TYPE_SERVER_OWNERSHIP,
18
20
  SERVER_ROLES,
19
21
  NFT_TYPE_SERVERLESS,
22
+ MAIN_CHAIN_ENDPOINT,
20
23
  } = require('@abtnode/constant');
21
24
  const { toExternalBlocklet } = require('@blocklet/meta/lib/did');
22
25
  const {
@@ -222,12 +225,13 @@ const authenticateByNFT = async ({ node, claims, userDid, challenge, locale, isA
222
225
  return { role: ROLES.OWNER, teamDid: info.did, nft: state, user, passport: null, ownerDid, ownerNFT: address };
223
226
  };
224
227
 
225
- const authenticateBySession = async ({ node, userDid }) => {
228
+ const authenticateBySession = async ({ node, userDid, locale, allowedRoles = ['owner', 'admin', 'member'] }) => {
226
229
  const info = await node.getNodeInfo();
227
230
  const user = await getUser(node, info.did, userDid);
228
- const passport = (user.passports || []).find(
229
- (x) => x.status === 'valid' && ['owner', 'admin', 'member'].includes(x.role)
230
- );
231
+ if (!user) {
232
+ throw new Error(messages.userNotFound[locale]);
233
+ }
234
+ const passport = (user.passports || []).find((x) => x.status === 'valid' && allowedRoles.includes(x.role));
231
235
  return { role: passport ? passport.role : ROLES.GUEST, teamDid: info.did, user, passport: null };
232
236
  };
233
237
 
@@ -286,8 +290,8 @@ const getAuthNFTClaim =
286
290
  };
287
291
 
288
292
  const getKeyPairClaim =
289
- () =>
290
- async ({ extraParams: { locale, title }, context: { didwallet } }) => {
293
+ (node) =>
294
+ async ({ extraParams: { locale, appDid, title }, context: { didwallet } }) => {
291
295
  checkWalletVersion({ didwallet, locale });
292
296
 
293
297
  const description = {
@@ -295,10 +299,27 @@ const getKeyPairClaim =
295
299
  zh: '请为应用创建新的钥匙对',
296
300
  };
297
301
 
302
+ let appName = title;
303
+ let migrateFrom = '';
304
+
305
+ // We are rotating a key-pair for existing application
306
+ if (appDid) {
307
+ const blocklet = await node.getBlocklet({ did: appDid, attachRuntimeInfo: false });
308
+ if (!blocklet) {
309
+ throw new Error(messages.invalidBlocklet[locale]);
310
+ }
311
+
312
+ const info = await node.getNodeInfo();
313
+ const { name, wallet } = getBlockletInfo(blocklet, info.sk);
314
+ appName = name;
315
+ migrateFrom = wallet.address;
316
+ }
317
+
298
318
  return {
299
319
  mfa: !process.env.DID_CONNECT_MFA_DISABLED,
300
320
  description: description[locale] || description.en,
301
- moniker: (urlFriendly(slugify(title)) || 'application').toLowerCase(),
321
+ moniker: (urlFriendly(slugify(appName)) || 'application').toLowerCase(),
322
+ migrateFrom,
302
323
  targetType: {
303
324
  role: 'application',
304
325
  hash: 'sha3',
@@ -308,9 +329,52 @@ const getKeyPairClaim =
308
329
  };
309
330
  };
310
331
 
332
+ const getRotateKeyPairClaims = (node) => {
333
+ return [
334
+ {
335
+ authPrincipal: async ({ extraParams: { locale, appDid } }) => {
336
+ const description = {
337
+ en: 'Please select ',
338
+ zh: '请为应用创建新的钥匙对',
339
+ };
340
+
341
+ let chainInfo = { host: 'none', id: 'none', type: 'arcblock' };
342
+
343
+ if (!appDid) {
344
+ throw new Error(messages.missingBlockletDid[locale]);
345
+ }
346
+
347
+ const blocklet = await node.getBlocklet({ did: appDid, attachRuntimeInfo: false });
348
+ if (!blocklet) {
349
+ throw new Error(messages.invalidBlocklet[locale]);
350
+ }
351
+
352
+ // Try to use blocklet chain config if possible
353
+ // Since migration happens on the chain the app holds some actual assets
354
+ // We must ensure it happens on that chain
355
+ chainInfo = getChainInfo(blocklet.configObj);
356
+
357
+ // Fallback to main chain, since it is the default registry for all DID
358
+ if (chainInfo.host === 'none') {
359
+ chainInfo = { host: MAIN_CHAIN_ENDPOINT, id: 'main', type: 'arcblock' };
360
+ }
361
+
362
+ return {
363
+ chainInfo,
364
+ description: description[locale] || description.en,
365
+ target: '',
366
+ };
367
+ },
368
+ },
369
+ {
370
+ keyPair: getKeyPairClaim(node),
371
+ },
372
+ ];
373
+ };
374
+
311
375
  const getLaunchBlockletClaims = (node, authMethod) => {
312
376
  const claims = {
313
- blockletAppKeypair: ['keyPair', getKeyPairClaim()],
377
+ blockletAppKeypair: ['keyPair', getKeyPairClaim(node)],
314
378
  };
315
379
 
316
380
  if (authMethod === 'vc') {
@@ -389,6 +453,7 @@ const ensureBlockletPermission = async ({
389
453
  blocklet,
390
454
  isAuth,
391
455
  chainHost,
456
+ allowedRoles = ['owner', 'admin', 'member'],
392
457
  }) => {
393
458
  let result;
394
459
  if (authMethod === 'vc') {
@@ -416,6 +481,8 @@ const ensureBlockletPermission = async ({
416
481
  result = await authenticateBySession({
417
482
  node,
418
483
  userDid,
484
+ locale,
485
+ allowedRoles,
419
486
  });
420
487
  }
421
488
 
@@ -554,7 +621,7 @@ const createLaunchBlockletHandler =
554
621
  };
555
622
 
556
623
  const getBlockletPermissionChecker =
557
- (node) =>
624
+ (node, allowedRoles = ['owner', 'admin', 'member']) =>
558
625
  async ({ userDid, extraParams }) => {
559
626
  const { locale = 'en', connectedDid } = extraParams;
560
627
 
@@ -569,7 +636,7 @@ const getBlockletPermissionChecker =
569
636
 
570
637
  const info = await node.getNodeInfo();
571
638
  const user = await getUser(node, info.did, userDid);
572
- const passport = (user.passports || []).find((x) => x.status === 'valid' && ['owner', 'admin'].includes(x.role));
639
+ const passport = (user.passports || []).find((x) => x.status === 'valid' && allowedRoles.includes(x.role));
573
640
  if (!passport) {
574
641
  throw new Error(
575
642
  {
@@ -580,15 +647,58 @@ const getBlockletPermissionChecker =
580
647
  }
581
648
  };
582
649
 
650
+ const createRotateKeyPairHandler =
651
+ (node, authMethod) =>
652
+ async ({ claims, userDid, req, extraParams }) => {
653
+ const { locale, appDid } = extraParams;
654
+ logger.info('createRotateKeyPairHandler', extraParams);
655
+
656
+ const keyPair = claims.find((x) => x.type === 'keyPair');
657
+ if (!keyPair) {
658
+ logger.error('app keyPair must be provided');
659
+ throw new Error(messages.missingKeyPair[locale]);
660
+ }
661
+
662
+ if (!appDid) {
663
+ logger.error('appDid must be provided');
664
+ throw new Error(messages.missingBlockletDid[locale]);
665
+ }
666
+
667
+ const blocklet = await node.getBlocklet({ did: appDid, attachRuntimeInfo: false });
668
+ if (!blocklet) {
669
+ throw new Error(messages.invalidBlocklet[locale]);
670
+ }
671
+
672
+ const { role, user } = await ensureBlockletPermission({
673
+ authMethod,
674
+ node,
675
+ userDid,
676
+ locale,
677
+ allowedRoles: ['owner'],
678
+ });
679
+
680
+ await node.configBlocklet(
681
+ {
682
+ did: blocklet.meta.did,
683
+ configs: [{ key: 'BLOCKLET_APP_SK', value: toHex(keyPair.secret), secure: true }],
684
+ skipHook: true,
685
+ skipDidDocument: true,
686
+ },
687
+ formatContext(Object.assign(req, { user: { ...pick(user, ['did', 'fullName']), role } }))
688
+ );
689
+ };
690
+
583
691
  module.exports = {
584
692
  getAuthVcClaim,
585
693
  getKeyPairClaim,
586
694
  authenticateByVc,
587
695
  authenticateByNFT,
588
696
  authenticateBySession,
697
+ getRotateKeyPairClaims,
589
698
  getOwnershipNFTClaim,
590
699
  getLaunchBlockletClaims,
591
700
  createLaunchBlockletHandler,
701
+ createRotateKeyPairHandler,
592
702
  ensureBlockletPermission,
593
703
  getBlockletPermissionChecker,
594
704
  getSetupBlockletClaims,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.8.67-beta-794a8082",
6
+ "version": "1.8.68-beta-500af7e5",
7
7
  "description": "Simple lib to manage auth in ABT Node",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -20,18 +20,18 @@
20
20
  "author": "linchen <linchen1987@foxmail.com> (http://github.com/linchen1987)",
21
21
  "license": "MIT",
22
22
  "dependencies": {
23
- "@abtnode/constant": "1.8.67-beta-794a8082",
24
- "@abtnode/logger": "1.8.67-beta-794a8082",
25
- "@abtnode/util": "1.8.67-beta-794a8082",
26
- "@arcblock/did": "1.18.54",
27
- "@arcblock/jwt": "^1.18.54",
28
- "@arcblock/vc": "1.18.54",
29
- "@blocklet/constant": "1.8.67-beta-794a8082",
30
- "@blocklet/meta": "1.8.67-beta-794a8082",
31
- "@ocap/client": "1.18.54",
32
- "@ocap/mcrypto": "1.18.54",
33
- "@ocap/util": "1.18.54",
34
- "@ocap/wallet": "1.18.54",
23
+ "@abtnode/constant": "1.8.68-beta-500af7e5",
24
+ "@abtnode/logger": "1.8.68-beta-500af7e5",
25
+ "@abtnode/util": "1.8.68-beta-500af7e5",
26
+ "@arcblock/did": "1.18.57",
27
+ "@arcblock/jwt": "^1.18.57",
28
+ "@arcblock/vc": "1.18.57",
29
+ "@blocklet/constant": "1.8.68-beta-500af7e5",
30
+ "@blocklet/meta": "1.8.68-beta-500af7e5",
31
+ "@ocap/client": "1.18.57",
32
+ "@ocap/mcrypto": "1.18.57",
33
+ "@ocap/util": "1.18.57",
34
+ "@ocap/wallet": "1.18.57",
35
35
  "axios": "^0.27.2",
36
36
  "joi": "17.7.0",
37
37
  "jsonwebtoken": "^9.0.0",
@@ -43,5 +43,5 @@
43
43
  "devDependencies": {
44
44
  "jest": "^27.5.1"
45
45
  },
46
- "gitHead": "f4ad32bea4d80b12971fb6bef941bdbe2af6a834"
46
+ "gitHead": "9070621373f317a10ff0d289323bf725e30d3521"
47
47
  }