@abtnode/auth 1.8.66-beta-b56e3b54 → 1.8.66

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 +3 -15
  2. package/lib/server.js +82 -169
  3. package/package.json +14 -15
package/lib/auth.js CHANGED
@@ -156,18 +156,6 @@ const messages = {
156
156
  en: 'Invalid Params',
157
157
  zh: '无效的参数',
158
158
  },
159
- missingKeyPair: {
160
- en: 'Missing app key pair',
161
- zh: '缺少应用钥匙对',
162
- },
163
- missingBlockletUrl: {
164
- en: 'Missing blocklet url',
165
- zh: '缺少应用下载地址',
166
- },
167
- missingChainHost: {
168
- en: 'Missing chain host',
169
- zh: '缺少链的端点地址',
170
- },
171
159
  invalidBlocklet: {
172
160
  en: 'Invalid Blocklet',
173
161
  zh: '无效的 Blocklet',
@@ -821,9 +809,9 @@ const handleIssuePassportResponse = async ({
821
809
  };
822
810
 
823
811
  const getVCFromClaims = async ({ claims, challenge, trustedIssuers, vcTypes, locale = 'en', vcId }) => {
824
- const credential = claims
825
- .filter(Boolean) // FIXES: https://github.com/ArcBlock/did-connect/issues/74
826
- .find((x) => x.type === 'verifiableCredential' && vcTypes.some((item) => x.item.includes(item)));
812
+ const credential = claims.find(
813
+ (x) => x.type === 'verifiableCredential' && vcTypes.some((item) => x.item.includes(item))
814
+ );
827
815
 
828
816
  if (!credential || !credential.presentation) {
829
817
  return {};
package/lib/server.js CHANGED
@@ -1,14 +1,11 @@
1
1
  const get = require('lodash/get');
2
- const pick = require('lodash/pick');
3
2
  const isEmpty = require('lodash/isEmpty');
4
3
  const last = require('lodash/last');
5
4
  const { isNFTExpired, isNFTConsumed } = require('@abtnode/util/lib/nft');
6
5
  const Client = require('@ocap/client');
7
6
  const { fromPublicKey } = require('@ocap/wallet');
8
- const { fromBase58, toAddress, toHex } = require('@ocap/util');
7
+ const { fromBase58, toAddress } = require('@ocap/util');
9
8
  const { toTypeInfo, isFromPublicKey } = require('@arcblock/did');
10
- const { urlFriendly } = require('@blocklet/meta/lib/util');
11
- const { slugify } = require('transliteration');
12
9
  const formatContext = require('@abtnode/util/lib/format-context');
13
10
  const {
14
11
  ROLES,
@@ -222,15 +219,6 @@ const authenticateByNFT = async ({ node, claims, userDid, challenge, locale, isA
222
219
  return { role: ROLES.OWNER, teamDid: info.did, nft: state, user, passport: null, ownerDid, ownerNFT: address };
223
220
  };
224
221
 
225
- const authenticateBySession = async ({ node, userDid }) => {
226
- const info = await node.getNodeInfo();
227
- 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
- return { role: passport ? passport.role : ROLES.GUEST, teamDid: info.did, user, passport: null };
232
- };
233
-
234
222
  const getAuthVcClaim =
235
223
  ({ node, launchBlocklet, blocklet, options }) =>
236
224
  async ({ extraParams: { locale, passportId }, context: { didwallet } }) => {
@@ -285,57 +273,28 @@ const getAuthNFTClaim =
285
273
  return getOwnershipNFTClaim(node, locale);
286
274
  };
287
275
 
288
- const getKeyPairClaim =
289
- () =>
290
- async ({ extraParams: { locale, title }, context: { didwallet } }) => {
291
- checkWalletVersion({ didwallet, locale });
292
-
293
- const description = {
294
- en: 'Please generate a new key-pair for this application',
295
- zh: '请为应用创建新的钥匙对',
296
- };
297
-
298
- return {
299
- mfa: !process.env.DID_CONNECT_MFA_DISABLED,
300
- description: description[locale] || description.en,
301
- moniker: (urlFriendly(slugify(title)) || 'application').toLowerCase(),
302
- targetType: {
303
- role: 'application',
304
- hash: 'sha3',
305
- key: 'ed25519',
306
- encoding: 'base58',
307
- },
308
- };
309
- };
310
-
311
276
  const getLaunchBlockletClaims = (node, authMethod) => {
312
- const claims = {
313
- blockletAppKeypair: ['keyPair', getKeyPairClaim()],
314
- };
315
-
316
277
  if (authMethod === 'vc') {
317
- claims.serverPassport = ['verifiableCredential', getAuthVcClaim({ node, launchBlocklet: true })];
318
- }
319
-
320
- if (authMethod === 'nft') {
321
- claims.serverNFT = ['asset', getAuthNFTClaim({ node })];
278
+ return {
279
+ serverPassport: ['verifiableCredential', getAuthVcClaim({ node, launchBlocklet: true })],
280
+ };
322
281
  }
323
282
 
324
- return claims;
283
+ return {
284
+ serverNFT: ['asset', getAuthNFTClaim({ node })],
285
+ };
325
286
  };
326
287
 
327
- // FIXME: @wangshijun should be changed to blocklet appSK owner claim?
328
288
  const getSetupBlockletClaims = (node, authMethod, blocklet) => {
329
- const claims = {};
330
-
331
289
  if (authMethod === 'vc') {
332
- claims.serverPassport = ['verifiableCredential', getAuthVcClaim({ node, blocklet })];
333
- }
334
- if (authMethod === 'nft') {
335
- claims.serverNFT = ['asset', getAuthNFTClaim({ node })];
290
+ return {
291
+ serverPassport: ['verifiableCredential', getAuthVcClaim({ node, blocklet })],
292
+ };
336
293
  }
337
294
 
338
- return claims;
295
+ return {
296
+ serverNFT: ['asset', getAuthNFTClaim({ node })],
297
+ };
339
298
  };
340
299
 
341
300
  const getOwnershipNFTClaim = async (node, locale) => {
@@ -402,7 +361,7 @@ const ensureBlockletPermission = async ({
402
361
  launchBlocklet: true,
403
362
  blocklet,
404
363
  });
405
- } else if (authMethod === 'nft') {
364
+ } else {
406
365
  result = await authenticateByNFT({
407
366
  node,
408
367
  locale,
@@ -412,14 +371,9 @@ const ensureBlockletPermission = async ({
412
371
  isAuth,
413
372
  chainHost,
414
373
  });
415
- } else {
416
- result = await authenticateBySession({
417
- node,
418
- userDid,
419
- });
420
374
  }
421
-
422
375
  const { teamDid, role } = result;
376
+
423
377
  const permissions = await node.getPermissionsByRole({ teamDid, role: { name: role } });
424
378
  if (!permissions.some((item) => ['mutate_blocklets'].includes(item.name))) {
425
379
  throw new Error(messages.notAuthorized[locale]);
@@ -431,38 +385,17 @@ const ensureBlockletPermission = async ({
431
385
  const createLaunchBlockletHandler =
432
386
  (node, authMethod) =>
433
387
  async ({ claims, challenge, userDid, updateSession, req, extraParams }) => {
434
- const { locale, blockletMetaUrl, title, description, chainHost } = extraParams;
388
+ const { locale, blockletMetaUrl, chainHost } = extraParams;
435
389
  logger.info('createLaunchBlockletHandler', extraParams);
436
390
 
437
- const keyPair = claims.find((x) => x.type === 'keyPair');
438
- if (!keyPair) {
439
- logger.error('app keyPair must be provided');
440
- throw new Error(messages.missingKeyPair[locale]);
441
- }
442
-
443
- if (!blockletMetaUrl && !title && !description) {
444
- logger.error('blockletMetaUrl | title + description must be provided');
445
- throw new Error(messages.missingBlockletUrl[locale]);
391
+ if (!blockletMetaUrl) {
392
+ logger.error('blockletMetaUrl must be provided');
393
+ throw new Error(messages.invalidParams[locale]);
446
394
  }
447
395
 
448
396
  if (authMethod === 'nft' && !chainHost) {
449
397
  logger.error('chainHost must be provided');
450
- throw new Error(messages.missingChainHost[locale]);
451
- }
452
-
453
- let blocklet;
454
- if (blockletMetaUrl) {
455
- blocklet = await node.getBlockletMetaFromUrl({ url: blockletMetaUrl, checkPrice: true });
456
- if (!blocklet.meta) {
457
- throw new Error(messages.invalidBlocklet[locale]);
458
- }
459
-
460
- if (!blocklet.isFree) {
461
- if (isEmpty(extraParams?.previousWorkflowData?.downloadTokenList)) {
462
- logger.error('downloadTokenList must be provided');
463
- throw new Error(messages.invalidParams[locale]);
464
- }
465
- }
398
+ throw new Error(messages.invalidParams[locale]);
466
399
  }
467
400
 
468
401
  const { role, passport, user, extra, nft } = await ensureBlockletPermission({
@@ -474,9 +407,22 @@ const createLaunchBlockletHandler =
474
407
  locale,
475
408
  isAuth: false,
476
409
  chainHost,
477
- blocklet,
478
410
  });
479
411
 
412
+ const blocklet = await node.getBlockletMetaFromUrl({ url: blockletMetaUrl, checkPrice: true });
413
+ if (!blocklet.meta) {
414
+ throw new Error(messages.invalidBlocklet[locale]);
415
+ }
416
+
417
+ if (!blocklet.isFree) {
418
+ if (isEmpty(extraParams?.previousWorkflowData?.downloadTokenList)) {
419
+ logger.error('downloadTokenList must be provided');
420
+ throw new Error(messages.invalidParams[locale]);
421
+ }
422
+ }
423
+
424
+ const { did } = blocklet.meta;
425
+
480
426
  let controller;
481
427
 
482
428
  let sessionToken = '';
@@ -488,109 +434,76 @@ const createLaunchBlockletHandler =
488
434
  secret,
489
435
  expiresIn: LAUNCH_BLOCKLET_TOKEN_EXPIRE,
490
436
  });
491
- }
492
- if (authMethod === 'nft') {
493
- if (role === SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER) {
494
- controller = extra.controller;
495
- sessionToken = createBlockletControllerAuthToken({
496
- did: userDid,
497
- role,
498
- controller,
499
- secret,
500
- expiresIn: EXTERNAL_LAUNCH_BLOCKLET_TOKEN_EXPIRE,
501
- });
502
- } else {
503
- sessionToken = createAuthTokenByOwnershipNFT({
504
- did: userDid,
505
- role,
506
- secret,
507
- expiresIn: LAUNCH_BLOCKLET_TOKEN_EXPIRE,
508
- });
509
- }
437
+ } else if (role === SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER) {
438
+ controller = extra.controller;
439
+ sessionToken = createBlockletControllerAuthToken({
440
+ did: userDid,
441
+ role,
442
+ controller,
443
+ secret,
444
+ expiresIn: EXTERNAL_LAUNCH_BLOCKLET_TOKEN_EXPIRE,
445
+ });
446
+ } else {
447
+ sessionToken = createAuthTokenByOwnershipNFT({
448
+ did: userDid,
449
+ role,
450
+ secret,
451
+ expiresIn: LAUNCH_BLOCKLET_TOKEN_EXPIRE,
452
+ });
510
453
  }
511
454
 
512
- if (sessionToken) {
513
- await updateSession({ sessionToken }, true);
514
- }
455
+ await updateSession({ sessionToken }, true);
515
456
 
516
- if (blocklet) {
517
- const blockletDid =
518
- role === SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER
519
- ? toExternalBlocklet(blocklet.meta.name, controller.nftId, { didOnly: true })
520
- : blocklet.meta.did;
457
+ const blockletDid =
458
+ role === SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER
459
+ ? toExternalBlocklet(blocklet.meta.name, controller.nftId, { didOnly: true })
460
+ : blocklet.meta.did;
521
461
 
522
- await updateSession({ blockletDid });
462
+ await updateSession({
463
+ blockletDid,
464
+ });
523
465
 
524
- // 检查是否已安装,这里不做升级的处理
525
- const existedBlocklet = await node.getBlocklet({ did: blockletDid, attachRuntimeInfo: false });
466
+ // 检查是否已安装,这里不做升级的处理
467
+ const existedBlocklet = await node.getBlocklet({ did: blockletDid, attachRuntimeInfo: false });
526
468
 
527
- // 如果是 serverless, 并且已经消费过了,但是没有安装,则抛出异常
528
- if (!existedBlocklet && role === SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER && isNFTConsumed(nft)) {
529
- throw new Error(messages.nftAlreadyConsume[locale]);
530
- }
469
+ // 如果是 serverless, 并且已经消费过了,但是没有安装,则抛出异常
470
+ if (!existedBlocklet && role === SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER && isNFTConsumed(nft)) {
471
+ throw new Error(messages.nftAlreadyConsume[locale]);
472
+ }
531
473
 
532
- if (existedBlocklet) {
533
- await updateSession({ isInstalled: true });
534
- logger.info('blocklet already exists', { blockletDid });
535
- return;
536
- }
474
+ if (existedBlocklet) {
475
+ await updateSession({ isInstalled: true });
476
+ logger.info('blocklet already exists', { blockletDid });
477
+ return;
537
478
  }
538
479
 
539
- logger.info('start install blocklet', { blockletMetaUrl, title, description });
540
- const tmp = await node.installBlocklet(
480
+ const tmp = await node.installBlocklet({
481
+ url: blockletMetaUrl,
482
+ delay: 1000 * 4, // delay 4 seconds to download, wait for ws connection from frontend
483
+ downloadTokenList: extraParams?.previousWorkflowData?.downloadTokenList,
484
+ controller: role === SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER ? controller : null,
485
+ });
486
+
487
+ await node.createAuditLog(
541
488
  {
542
- url: blockletMetaUrl,
543
- title,
544
- description,
545
- appSk: toHex(keyPair.secret),
546
- delay: 1000 * 4, // delay 4 seconds to download, wait for ws connection from frontend
547
- downloadTokenList: extraParams?.previousWorkflowData?.downloadTokenList,
548
- controller: role === SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER ? controller : null,
489
+ action: 'installBlocklet',
490
+ args: { url: blockletMetaUrl },
491
+ context: formatContext(Object.assign(req, { user })),
492
+ result: tmp,
549
493
  },
550
- formatContext(Object.assign(req, { user: { ...pick(user, ['did', 'fullName']), role } }))
494
+ node
551
495
  );
552
-
553
- await updateSession({ blockletDid: tmp.meta.did });
554
- };
555
-
556
- const getBlockletPermissionChecker =
557
- (node) =>
558
- async ({ userDid, extraParams }) => {
559
- const { locale = 'en', connectedDid } = extraParams;
560
-
561
- if (!connectedDid || userDid !== connectedDid) {
562
- throw new Error(
563
- {
564
- en: 'Please use current connected wallet to install blocklet',
565
- zh: '请使用当前登录的钱包来安装应用',
566
- }[locale]
567
- );
568
- }
569
-
570
- const info = await node.getNodeInfo();
571
- const user = await getUser(node, info.did, userDid);
572
- const passport = (user.passports || []).find((x) => x.status === 'valid' && ['owner', 'admin'].includes(x.role));
573
- if (!passport) {
574
- throw new Error(
575
- {
576
- en: 'You do not have permission to install blocklets on this server',
577
- zh: '你无权在此节点上安装应用',
578
- }[locale]
579
- );
580
- }
496
+ logger.info('start install blocklet', { blockletDid, bundleDid: did });
581
497
  };
582
498
 
583
499
  module.exports = {
584
500
  getAuthVcClaim,
585
- getKeyPairClaim,
586
501
  authenticateByVc,
587
502
  authenticateByNFT,
588
- authenticateBySession,
589
503
  getOwnershipNFTClaim,
590
504
  getLaunchBlockletClaims,
591
505
  createLaunchBlockletHandler,
592
506
  ensureBlockletPermission,
593
- getBlockletPermissionChecker,
594
507
  getSetupBlockletClaims,
595
508
  getTrustedIssuers,
596
509
  getServerlessNFTClaim,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.8.66-beta-b56e3b54",
6
+ "version": "1.8.66",
7
7
  "description": "Simple lib to manage auth in ABT Node",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -20,28 +20,27 @@
20
20
  "author": "linchen <linchen1987@foxmail.com> (http://github.com/linchen1987)",
21
21
  "license": "MIT",
22
22
  "dependencies": {
23
- "@abtnode/constant": "1.8.66-beta-b56e3b54",
24
- "@abtnode/logger": "1.8.66-beta-b56e3b54",
25
- "@abtnode/util": "1.8.66-beta-b56e3b54",
26
- "@arcblock/did": "1.18.52",
27
- "@arcblock/jwt": "^1.18.52",
28
- "@arcblock/vc": "1.18.52",
29
- "@blocklet/constant": "1.8.66-beta-b56e3b54",
30
- "@blocklet/meta": "1.8.66-beta-b56e3b54",
31
- "@ocap/client": "1.18.52",
32
- "@ocap/mcrypto": "1.18.52",
33
- "@ocap/util": "1.18.52",
34
- "@ocap/wallet": "1.18.52",
23
+ "@abtnode/constant": "1.8.66",
24
+ "@abtnode/logger": "1.8.66",
25
+ "@abtnode/util": "1.8.66",
26
+ "@arcblock/did": "1.18.42",
27
+ "@arcblock/jwt": "^1.18.42",
28
+ "@arcblock/vc": "1.18.42",
29
+ "@blocklet/constant": "1.8.66",
30
+ "@blocklet/meta": "1.8.66",
31
+ "@ocap/client": "1.18.42",
32
+ "@ocap/mcrypto": "1.18.42",
33
+ "@ocap/util": "1.18.42",
34
+ "@ocap/wallet": "1.18.42",
35
35
  "axios": "^0.27.2",
36
36
  "joi": "17.7.0",
37
37
  "jsonwebtoken": "^9.0.0",
38
38
  "lodash": "^4.17.21",
39
39
  "semver": "^7.3.8",
40
- "transliteration": "^2.3.5",
41
40
  "url-join": "^4.0.1"
42
41
  },
43
42
  "devDependencies": {
44
43
  "jest": "^27.5.1"
45
44
  },
46
- "gitHead": "4d95b431526128c14cd04c0741cac423afce8f48"
45
+ "gitHead": "282247fd0ce6702e1d6920e90e2b3be0408cf879"
47
46
  }