@blocklet/sdk 1.16.32-beta-f35ca4b8 → 1.16.32-beta-76103be3

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.
@@ -1,9 +1,13 @@
1
1
  import { NextFunction, Request, Response } from 'express';
2
- type MiddlewareParams = {
2
+ import { SessionUser, AuthMethod, KycMethod } from '../util/login';
3
+ type AuthOptions = {
3
4
  roles?: string[];
4
5
  permissions?: string[];
5
- kyc?: string[];
6
+ kyc?: KycMethod[];
7
+ methods?: AuthMethod[];
6
8
  getClient?: Function;
7
9
  };
8
- declare const AuthMiddleware: ({ roles, permissions, kyc, getClient }?: MiddlewareParams) => (req: Request, res: Response, next: NextFunction) => Promise<void>;
10
+ declare const AuthMiddleware: ({ roles, permissions, kyc, methods, getClient }?: AuthOptions) => (req: Request & {
11
+ user?: SessionUser;
12
+ }, res: Response, next: NextFunction) => Promise<void>;
9
13
  export = AuthMiddleware;
@@ -26,7 +26,7 @@ const getPermissionsByRole = async (getClient, role) => {
26
26
  cache.set(role, res);
27
27
  return res;
28
28
  };
29
- const AuthMiddleware = ({ roles, permissions, kyc, getClient = getServiceClient } = {}) => {
29
+ const AuthMiddleware = ({ roles, permissions, kyc, methods, getClient = getServiceClient } = {}) => {
30
30
  if (roles && !Array.isArray(roles)) {
31
31
  throw new Error('roles must be array');
32
32
  }
@@ -36,29 +36,42 @@ const AuthMiddleware = ({ roles, permissions, kyc, getClient = getServiceClient
36
36
  if (kyc && !Array.isArray(kyc)) {
37
37
  throw new Error('kyc must be array');
38
38
  }
39
+ if (methods && !Array.isArray(methods)) {
40
+ throw new Error('auth methods must be array');
41
+ }
39
42
  return async (req, res, next) => {
40
- if (!req.headers['x-user-did']) {
43
+ const userDid = req.user?.did || req.headers['x-user-did'];
44
+ const userRole = req.user?.role || req.headers['x-user-role'];
45
+ const userKyc = req.user?.kyc || req.headers['x-user-kyc'];
46
+ const userMethod = req.user?.method || 'loginToken';
47
+ if (!userDid) {
41
48
  res.status(401).json({ code: 'forbidden', error: 'not authorized' });
42
49
  return;
43
50
  }
44
- if (roles && !roles.includes(req.headers['x-user-role'])) {
51
+ if (roles && !roles.includes(userRole)) {
45
52
  res.status(403).json({ code: 'forbidden', error: 'no permission' });
46
53
  return;
47
54
  }
48
55
  if (permissions) {
49
- const { permissions: list } = await getPermissionsByRole(getClient, req.headers['x-user-role']);
56
+ const { permissions: list } = await getPermissionsByRole(getClient, userRole);
50
57
  if (!permissions.some((x) => (list || []).some((y) => y.name === x))) {
51
58
  res.status(403).json({ code: 'forbidden', error: 'no permission' });
52
59
  return;
53
60
  }
54
61
  }
55
62
  if (kyc) {
56
- const kycStatus = (0, login_1.decodeKycStatus)(Number(req.headers['x-user-kyc']) || 0);
63
+ const kycStatus = (0, login_1.decodeKycStatus)(Number(userKyc) || 0);
57
64
  if (kyc.some((x) => !kycStatus[`${x}Verified`])) {
58
65
  res.status(403).json({ code: 'forbidden', error: 'kyc required' });
59
66
  return;
60
67
  }
61
68
  }
69
+ if (methods) {
70
+ if (!methods.includes(userMethod)) {
71
+ res.status(403).json({ code: 'forbidden', error: 'auth method not allowed' });
72
+ return;
73
+ }
74
+ }
62
75
  next();
63
76
  };
64
77
  };
@@ -3,31 +3,22 @@ import auth from './auth';
3
3
  import component from './component';
4
4
  import fallback from './fallback';
5
5
  import sitemap from './sitemap';
6
+ import session from './session';
6
7
  import { csrf } from './csrf';
7
- export { user };
8
- export { auth };
9
- export { component };
10
- export { fallback };
11
- export { sitemap };
12
- export { csrf };
8
+ export { user, auth, component, fallback, sitemap, csrf, session };
13
9
  declare const _default: {
14
10
  user: () => (req: import("express").Request & {
15
- user?: {
16
- did: string;
17
- role: string | undefined;
18
- provider: string;
19
- fullName: string;
20
- walletOS: string;
21
- emailVerified: boolean;
22
- phoneVerified: boolean;
23
- };
11
+ user?: import("../util/login").SessionUser;
24
12
  }, res: import("express").Response, next: import("express").NextFunction) => void;
25
- auth: ({ roles, permissions, kyc, getClient }?: {
13
+ auth: ({ roles, permissions, kyc, methods, getClient }?: {
26
14
  roles?: string[];
27
15
  permissions?: string[];
28
- kyc?: string[];
16
+ kyc?: import("../util/login").KycMethod[];
17
+ methods?: import("../util/login").AuthMethod[];
29
18
  getClient?: Function;
30
- }) => (req: import("express").Request, res: import("express").Response, next: import("express").NextFunction) => Promise<void>;
19
+ }) => (req: import("express").Request & {
20
+ user?: import("../util/login").SessionUser;
21
+ }, res: import("express").Response, next: import("express").NextFunction) => Promise<void>;
31
22
  component: {
32
23
  verifySig: (req: import("express").Request, res: import("express").Response, next: import("express").NextFunction) => void | import("express").Response<any, Record<string, any>>;
33
24
  };
@@ -75,5 +66,12 @@ declare const _default: {
75
66
  };
76
67
  }) => void, req?: import("express").Request) => Promise<void>) => (req: import("express").Request, res: import("express").Response) => Promise<void>;
77
68
  csrf: typeof csrf;
69
+ session: (options?: {
70
+ loginToken?: boolean;
71
+ componentCall?: boolean;
72
+ signedToken?: boolean;
73
+ }) => (req: import("express").Request & {
74
+ user?: import("../util/login").SessionUser;
75
+ }, res: import("express").Response, next: import("express").NextFunction) => void | import("express").Response<any, Record<string, any>>;
78
76
  };
79
77
  export default _default;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.csrf = exports.sitemap = exports.fallback = exports.component = exports.auth = exports.user = void 0;
6
+ exports.session = exports.csrf = exports.sitemap = exports.fallback = exports.component = exports.auth = exports.user = void 0;
7
7
  const user_1 = __importDefault(require("./user"));
8
8
  exports.user = user_1.default;
9
9
  const auth_1 = __importDefault(require("./auth"));
@@ -14,6 +14,8 @@ const fallback_1 = __importDefault(require("./fallback"));
14
14
  exports.fallback = fallback_1.default;
15
15
  const sitemap_1 = __importDefault(require("./sitemap"));
16
16
  exports.sitemap = sitemap_1.default;
17
+ const session_1 = __importDefault(require("./session"));
18
+ exports.session = session_1.default;
17
19
  const csrf_1 = require("./csrf");
18
20
  Object.defineProperty(exports, "csrf", { enumerable: true, get: function () { return csrf_1.csrf; } });
19
21
  exports.default = {
@@ -23,4 +25,5 @@ exports.default = {
23
25
  fallback: fallback_1.default,
24
26
  sitemap: sitemap_1.default,
25
27
  csrf: csrf_1.csrf,
28
+ session: session_1.default,
26
29
  };
@@ -0,0 +1,11 @@
1
+ import { NextFunction, Request, Response } from 'express';
2
+ import { SessionUser } from '../util/login';
3
+ type SessionOptions = {
4
+ loginToken?: boolean;
5
+ componentCall?: boolean;
6
+ signedToken?: boolean;
7
+ };
8
+ declare const sessionMiddleware: (options?: SessionOptions) => (req: Request & {
9
+ user?: SessionUser;
10
+ }, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
11
+ export = sessionMiddleware;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const constant_1 = require("@blocklet/constant");
6
+ const mcrypto_1 = require("@ocap/mcrypto");
7
+ const jwt_1 = require("@arcblock/jwt");
8
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
9
+ const login_1 = require("../util/login");
10
+ const verify_sign_1 = require("../util/verify-sign");
11
+ const wallet_1 = __importDefault(require("../wallet"));
12
+ const sessionMiddleware = (options = {}) => {
13
+ const wallet = (0, wallet_1.default)();
14
+ const secret = mcrypto_1.Hasher.SHA3.hash256(Buffer.concat([wallet.secretKey, wallet.address].map((v) => Buffer.from(v))));
15
+ const { loginToken = true, componentCall = false, signedToken = '' } = options;
16
+ return (req, res, next) => {
17
+ // authenticate by login token
18
+ if (loginToken) {
19
+ const token = req.cookies.login_token;
20
+ if (token) {
21
+ return jsonwebtoken_1.default.verify(token, secret, (err, decoded) => {
22
+ if (err) {
23
+ res.status(401).json({ message: 'Unauthorized: Invalid login token' });
24
+ }
25
+ else {
26
+ const { did, role, fullName, provider = constant_1.LOGIN_PROVIDER.WALLET, walletOS, kyc = 0 } = decoded;
27
+ req.user = {
28
+ did,
29
+ role,
30
+ fullName,
31
+ provider,
32
+ walletOS,
33
+ ...(0, login_1.decodeKycStatus)(Number(kyc) || 0),
34
+ method: 'loginToken',
35
+ };
36
+ next();
37
+ }
38
+ });
39
+ }
40
+ }
41
+ // authenticate by component call
42
+ if (componentCall) {
43
+ const signature = req.get('x-component-sig');
44
+ if (signature) {
45
+ // FIXME: @zhanghan please check this
46
+ const data = typeof req.body === 'undefined' ? {} : req.body;
47
+ if ((0, verify_sign_1.verify)(data, signature) === false) {
48
+ return res.status(401).json({ error: 'Unauthorized: Invalid signature' });
49
+ }
50
+ req.user = {
51
+ did: req.get('x-component-did'),
52
+ role: 'component',
53
+ provider: 'wallet',
54
+ fullName: req.get('x-component-did'),
55
+ walletOS: 'embed',
56
+ emailVerified: false,
57
+ phoneVerified: false,
58
+ method: 'componentCall',
59
+ };
60
+ return next();
61
+ }
62
+ }
63
+ // authenticate by signed tmp token: which expires in 5 minutes
64
+ if (signedToken) {
65
+ const token = req.query.__jwt || '';
66
+ if (token) {
67
+ if ((0, jwt_1.verify)(token, secret) === false) {
68
+ return res.status(401).json({ error: 'Unauthorized: Invalid signed token' });
69
+ }
70
+ req.user = {
71
+ did: wallet.address,
72
+ role: 'component',
73
+ provider: 'wallet',
74
+ fullName: wallet.address,
75
+ walletOS: 'embed',
76
+ emailVerified: false,
77
+ phoneVerified: false,
78
+ method: 'signedToken',
79
+ };
80
+ return next();
81
+ }
82
+ }
83
+ return next();
84
+ };
85
+ };
86
+ module.exports = sessionMiddleware;
@@ -1,14 +1,6 @@
1
1
  import { NextFunction, Request, Response } from 'express';
2
- type User = {
3
- did: string;
4
- role: string | undefined;
5
- provider: string;
6
- fullName: string;
7
- walletOS: string;
8
- emailVerified: boolean;
9
- phoneVerified: boolean;
10
- };
2
+ import { SessionUser } from '../util/login';
11
3
  declare const userMiddleware: () => (req: Request & {
12
- user?: User;
4
+ user?: SessionUser;
13
5
  }, res: Response, next: NextFunction) => void;
14
6
  export = userMiddleware;
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
+ const util_1 = require("util");
2
3
  const login_1 = require("../util/login");
3
- const userMiddleware = () => (req, res, next) => {
4
- if (req.headers['x-user-did']) {
4
+ const userMiddleware = (0, util_1.deprecate)(() => (req, res, next) => {
5
+ if (!req.user && req.headers['x-user-did']) {
5
6
  req.user = {
6
7
  did: req.headers['x-user-did'],
7
8
  role: req.headers['x-user-role'],
@@ -12,5 +13,5 @@ const userMiddleware = () => (req, res, next) => {
12
13
  };
13
14
  }
14
15
  next();
15
- };
16
+ }, 'user middleware is deprecated, please use session middleware for better security');
16
17
  module.exports = userMiddleware;
@@ -1,3 +1,4 @@
1
+ import type { LiteralUnion } from 'type-fest';
1
2
  export declare function getLoginProvider(request: any): any;
2
3
  export declare function getSourceAppPid(request: any): any;
3
4
  export declare const encodeKycStatus: (emailVerified: boolean, phoneVerified: boolean) => number;
@@ -5,3 +6,17 @@ export declare const decodeKycStatus: (status: number) => {
5
6
  emailVerified: boolean;
6
7
  phoneVerified: boolean;
7
8
  };
9
+ export type KycMethod = LiteralUnion<'email' | 'phone', string>;
10
+ export type AuthMethod = LiteralUnion<'loginToken' | 'componentCall' | 'signedToken', string>;
11
+ export type SessionUser = {
12
+ did: string;
13
+ role: string | undefined;
14
+ provider: string;
15
+ fullName: string;
16
+ walletOS: string;
17
+ emailVerified: boolean;
18
+ phoneVerified: boolean;
19
+ method?: AuthMethod;
20
+ kyc?: number;
21
+ [key: string]: any;
22
+ };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.32-beta-f35ca4b8",
6
+ "version": "1.16.32-beta-76103be3",
7
7
  "description": "graphql client to read/write data on abt node",
8
8
  "main": "lib/index.js",
9
9
  "typings": "lib/index.d.ts",
@@ -27,15 +27,15 @@
27
27
  "author": "linchen1987 <linchen.1987@foxmail.com> (http://github.com/linchen1987)",
28
28
  "license": "Apache-2.0",
29
29
  "dependencies": {
30
- "@abtnode/client": "1.16.32-beta-f35ca4b8",
31
- "@abtnode/constant": "1.16.32-beta-f35ca4b8",
30
+ "@abtnode/client": "1.16.32-beta-76103be3",
31
+ "@abtnode/constant": "1.16.32-beta-76103be3",
32
32
  "@arcblock/did": "1.18.135",
33
33
  "@arcblock/did-auth": "1.18.135",
34
34
  "@arcblock/jwt": "1.18.135",
35
35
  "@arcblock/ws": "1.18.135",
36
- "@blocklet/constant": "1.16.32-beta-f35ca4b8",
37
- "@blocklet/env": "1.16.32-beta-f35ca4b8",
38
- "@blocklet/meta": "1.16.32-beta-f35ca4b8",
36
+ "@blocklet/constant": "1.16.32-beta-76103be3",
37
+ "@blocklet/env": "1.16.32-beta-76103be3",
38
+ "@blocklet/meta": "1.16.32-beta-76103be3",
39
39
  "@did-connect/authenticator": "^2.2.4",
40
40
  "@did-connect/handler": "^2.2.4",
41
41
  "@nedb/core": "^2.1.5",
@@ -46,6 +46,7 @@
46
46
  "fs-extra": "^11.2.0",
47
47
  "joi": "17.12.2",
48
48
  "json-stable-stringify": "^1.0.1",
49
+ "jsonwebtoken": "^9.0.0",
49
50
  "lodash": "^4.17.21",
50
51
  "lru-cache": "^6.0.0",
51
52
  "semver": "^7.6.3",
@@ -75,5 +76,5 @@
75
76
  "ts-node": "^10.9.1",
76
77
  "typescript": "^5.0.4"
77
78
  },
78
- "gitHead": "061103ce2e5a200eb4c318b41ccb7ea92b6c4ca3"
79
+ "gitHead": "6d7afe107a349b1267b29e7f2216db9997085015"
79
80
  }