@abtnode/auth 1.8.35 → 1.8.37
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/lib/auth.js +8 -0
- package/lib/server.js +82 -85
- package/lib/util/get-auth-method.js +5 -1
- package/package.json +7 -7
package/lib/auth.js
CHANGED
|
@@ -48,6 +48,10 @@ const messages = {
|
|
|
48
48
|
en: 'Please provide passport',
|
|
49
49
|
zh: '请提供通行证',
|
|
50
50
|
},
|
|
51
|
+
requestOwnerPassport: {
|
|
52
|
+
en: 'Please provide owner passport',
|
|
53
|
+
zh: '请提供节点的所有者通行证',
|
|
54
|
+
},
|
|
51
55
|
requestBlockletNft: {
|
|
52
56
|
en: 'Please provide Blocklet Purchase NFT',
|
|
53
57
|
zh: '请提供 Blocklet Purchase NFT',
|
|
@@ -225,6 +229,10 @@ const messages = {
|
|
|
225
229
|
en: 'Not allowed to transfer the Server to yourself',
|
|
226
230
|
zh: '不能将节点转移给自己',
|
|
227
231
|
},
|
|
232
|
+
tagRequired: {
|
|
233
|
+
en: 'tag is required',
|
|
234
|
+
zh: 'tag 不能为空',
|
|
235
|
+
},
|
|
228
236
|
};
|
|
229
237
|
|
|
230
238
|
const PASSPORT_STATUS_KEY = 'passport-status';
|
package/lib/server.js
CHANGED
|
@@ -11,8 +11,8 @@ const {
|
|
|
11
11
|
VC_TYPE_GENERAL_PASSPORT,
|
|
12
12
|
VC_TYPE_NODE_PASSPORT,
|
|
13
13
|
NFT_TYPE_SERVER_OWNERSHIP,
|
|
14
|
-
VC_TYPE_SERVER_SHARE,
|
|
15
14
|
SERVER_ROLES,
|
|
15
|
+
NFT_TYPE_SERVER_USAGE_CREDENTIAL,
|
|
16
16
|
} = require('@abtnode/constant');
|
|
17
17
|
const { toExternalBlocklet } = require('@blocklet/meta/lib/did');
|
|
18
18
|
const {
|
|
@@ -41,46 +41,27 @@ const LAUNCH_BLOCKLET_TOKEN_EXPIRE = '1d';
|
|
|
41
41
|
// Assuming the blocklet installation will take no more than 20 min
|
|
42
42
|
const EXTERNAL_LAUNCH_BLOCKLET_TOKEN_EXPIRE = '20m';
|
|
43
43
|
|
|
44
|
-
const
|
|
45
|
-
launchBlocklet
|
|
46
|
-
? [VC_TYPE_GENERAL_PASSPORT, VC_TYPE_NODE_PASSPORT, VC_TYPE_SERVER_SHARE]
|
|
47
|
-
: [VC_TYPE_GENERAL_PASSPORT, VC_TYPE_NODE_PASSPORT];
|
|
44
|
+
const BLOCKLET_SERVER_VC_TYPES = [VC_TYPE_GENERAL_PASSPORT, VC_TYPE_NODE_PASSPORT];
|
|
48
45
|
|
|
49
46
|
const ensureLauncherIssuer = (issuers, nodeInfo) => {
|
|
50
|
-
// TODO: server 开启共享后, 才接收 launcher 颁发的 nft
|
|
51
|
-
|
|
52
47
|
const launcherDid = get(nodeInfo, 'launcher.did');
|
|
53
48
|
if (launcherDid) {
|
|
54
49
|
issuers.push(launcherDid);
|
|
55
50
|
}
|
|
56
51
|
};
|
|
57
52
|
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (!launcherDid) {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (vc.issuer.id !== launcherDid) {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (!vc.type.includes(VC_TYPE_SERVER_SHARE)) {
|
|
71
|
-
throw new Error('Cannot get NFT issued by launcher: Invalid type');
|
|
72
|
-
}
|
|
53
|
+
const getTrustedIssuers = (nodeInfo) => {
|
|
54
|
+
const trustedPassports = (nodeInfo.trustedPassports || []).map((x) => x.issuerDid);
|
|
55
|
+
return [nodeInfo.did, ...trustedPassports].filter(Boolean);
|
|
56
|
+
};
|
|
73
57
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
58
|
+
const getExternalPassport = async (nft) => {
|
|
59
|
+
const data = JSON.parse(nft.data.value);
|
|
77
60
|
|
|
78
|
-
// TODO more info from vc and launcher
|
|
79
|
-
// FIXME expireDate 需要动态获取
|
|
80
61
|
return {
|
|
81
62
|
name: SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER,
|
|
82
|
-
appMaxCount:
|
|
83
|
-
expireDate:
|
|
63
|
+
appMaxCount: data.appMaxCount || 1,
|
|
64
|
+
expireDate: last(data.expirationDate),
|
|
84
65
|
};
|
|
85
66
|
};
|
|
86
67
|
|
|
@@ -104,9 +85,7 @@ const authenticateByVc = async ({
|
|
|
104
85
|
const teamDid = info.did;
|
|
105
86
|
const { name } = info;
|
|
106
87
|
|
|
107
|
-
|
|
108
|
-
const trustedPassports = (info.trustedPassports || []).map((x) => x.issuerDid);
|
|
109
|
-
const trustedIssuers = [info.did, ...trustedPassports].filter(Boolean);
|
|
88
|
+
const trustedIssuers = getTrustedIssuers(info);
|
|
110
89
|
|
|
111
90
|
if (launchBlocklet) {
|
|
112
91
|
ensureLauncherIssuer(trustedIssuers, info);
|
|
@@ -116,7 +95,7 @@ const authenticateByVc = async ({
|
|
|
116
95
|
claims,
|
|
117
96
|
challenge,
|
|
118
97
|
trustedIssuers,
|
|
119
|
-
vcTypes:
|
|
98
|
+
vcTypes: BLOCKLET_SERVER_VC_TYPES,
|
|
120
99
|
locale,
|
|
121
100
|
vcId: blocklet?.controller?.vcId,
|
|
122
101
|
});
|
|
@@ -125,27 +104,6 @@ const authenticateByVc = async ({
|
|
|
125
104
|
throw new Error(messages.missingCredentialClaim[locale]);
|
|
126
105
|
}
|
|
127
106
|
|
|
128
|
-
// external user
|
|
129
|
-
if (launchBlocklet) {
|
|
130
|
-
const externalPassport = await getExternalPassport(vc, info);
|
|
131
|
-
if (externalPassport) {
|
|
132
|
-
return {
|
|
133
|
-
role: externalPassport.name,
|
|
134
|
-
extra: {
|
|
135
|
-
controller: {
|
|
136
|
-
vcId: vc.id,
|
|
137
|
-
appMaxCount: externalPassport.appMaxCount,
|
|
138
|
-
expireDate: externalPassport.expireDate,
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
user: {
|
|
142
|
-
did: userDid,
|
|
143
|
-
},
|
|
144
|
-
teamDid,
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
107
|
// check user approved
|
|
150
108
|
const user = await getUser(node, teamDid, userDid);
|
|
151
109
|
if (user && !user.approved) {
|
|
@@ -179,12 +137,10 @@ const authenticateByVc = async ({
|
|
|
179
137
|
// check status of external passport if passport has an endpoint
|
|
180
138
|
const endpoint = get(vc, 'credentialStatus.id');
|
|
181
139
|
if (endpoint) {
|
|
182
|
-
|
|
183
|
-
await validatePassportStatus({ vcId: vc.id, endpoint, locale });
|
|
184
|
-
}
|
|
140
|
+
await validatePassportStatus({ vcId: vc.id, endpoint, locale });
|
|
185
141
|
}
|
|
186
142
|
}
|
|
187
|
-
} else if (passportTypes.
|
|
143
|
+
} else if (passportTypes.includes(NFT_TYPE_SERVER_OWNERSHIP)) {
|
|
188
144
|
role = ROLES.OWNER;
|
|
189
145
|
} else {
|
|
190
146
|
logger.error('cannot get role from passport, use "guest" for default', { passportTypes, vcId: vc.id });
|
|
@@ -237,6 +193,26 @@ const authenticateByNFT = async ({ node, claims, userDid, challenge, locale }) =
|
|
|
237
193
|
throw new Error(messages.invalidNftIssuer[locale]);
|
|
238
194
|
}
|
|
239
195
|
|
|
196
|
+
if (state.tags.includes(NFT_TYPE_SERVER_USAGE_CREDENTIAL) && state.tags.includes(info.did)) {
|
|
197
|
+
const passport = await getExternalPassport(state);
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
role: SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER,
|
|
201
|
+
extra: {
|
|
202
|
+
controller: {
|
|
203
|
+
nftId: address,
|
|
204
|
+
nftOwner: state.owner,
|
|
205
|
+
appMaxCount: passport.appMaxCount,
|
|
206
|
+
expireDate: passport.expireDate,
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
user: {
|
|
210
|
+
did: userDid,
|
|
211
|
+
},
|
|
212
|
+
teamDid: info.did,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
240
216
|
// enforce tag match
|
|
241
217
|
if (last(state.tags) !== info.launcher.tag) {
|
|
242
218
|
throw new Error(messages.tagNotMatch[locale]);
|
|
@@ -247,14 +223,14 @@ const authenticateByNFT = async ({ node, claims, userDid, challenge, locale }) =
|
|
|
247
223
|
};
|
|
248
224
|
|
|
249
225
|
const getAuthVcClaim =
|
|
250
|
-
({ node, launchBlocklet, blocklet }) =>
|
|
226
|
+
({ node, launchBlocklet, blocklet, options }) =>
|
|
251
227
|
async ({ extraParams: { locale, passportId }, context: { didwallet } }) => {
|
|
252
228
|
checkWalletVersion({ didwallet, locale });
|
|
253
229
|
|
|
254
230
|
const baseClaim = {
|
|
255
231
|
description: messages.requestPassport[locale],
|
|
256
232
|
optional: false,
|
|
257
|
-
item:
|
|
233
|
+
item: BLOCKLET_SERVER_VC_TYPES,
|
|
258
234
|
};
|
|
259
235
|
|
|
260
236
|
if (blocklet && blocklet?.controller?.vcId) {
|
|
@@ -272,9 +248,7 @@ const getAuthVcClaim =
|
|
|
272
248
|
}
|
|
273
249
|
|
|
274
250
|
const info = await node.getNodeInfo();
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
const trustedIssuers = [info.did, ...trustedPassports].filter(Boolean);
|
|
251
|
+
const trustedIssuers = getTrustedIssuers(info);
|
|
278
252
|
|
|
279
253
|
if (launchBlocklet) {
|
|
280
254
|
ensureLauncherIssuer(trustedIssuers, info);
|
|
@@ -283,13 +257,18 @@ const getAuthVcClaim =
|
|
|
283
257
|
return {
|
|
284
258
|
...baseClaim,
|
|
285
259
|
trustedIssuers,
|
|
260
|
+
...(options || {}),
|
|
286
261
|
};
|
|
287
262
|
};
|
|
288
263
|
|
|
289
264
|
const getAuthNFTClaim =
|
|
290
265
|
({ node }) =>
|
|
291
|
-
async ({ extraParams: { locale }, context: { didwallet } }) => {
|
|
266
|
+
async ({ extraParams: { locale, launchType }, context: { didwallet } }) => {
|
|
292
267
|
checkWalletVersion({ didwallet, locale });
|
|
268
|
+
if (launchType === 'serverless') {
|
|
269
|
+
return getUsageCredentialNFTClaim(node, locale);
|
|
270
|
+
}
|
|
271
|
+
|
|
293
272
|
return getOwnershipNFTClaim(node, locale);
|
|
294
273
|
};
|
|
295
274
|
|
|
@@ -319,7 +298,7 @@ const getSetupBlockletClaims = (node, authMethod, blocklet) => {
|
|
|
319
298
|
|
|
320
299
|
const getOwnershipNFTClaim = async (node, locale) => {
|
|
321
300
|
const info = await node.getNodeInfo();
|
|
322
|
-
if (!info.ownerNft
|
|
301
|
+
if (!info.ownerNft || !info.ownerNft.issuer) {
|
|
323
302
|
throw new Error(messages.noNft[locale]);
|
|
324
303
|
}
|
|
325
304
|
|
|
@@ -339,6 +318,25 @@ const getOwnershipNFTClaim = async (node, locale) => {
|
|
|
339
318
|
};
|
|
340
319
|
};
|
|
341
320
|
|
|
321
|
+
const getUsageCredentialNFTClaim = async (node, locale) => {
|
|
322
|
+
const info = await node.getNodeInfo();
|
|
323
|
+
if (!info.ownerNft || !info.ownerNft.issuer) {
|
|
324
|
+
throw new Error(messages.noNft[locale]);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const chainHost = get(info, 'launcher.chainHost', '');
|
|
328
|
+
|
|
329
|
+
if (!chainHost) {
|
|
330
|
+
throw new Error(messages.noChainHost[locale]);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return {
|
|
334
|
+
description: messages.requestNft[locale],
|
|
335
|
+
trustedIssuers: [info.ownerNft.issuer],
|
|
336
|
+
tag: info.did,
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
|
|
342
340
|
const ensureBlockletPermission = async ({ authMethod, node, userDid, claims, challenge, locale, blocklet }) => {
|
|
343
341
|
let result;
|
|
344
342
|
if (authMethod === 'vc') {
|
|
@@ -364,7 +362,7 @@ const ensureBlockletPermission = async ({ authMethod, node, userDid, claims, cha
|
|
|
364
362
|
const { teamDid, role } = result;
|
|
365
363
|
|
|
366
364
|
const permissions = await node.getPermissionsByRole({ teamDid, role: { name: role } });
|
|
367
|
-
if (!permissions.some((item) => ['
|
|
365
|
+
if (!permissions.some((item) => ['mutate_blocklets'].includes(item.name))) {
|
|
368
366
|
throw new Error(messages.notAuthorized[locale]);
|
|
369
367
|
}
|
|
370
368
|
|
|
@@ -409,25 +407,22 @@ const createLaunchBlockletHandler =
|
|
|
409
407
|
|
|
410
408
|
let sessionToken = '';
|
|
411
409
|
if (authMethod === 'vc') {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
expiresIn: LAUNCH_BLOCKLET_TOKEN_EXPIRE,
|
|
429
|
-
});
|
|
430
|
-
}
|
|
410
|
+
sessionToken = createAuthToken({
|
|
411
|
+
did: userDid,
|
|
412
|
+
passport,
|
|
413
|
+
role,
|
|
414
|
+
secret,
|
|
415
|
+
expiresIn: LAUNCH_BLOCKLET_TOKEN_EXPIRE,
|
|
416
|
+
});
|
|
417
|
+
} else if (role === SERVER_ROLES.EXTERNAL_BLOCKLET_CONTROLLER) {
|
|
418
|
+
controller = extra.controller;
|
|
419
|
+
sessionToken = createBlockletControllerAuthToken({
|
|
420
|
+
did: userDid,
|
|
421
|
+
role,
|
|
422
|
+
controller,
|
|
423
|
+
secret,
|
|
424
|
+
expiresIn: EXTERNAL_LAUNCH_BLOCKLET_TOKEN_EXPIRE,
|
|
425
|
+
});
|
|
431
426
|
} else {
|
|
432
427
|
sessionToken = createAuthTokenByOwnershipNFT({
|
|
433
428
|
did: userDid,
|
|
@@ -491,4 +486,6 @@ module.exports = {
|
|
|
491
486
|
createLaunchBlockletHandler,
|
|
492
487
|
ensureBlockletPermission,
|
|
493
488
|
getSetupBlockletClaims,
|
|
489
|
+
getTrustedIssuers,
|
|
490
|
+
getUsageCredentialNFTClaim,
|
|
494
491
|
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.8.
|
|
6
|
+
"version": "1.8.37",
|
|
7
7
|
"description": "Simple lib to manage auth in ABT Node",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
"author": "linchen <linchen1987@foxmail.com> (http://github.com/linchen1987)",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@abtnode/constant": "1.8.
|
|
24
|
-
"@abtnode/logger": "1.8.
|
|
25
|
-
"@abtnode/util": "1.8.
|
|
23
|
+
"@abtnode/constant": "1.8.37",
|
|
24
|
+
"@abtnode/logger": "1.8.37",
|
|
25
|
+
"@abtnode/util": "1.8.37",
|
|
26
26
|
"@arcblock/did": "1.18.15",
|
|
27
27
|
"@arcblock/jwt": "^1.18.15",
|
|
28
28
|
"@arcblock/vc": "1.18.15",
|
|
29
|
-
"@blocklet/constant": "1.8.
|
|
30
|
-
"@blocklet/meta": "1.8.
|
|
29
|
+
"@blocklet/constant": "1.8.37",
|
|
30
|
+
"@blocklet/meta": "1.8.37",
|
|
31
31
|
"@ocap/client": "1.18.15",
|
|
32
32
|
"@ocap/mcrypto": "1.18.15",
|
|
33
33
|
"@ocap/util": "1.18.15",
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"jest": "^27.5.1"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "f26f451c6e2b1168b36f78269eafdf3f671236bf"
|
|
46
46
|
}
|