@arcblock/jwt 1.27.16 → 1.28.1

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/esm/index.d.ts CHANGED
@@ -1,25 +1,27 @@
1
- import { BytesType } from '@ocap/util';
2
- export type JwtBody = {
3
- iss: string;
4
- iat: string;
5
- nbf: string;
6
- exp: string;
7
- version: string;
8
- [key: string]: any;
1
+ import { BytesType } from "@ocap/util";
2
+
3
+ //#region src/index.d.ts
4
+ type JwtBody = {
5
+ iss: string;
6
+ iat: string;
7
+ nbf: string;
8
+ exp: string;
9
+ version: string;
10
+ [key: string]: any;
9
11
  };
10
- export type JwtHeader = {
11
- alg: string;
12
- type: 'JWT';
12
+ type JwtHeader = {
13
+ alg: string;
14
+ type: 'JWT';
13
15
  };
14
- export type JwtToken = {
15
- header: JwtHeader;
16
- body: JwtBody;
17
- signature: string;
16
+ type JwtToken = {
17
+ header: JwtHeader;
18
+ body: JwtBody;
19
+ signature: string;
18
20
  };
19
- export type JwtVerifyOptions = Partial<{
20
- tolerance: number;
21
- enforceTimestamp: boolean;
22
- signerKey: string;
21
+ type JwtVerifyOptions = Partial<{
22
+ tolerance: number;
23
+ enforceTimestamp: boolean;
24
+ signerKey: string;
23
25
  }>;
24
26
  /**
25
27
  *
@@ -31,10 +33,10 @@ export type JwtVerifyOptions = Partial<{
31
33
  * @param {string} [version='1.0.0']
32
34
  * @return {*} {string} - hex encoded signature
33
35
  */
34
- export declare function sign(signer: string, sk?: BytesType, payload?: {}, doSign?: boolean, version?: string): Promise<string>;
35
- export declare function signV2(signer: string, sk?: BytesType, payload?: any): Promise<string>;
36
- export declare function decode(token: string, bodyOnly?: true): JwtBody;
37
- export declare function decode(token: string, bodyOnly?: false): JwtToken;
36
+ declare function sign(signer: string, sk?: BytesType, payload?: {}, doSign?: boolean, version?: string): Promise<string>;
37
+ declare function signV2(signer: string, sk?: BytesType, payload?: any): Promise<string>;
38
+ declare function decode(token: string, bodyOnly?: true): JwtBody;
39
+ declare function decode(token: string, bodyOnly?: false): JwtToken;
38
40
  /**
39
41
  * Verify a jwt token
40
42
  *
@@ -55,4 +57,6 @@ export declare function decode(token: string, bodyOnly?: false): JwtToken;
55
57
  * }]
56
58
  * @return {*} {boolean}
57
59
  */
58
- export declare function verify(token: string, signerPk: BytesType, options?: JwtVerifyOptions): Promise<boolean>;
60
+ declare function verify(token: string, signerPk: BytesType, options?: JwtVerifyOptions): Promise<boolean>;
61
+ //#endregion
62
+ export { JwtBody, JwtHeader, JwtToken, JwtVerifyOptions, decode, sign, signV2, verify };
package/esm/index.js CHANGED
@@ -1,187 +1,177 @@
1
- /* eslint-disable @typescript-eslint/ban-ts-comment */
2
- import stringify from 'json-stable-stringify';
3
- import semver from 'semver';
4
- import { toHex, toBase64, fromBase64 } from '@ocap/util';
5
- import { toDid, toStrictHex, toTypeInfo, isValid, isFromPublicKey } from '@arcblock/did';
6
- import { types, getSigner, Hasher } from '@ocap/mcrypto';
7
- import Debug from 'debug';
8
- const debug = Debug('@arcblock/jwt');
9
- // we start hashing before signing after 1.1
10
- const JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN = '1.1.0';
11
- // since ios requires a fixed length of input to sign, we use sha3 here before sign
1
+ import stringify from "json-stable-stringify";
2
+ import semver from "semver";
3
+ import { fromBase64, toBase64, toHex } from "@ocap/util";
4
+ import { isFromPublicKey, isValid, toDid, toStrictHex, toTypeInfo } from "@arcblock/did";
5
+ import { Hasher, getSigner, types } from "@ocap/mcrypto";
6
+ import Debug from "debug";
7
+
8
+ //#region src/index.ts
9
+ const debug = Debug("@arcblock/jwt");
10
+ const JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN = "1.1.0";
12
11
  const hasher = Hasher.SHA3.hash256;
13
12
  /**
14
- *
15
- *
16
- * @param {string} signer - address string
17
- * @param {string} sk - hex encoded secret key
18
- * @param {*} [payload={}] - data to be included before signing
19
- * @param {boolean} [doSign=true] - do we need to sign the payload or just return the content to be signed
20
- * @param {string} [version='1.0.0']
21
- * @return {*} {string} - hex encoded signature
22
- */
23
- // eslint-disable-next-line require-await
24
- export async function sign(signer, sk, payload = {}, doSign = true, version = '1.0.0') {
25
- if (isValid(signer) === false) {
26
- throw new Error('Cannot do sign with invalid signer');
27
- }
28
- const type = toTypeInfo(signer);
29
- const headers = {
30
- [types.KeyType.SECP256K1]: {
31
- alg: 'ES256K',
32
- type: 'JWT',
33
- },
34
- [types.KeyType.ED25519]: {
35
- alg: 'Ed25519',
36
- type: 'JWT',
37
- },
38
- [types.KeyType.ETHEREUM]: {
39
- alg: 'Ethereum',
40
- type: 'JWT',
41
- },
42
- [types.KeyType.PASSKEY]: {
43
- alg: 'Passkey',
44
- type: 'JWT',
45
- },
46
- };
47
- // make header
48
- const header = headers[type.pk];
49
- const headerB64 = toBase64(stringify(header));
50
- // make body
51
- const now = Math.floor(Date.now() / 1000);
52
- const body = {
53
- iss: toDid(signer),
54
- iat: String(now),
55
- nbf: String(now),
56
- exp: String(now + 5 * 60),
57
- version,
58
- ...(payload || {}),
59
- };
60
- // remove empty keys
61
- Object.keys(body).forEach((x) => {
62
- if (typeof body[x] === 'undefined' || body[x] == null || body[x] === '') {
63
- delete body[x];
64
- }
65
- });
66
- const bodyB64 = toBase64(stringify(body));
67
- debug('sign.body', body);
68
- // @ts-ignore make signature
69
- const msgHex = toHex(`${headerB64}.${bodyB64}`);
70
- const msgHash = semver.gte(semver.coerce(version).version, JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN)
71
- ? hasher(msgHex)
72
- : msgHex;
73
- // istanbul ignore if
74
- if (!doSign) {
75
- return `${headerB64}.${bodyB64}`;
76
- }
77
- const sigHex = getSigner(type.pk).sign(msgHash, sk);
78
- const sigB64 = toBase64(sigHex);
79
- return [headerB64, bodyB64, sigB64].join('.');
13
+ *
14
+ *
15
+ * @param {string} signer - address string
16
+ * @param {string} sk - hex encoded secret key
17
+ * @param {*} [payload={}] - data to be included before signing
18
+ * @param {boolean} [doSign=true] - do we need to sign the payload or just return the content to be signed
19
+ * @param {string} [version='1.0.0']
20
+ * @return {*} {string} - hex encoded signature
21
+ */
22
+ async function sign(signer, sk, payload = {}, doSign = true, version = "1.0.0") {
23
+ if (isValid(signer) === false) throw new Error("Cannot do sign with invalid signer");
24
+ const type = toTypeInfo(signer);
25
+ const header = {
26
+ [types.KeyType.SECP256K1]: {
27
+ alg: "ES256K",
28
+ type: "JWT"
29
+ },
30
+ [types.KeyType.ED25519]: {
31
+ alg: "Ed25519",
32
+ type: "JWT"
33
+ },
34
+ [types.KeyType.ETHEREUM]: {
35
+ alg: "Ethereum",
36
+ type: "JWT"
37
+ },
38
+ [types.KeyType.PASSKEY]: {
39
+ alg: "Passkey",
40
+ type: "JWT"
41
+ }
42
+ }[type.pk];
43
+ const headerB64 = toBase64(stringify(header));
44
+ const now = Math.floor(Date.now() / 1e3);
45
+ const body = {
46
+ iss: toDid(signer),
47
+ iat: String(now),
48
+ nbf: String(now),
49
+ exp: String(now + 300),
50
+ version,
51
+ ...payload || {}
52
+ };
53
+ Object.keys(body).forEach((x) => {
54
+ if (typeof body[x] === "undefined" || body[x] == null || body[x] === "") delete body[x];
55
+ });
56
+ const bodyB64 = toBase64(stringify(body));
57
+ debug("sign.body", body);
58
+ const msgHex = toHex(`${headerB64}.${bodyB64}`);
59
+ const msgHash = semver.gte(semver.coerce(version).version, JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN) ? hasher(msgHex) : msgHex;
60
+ // istanbul ignore if
61
+ if (!doSign) return `${headerB64}.${bodyB64}`;
62
+ return [
63
+ headerB64,
64
+ bodyB64,
65
+ toBase64(getSigner(type.pk).sign(msgHash, sk))
66
+ ].join(".");
80
67
  }
81
- // eslint-disable-next-line require-await
82
- export async function signV2(signer, sk, payload = {}) {
83
- return sign(signer, sk, payload, !!sk, '1.1.0');
68
+ async function signV2(signer, sk, payload = {}) {
69
+ return sign(signer, sk, payload, !!sk, "1.1.0");
84
70
  }
85
- export function decode(token, bodyOnly = true) {
86
- const [headerB64, bodyB64, sigB64] = token.split('.');
87
- const header = JSON.parse(fromBase64(headerB64).toString());
88
- const body = JSON.parse(fromBase64(bodyB64).toString());
89
- const sig = Buffer.from(fromBase64(sigB64)).toString('hex');
90
- if (bodyOnly) {
91
- return body;
92
- }
93
- return { header, body, signature: `0x${toStrictHex(sig)}` };
71
+ function decode(token, bodyOnly = true) {
72
+ const [headerB64, bodyB64, sigB64] = token.split(".");
73
+ const header = JSON.parse(fromBase64(headerB64).toString());
74
+ const body = JSON.parse(fromBase64(bodyB64).toString());
75
+ const sig = Buffer.from(fromBase64(sigB64)).toString("hex");
76
+ if (bodyOnly) return body;
77
+ return {
78
+ header,
79
+ body,
80
+ signature: `0x${toStrictHex(sig)}`
81
+ };
94
82
  }
95
83
  /**
96
- * Verify a jwt token
97
- *
98
- * @param {string} token - the jwt token
99
- * @param {string} signerPk - signer public key
100
- * @param {{
101
- * tolerance: number; - number of seconds to tolerant expire
102
- * enforceTimestamp: boolean; - whether should be verify timestamps?
103
- * signerKey: string; - which field should be used to pick the signer
104
- * }} [{
105
- * tolerance,
106
- * enforceTimestamp,
107
- * signerKey,
108
- * }={
109
- * tolerance: 5,
110
- * enforceTimestamp: true,
111
- * signerKey: 'iss',
112
- * }]
113
- * @return {*} {boolean}
114
- */
115
- // eslint-disable-next-line require-await
116
- export async function verify(token, signerPk, options) {
117
- const { tolerance, enforceTimestamp, signerKey } = Object.assign({
118
- tolerance: 5,
119
- enforceTimestamp: true,
120
- signerKey: 'iss',
121
- }, options);
122
- try {
123
- const [headerB64, bodyB64] = token.split('.');
124
- const { header, body, signature } = decode(token, false);
125
- if (!signature) {
126
- debug('verify.error.emptySig');
127
- return false;
128
- }
129
- if (!header.alg) {
130
- debug('verify.error.emptyAlg');
131
- return false;
132
- }
133
- const signerDid = body[signerKey];
134
- if (!signerDid) {
135
- debug('verify.error.emptySignerDid');
136
- return false;
137
- }
138
- if (isFromPublicKey(signerDid, signerPk) === false) {
139
- debug('verify.error.signerDidAndPkNotMatch');
140
- return false;
141
- }
142
- if (enforceTimestamp) {
143
- const now = Math.ceil(Date.now() / 1000);
144
- const exp = Number(body.exp) || 0;
145
- const iat = Number(body.iat) || 0;
146
- const nbf = Number(body.nbf) || 0;
147
- debug('verify.enforceTimestamp', { now, exp, iat, nbf });
148
- if (exp && exp + tolerance < now) {
149
- debug('verify.error.expired');
150
- return false;
151
- }
152
- if (iat && iat > now && iat - now > tolerance) {
153
- debug('verify.error.issuedAt');
154
- return false;
155
- }
156
- if (nbf && nbf > now && nbf - now > tolerance) {
157
- debug('verify.error.notBefore');
158
- return false;
159
- }
160
- }
161
- const signers = {
162
- secp256k1: getSigner(types.KeyType.SECP256K1),
163
- es256k: getSigner(types.KeyType.SECP256K1),
164
- ed25519: getSigner(types.KeyType.ED25519),
165
- ethereum: getSigner(types.KeyType.ETHEREUM),
166
- passkey: getSigner(types.KeyType.PASSKEY),
167
- };
168
- const alg = header.alg.toLowerCase();
169
- if (signers[alg]) {
170
- // @ts-ignore
171
- const msgHex = toHex(`${headerB64}.${bodyB64}`);
172
- // If we are using v1.1 protocol, the message should be hashed before verify
173
- const version = body.version && semver.coerce(body.version) ? semver.coerce(body.version).version : '';
174
- if (version && version === JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN) {
175
- return signers[alg].verify(hasher(msgHex), signature, signerPk);
176
- }
177
- return signers[alg].verify(msgHex, signature, signerPk);
178
- }
179
- debug('verify.error.crypto');
180
- return false;
181
- }
182
- catch (err) {
183
- debug('verify.error.exception');
184
- debug(err);
185
- return false;
186
- }
84
+ * Verify a jwt token
85
+ *
86
+ * @param {string} token - the jwt token
87
+ * @param {string} signerPk - signer public key
88
+ * @param {{
89
+ * tolerance: number; - number of seconds to tolerant expire
90
+ * enforceTimestamp: boolean; - whether should be verify timestamps?
91
+ * signerKey: string; - which field should be used to pick the signer
92
+ * }} [{
93
+ * tolerance,
94
+ * enforceTimestamp,
95
+ * signerKey,
96
+ * }={
97
+ * tolerance: 5,
98
+ * enforceTimestamp: true,
99
+ * signerKey: 'iss',
100
+ * }]
101
+ * @return {*} {boolean}
102
+ */
103
+ async function verify(token, signerPk, options) {
104
+ const { tolerance, enforceTimestamp, signerKey } = Object.assign({
105
+ tolerance: 5,
106
+ enforceTimestamp: true,
107
+ signerKey: "iss"
108
+ }, options);
109
+ try {
110
+ const [headerB64, bodyB64] = token.split(".");
111
+ const { header, body, signature } = decode(token, false);
112
+ if (!signature) {
113
+ debug("verify.error.emptySig");
114
+ return false;
115
+ }
116
+ if (!header.alg) {
117
+ debug("verify.error.emptyAlg");
118
+ return false;
119
+ }
120
+ const signerDid = body[signerKey];
121
+ if (!signerDid) {
122
+ debug("verify.error.emptySignerDid");
123
+ return false;
124
+ }
125
+ if (isFromPublicKey(signerDid, signerPk) === false) {
126
+ debug("verify.error.signerDidAndPkNotMatch");
127
+ return false;
128
+ }
129
+ if (enforceTimestamp) {
130
+ const now = Math.ceil(Date.now() / 1e3);
131
+ const exp = Number(body.exp) || 0;
132
+ const iat = Number(body.iat) || 0;
133
+ const nbf = Number(body.nbf) || 0;
134
+ debug("verify.enforceTimestamp", {
135
+ now,
136
+ exp,
137
+ iat,
138
+ nbf
139
+ });
140
+ if (exp && exp + tolerance < now) {
141
+ debug("verify.error.expired");
142
+ return false;
143
+ }
144
+ if (iat && iat > now && iat - now > tolerance) {
145
+ debug("verify.error.issuedAt");
146
+ return false;
147
+ }
148
+ if (nbf && nbf > now && nbf - now > tolerance) {
149
+ debug("verify.error.notBefore");
150
+ return false;
151
+ }
152
+ }
153
+ const signers = {
154
+ secp256k1: getSigner(types.KeyType.SECP256K1),
155
+ es256k: getSigner(types.KeyType.SECP256K1),
156
+ ed25519: getSigner(types.KeyType.ED25519),
157
+ ethereum: getSigner(types.KeyType.ETHEREUM),
158
+ passkey: getSigner(types.KeyType.PASSKEY)
159
+ };
160
+ const alg = header.alg.toLowerCase();
161
+ if (signers[alg]) {
162
+ const msgHex = toHex(`${headerB64}.${bodyB64}`);
163
+ const version = body.version && semver.coerce(body.version) ? semver.coerce(body.version).version : "";
164
+ if (version && version === JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN) return signers[alg].verify(hasher(msgHex), signature, signerPk);
165
+ return signers[alg].verify(msgHex, signature, signerPk);
166
+ }
167
+ debug("verify.error.crypto");
168
+ return false;
169
+ } catch (err) {
170
+ debug("verify.error.exception");
171
+ debug(err);
172
+ return false;
173
+ }
187
174
  }
175
+
176
+ //#endregion
177
+ export { decode, sign, signV2, verify };
@@ -0,0 +1,29 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) {
13
+ __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ }
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+
27
+ //#endregion
28
+
29
+ exports.__toESM = __toESM;
package/lib/index.d.ts CHANGED
@@ -1,25 +1,27 @@
1
- import { BytesType } from '@ocap/util';
2
- export type JwtBody = {
3
- iss: string;
4
- iat: string;
5
- nbf: string;
6
- exp: string;
7
- version: string;
8
- [key: string]: any;
1
+ import { BytesType } from "@ocap/util";
2
+
3
+ //#region src/index.d.ts
4
+ type JwtBody = {
5
+ iss: string;
6
+ iat: string;
7
+ nbf: string;
8
+ exp: string;
9
+ version: string;
10
+ [key: string]: any;
9
11
  };
10
- export type JwtHeader = {
11
- alg: string;
12
- type: 'JWT';
12
+ type JwtHeader = {
13
+ alg: string;
14
+ type: 'JWT';
13
15
  };
14
- export type JwtToken = {
15
- header: JwtHeader;
16
- body: JwtBody;
17
- signature: string;
16
+ type JwtToken = {
17
+ header: JwtHeader;
18
+ body: JwtBody;
19
+ signature: string;
18
20
  };
19
- export type JwtVerifyOptions = Partial<{
20
- tolerance: number;
21
- enforceTimestamp: boolean;
22
- signerKey: string;
21
+ type JwtVerifyOptions = Partial<{
22
+ tolerance: number;
23
+ enforceTimestamp: boolean;
24
+ signerKey: string;
23
25
  }>;
24
26
  /**
25
27
  *
@@ -31,10 +33,10 @@ export type JwtVerifyOptions = Partial<{
31
33
  * @param {string} [version='1.0.0']
32
34
  * @return {*} {string} - hex encoded signature
33
35
  */
34
- export declare function sign(signer: string, sk?: BytesType, payload?: {}, doSign?: boolean, version?: string): Promise<string>;
35
- export declare function signV2(signer: string, sk?: BytesType, payload?: any): Promise<string>;
36
- export declare function decode(token: string, bodyOnly?: true): JwtBody;
37
- export declare function decode(token: string, bodyOnly?: false): JwtToken;
36
+ declare function sign(signer: string, sk?: BytesType, payload?: {}, doSign?: boolean, version?: string): Promise<string>;
37
+ declare function signV2(signer: string, sk?: BytesType, payload?: any): Promise<string>;
38
+ declare function decode(token: string, bodyOnly?: true): JwtBody;
39
+ declare function decode(token: string, bodyOnly?: false): JwtToken;
38
40
  /**
39
41
  * Verify a jwt token
40
42
  *
@@ -55,4 +57,6 @@ export declare function decode(token: string, bodyOnly?: false): JwtToken;
55
57
  * }]
56
58
  * @return {*} {boolean}
57
59
  */
58
- export declare function verify(token: string, signerPk: BytesType, options?: JwtVerifyOptions): Promise<boolean>;
60
+ declare function verify(token: string, signerPk: BytesType, options?: JwtVerifyOptions): Promise<boolean>;
61
+ //#endregion
62
+ export { JwtBody, JwtHeader, JwtToken, JwtVerifyOptions, decode, sign, signV2, verify };
package/lib/index.js CHANGED
@@ -1,196 +1,184 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.sign = sign;
7
- exports.signV2 = signV2;
8
- exports.decode = decode;
9
- exports.verify = verify;
10
- /* eslint-disable @typescript-eslint/ban-ts-comment */
11
- const json_stable_stringify_1 = __importDefault(require("json-stable-stringify"));
12
- const semver_1 = __importDefault(require("semver"));
13
- const util_1 = require("@ocap/util");
14
- const did_1 = require("@arcblock/did");
15
- const mcrypto_1 = require("@ocap/mcrypto");
16
- const debug_1 = __importDefault(require("debug"));
17
- const debug = (0, debug_1.default)('@arcblock/jwt');
18
- // we start hashing before signing after 1.1
19
- const JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN = '1.1.0';
20
- // since ios requires a fixed length of input to sign, we use sha3 here before sign
21
- const hasher = mcrypto_1.Hasher.SHA3.hash256;
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.js');
2
+ let json_stable_stringify = require("json-stable-stringify");
3
+ json_stable_stringify = require_rolldown_runtime.__toESM(json_stable_stringify);
4
+ let semver = require("semver");
5
+ semver = require_rolldown_runtime.__toESM(semver);
6
+ let _ocap_util = require("@ocap/util");
7
+ let _arcblock_did = require("@arcblock/did");
8
+ let _ocap_mcrypto = require("@ocap/mcrypto");
9
+ let debug = require("debug");
10
+ debug = require_rolldown_runtime.__toESM(debug);
11
+
12
+ //#region src/index.ts
13
+ const debug$1 = (0, debug.default)("@arcblock/jwt");
14
+ const JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN = "1.1.0";
15
+ const hasher = _ocap_mcrypto.Hasher.SHA3.hash256;
22
16
  /**
23
- *
24
- *
25
- * @param {string} signer - address string
26
- * @param {string} sk - hex encoded secret key
27
- * @param {*} [payload={}] - data to be included before signing
28
- * @param {boolean} [doSign=true] - do we need to sign the payload or just return the content to be signed
29
- * @param {string} [version='1.0.0']
30
- * @return {*} {string} - hex encoded signature
31
- */
32
- // eslint-disable-next-line require-await
33
- async function sign(signer, sk, payload = {}, doSign = true, version = '1.0.0') {
34
- if ((0, did_1.isValid)(signer) === false) {
35
- throw new Error('Cannot do sign with invalid signer');
36
- }
37
- const type = (0, did_1.toTypeInfo)(signer);
38
- const headers = {
39
- [mcrypto_1.types.KeyType.SECP256K1]: {
40
- alg: 'ES256K',
41
- type: 'JWT',
42
- },
43
- [mcrypto_1.types.KeyType.ED25519]: {
44
- alg: 'Ed25519',
45
- type: 'JWT',
46
- },
47
- [mcrypto_1.types.KeyType.ETHEREUM]: {
48
- alg: 'Ethereum',
49
- type: 'JWT',
50
- },
51
- [mcrypto_1.types.KeyType.PASSKEY]: {
52
- alg: 'Passkey',
53
- type: 'JWT',
54
- },
55
- };
56
- // make header
57
- const header = headers[type.pk];
58
- const headerB64 = (0, util_1.toBase64)((0, json_stable_stringify_1.default)(header));
59
- // make body
60
- const now = Math.floor(Date.now() / 1000);
61
- const body = {
62
- iss: (0, did_1.toDid)(signer),
63
- iat: String(now),
64
- nbf: String(now),
65
- exp: String(now + 5 * 60),
66
- version,
67
- ...(payload || {}),
68
- };
69
- // remove empty keys
70
- Object.keys(body).forEach((x) => {
71
- if (typeof body[x] === 'undefined' || body[x] == null || body[x] === '') {
72
- delete body[x];
73
- }
74
- });
75
- const bodyB64 = (0, util_1.toBase64)((0, json_stable_stringify_1.default)(body));
76
- debug('sign.body', body);
77
- // @ts-ignore make signature
78
- const msgHex = (0, util_1.toHex)(`${headerB64}.${bodyB64}`);
79
- const msgHash = semver_1.default.gte(semver_1.default.coerce(version).version, JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN)
80
- ? hasher(msgHex)
81
- : msgHex;
82
- // istanbul ignore if
83
- if (!doSign) {
84
- return `${headerB64}.${bodyB64}`;
85
- }
86
- const sigHex = (0, mcrypto_1.getSigner)(type.pk).sign(msgHash, sk);
87
- const sigB64 = (0, util_1.toBase64)(sigHex);
88
- return [headerB64, bodyB64, sigB64].join('.');
17
+ *
18
+ *
19
+ * @param {string} signer - address string
20
+ * @param {string} sk - hex encoded secret key
21
+ * @param {*} [payload={}] - data to be included before signing
22
+ * @param {boolean} [doSign=true] - do we need to sign the payload or just return the content to be signed
23
+ * @param {string} [version='1.0.0']
24
+ * @return {*} {string} - hex encoded signature
25
+ */
26
+ async function sign(signer, sk, payload = {}, doSign = true, version = "1.0.0") {
27
+ if ((0, _arcblock_did.isValid)(signer) === false) throw new Error("Cannot do sign with invalid signer");
28
+ const type = (0, _arcblock_did.toTypeInfo)(signer);
29
+ const header = {
30
+ [_ocap_mcrypto.types.KeyType.SECP256K1]: {
31
+ alg: "ES256K",
32
+ type: "JWT"
33
+ },
34
+ [_ocap_mcrypto.types.KeyType.ED25519]: {
35
+ alg: "Ed25519",
36
+ type: "JWT"
37
+ },
38
+ [_ocap_mcrypto.types.KeyType.ETHEREUM]: {
39
+ alg: "Ethereum",
40
+ type: "JWT"
41
+ },
42
+ [_ocap_mcrypto.types.KeyType.PASSKEY]: {
43
+ alg: "Passkey",
44
+ type: "JWT"
45
+ }
46
+ }[type.pk];
47
+ const headerB64 = (0, _ocap_util.toBase64)((0, json_stable_stringify.default)(header));
48
+ const now = Math.floor(Date.now() / 1e3);
49
+ const body = {
50
+ iss: (0, _arcblock_did.toDid)(signer),
51
+ iat: String(now),
52
+ nbf: String(now),
53
+ exp: String(now + 300),
54
+ version,
55
+ ...payload || {}
56
+ };
57
+ Object.keys(body).forEach((x) => {
58
+ if (typeof body[x] === "undefined" || body[x] == null || body[x] === "") delete body[x];
59
+ });
60
+ const bodyB64 = (0, _ocap_util.toBase64)((0, json_stable_stringify.default)(body));
61
+ debug$1("sign.body", body);
62
+ const msgHex = (0, _ocap_util.toHex)(`${headerB64}.${bodyB64}`);
63
+ const msgHash = semver.default.gte(semver.default.coerce(version).version, JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN) ? hasher(msgHex) : msgHex;
64
+ // istanbul ignore if
65
+ if (!doSign) return `${headerB64}.${bodyB64}`;
66
+ return [
67
+ headerB64,
68
+ bodyB64,
69
+ (0, _ocap_util.toBase64)((0, _ocap_mcrypto.getSigner)(type.pk).sign(msgHash, sk))
70
+ ].join(".");
89
71
  }
90
- // eslint-disable-next-line require-await
91
72
  async function signV2(signer, sk, payload = {}) {
92
- return sign(signer, sk, payload, !!sk, '1.1.0');
73
+ return sign(signer, sk, payload, !!sk, "1.1.0");
93
74
  }
94
75
  function decode(token, bodyOnly = true) {
95
- const [headerB64, bodyB64, sigB64] = token.split('.');
96
- const header = JSON.parse((0, util_1.fromBase64)(headerB64).toString());
97
- const body = JSON.parse((0, util_1.fromBase64)(bodyB64).toString());
98
- const sig = Buffer.from((0, util_1.fromBase64)(sigB64)).toString('hex');
99
- if (bodyOnly) {
100
- return body;
101
- }
102
- return { header, body, signature: `0x${(0, did_1.toStrictHex)(sig)}` };
76
+ const [headerB64, bodyB64, sigB64] = token.split(".");
77
+ const header = JSON.parse((0, _ocap_util.fromBase64)(headerB64).toString());
78
+ const body = JSON.parse((0, _ocap_util.fromBase64)(bodyB64).toString());
79
+ const sig = Buffer.from((0, _ocap_util.fromBase64)(sigB64)).toString("hex");
80
+ if (bodyOnly) return body;
81
+ return {
82
+ header,
83
+ body,
84
+ signature: `0x${(0, _arcblock_did.toStrictHex)(sig)}`
85
+ };
103
86
  }
104
87
  /**
105
- * Verify a jwt token
106
- *
107
- * @param {string} token - the jwt token
108
- * @param {string} signerPk - signer public key
109
- * @param {{
110
- * tolerance: number; - number of seconds to tolerant expire
111
- * enforceTimestamp: boolean; - whether should be verify timestamps?
112
- * signerKey: string; - which field should be used to pick the signer
113
- * }} [{
114
- * tolerance,
115
- * enforceTimestamp,
116
- * signerKey,
117
- * }={
118
- * tolerance: 5,
119
- * enforceTimestamp: true,
120
- * signerKey: 'iss',
121
- * }]
122
- * @return {*} {boolean}
123
- */
124
- // eslint-disable-next-line require-await
88
+ * Verify a jwt token
89
+ *
90
+ * @param {string} token - the jwt token
91
+ * @param {string} signerPk - signer public key
92
+ * @param {{
93
+ * tolerance: number; - number of seconds to tolerant expire
94
+ * enforceTimestamp: boolean; - whether should be verify timestamps?
95
+ * signerKey: string; - which field should be used to pick the signer
96
+ * }} [{
97
+ * tolerance,
98
+ * enforceTimestamp,
99
+ * signerKey,
100
+ * }={
101
+ * tolerance: 5,
102
+ * enforceTimestamp: true,
103
+ * signerKey: 'iss',
104
+ * }]
105
+ * @return {*} {boolean}
106
+ */
125
107
  async function verify(token, signerPk, options) {
126
- const { tolerance, enforceTimestamp, signerKey } = Object.assign({
127
- tolerance: 5,
128
- enforceTimestamp: true,
129
- signerKey: 'iss',
130
- }, options);
131
- try {
132
- const [headerB64, bodyB64] = token.split('.');
133
- const { header, body, signature } = decode(token, false);
134
- if (!signature) {
135
- debug('verify.error.emptySig');
136
- return false;
137
- }
138
- if (!header.alg) {
139
- debug('verify.error.emptyAlg');
140
- return false;
141
- }
142
- const signerDid = body[signerKey];
143
- if (!signerDid) {
144
- debug('verify.error.emptySignerDid');
145
- return false;
146
- }
147
- if ((0, did_1.isFromPublicKey)(signerDid, signerPk) === false) {
148
- debug('verify.error.signerDidAndPkNotMatch');
149
- return false;
150
- }
151
- if (enforceTimestamp) {
152
- const now = Math.ceil(Date.now() / 1000);
153
- const exp = Number(body.exp) || 0;
154
- const iat = Number(body.iat) || 0;
155
- const nbf = Number(body.nbf) || 0;
156
- debug('verify.enforceTimestamp', { now, exp, iat, nbf });
157
- if (exp && exp + tolerance < now) {
158
- debug('verify.error.expired');
159
- return false;
160
- }
161
- if (iat && iat > now && iat - now > tolerance) {
162
- debug('verify.error.issuedAt');
163
- return false;
164
- }
165
- if (nbf && nbf > now && nbf - now > tolerance) {
166
- debug('verify.error.notBefore');
167
- return false;
168
- }
169
- }
170
- const signers = {
171
- secp256k1: (0, mcrypto_1.getSigner)(mcrypto_1.types.KeyType.SECP256K1),
172
- es256k: (0, mcrypto_1.getSigner)(mcrypto_1.types.KeyType.SECP256K1),
173
- ed25519: (0, mcrypto_1.getSigner)(mcrypto_1.types.KeyType.ED25519),
174
- ethereum: (0, mcrypto_1.getSigner)(mcrypto_1.types.KeyType.ETHEREUM),
175
- passkey: (0, mcrypto_1.getSigner)(mcrypto_1.types.KeyType.PASSKEY),
176
- };
177
- const alg = header.alg.toLowerCase();
178
- if (signers[alg]) {
179
- // @ts-ignore
180
- const msgHex = (0, util_1.toHex)(`${headerB64}.${bodyB64}`);
181
- // If we are using v1.1 protocol, the message should be hashed before verify
182
- const version = body.version && semver_1.default.coerce(body.version) ? semver_1.default.coerce(body.version).version : '';
183
- if (version && version === JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN) {
184
- return signers[alg].verify(hasher(msgHex), signature, signerPk);
185
- }
186
- return signers[alg].verify(msgHex, signature, signerPk);
187
- }
188
- debug('verify.error.crypto');
189
- return false;
190
- }
191
- catch (err) {
192
- debug('verify.error.exception');
193
- debug(err);
194
- return false;
195
- }
108
+ const { tolerance, enforceTimestamp, signerKey } = Object.assign({
109
+ tolerance: 5,
110
+ enforceTimestamp: true,
111
+ signerKey: "iss"
112
+ }, options);
113
+ try {
114
+ const [headerB64, bodyB64] = token.split(".");
115
+ const { header, body, signature } = decode(token, false);
116
+ if (!signature) {
117
+ debug$1("verify.error.emptySig");
118
+ return false;
119
+ }
120
+ if (!header.alg) {
121
+ debug$1("verify.error.emptyAlg");
122
+ return false;
123
+ }
124
+ const signerDid = body[signerKey];
125
+ if (!signerDid) {
126
+ debug$1("verify.error.emptySignerDid");
127
+ return false;
128
+ }
129
+ if ((0, _arcblock_did.isFromPublicKey)(signerDid, signerPk) === false) {
130
+ debug$1("verify.error.signerDidAndPkNotMatch");
131
+ return false;
132
+ }
133
+ if (enforceTimestamp) {
134
+ const now = Math.ceil(Date.now() / 1e3);
135
+ const exp = Number(body.exp) || 0;
136
+ const iat = Number(body.iat) || 0;
137
+ const nbf = Number(body.nbf) || 0;
138
+ debug$1("verify.enforceTimestamp", {
139
+ now,
140
+ exp,
141
+ iat,
142
+ nbf
143
+ });
144
+ if (exp && exp + tolerance < now) {
145
+ debug$1("verify.error.expired");
146
+ return false;
147
+ }
148
+ if (iat && iat > now && iat - now > tolerance) {
149
+ debug$1("verify.error.issuedAt");
150
+ return false;
151
+ }
152
+ if (nbf && nbf > now && nbf - now > tolerance) {
153
+ debug$1("verify.error.notBefore");
154
+ return false;
155
+ }
156
+ }
157
+ const signers = {
158
+ secp256k1: (0, _ocap_mcrypto.getSigner)(_ocap_mcrypto.types.KeyType.SECP256K1),
159
+ es256k: (0, _ocap_mcrypto.getSigner)(_ocap_mcrypto.types.KeyType.SECP256K1),
160
+ ed25519: (0, _ocap_mcrypto.getSigner)(_ocap_mcrypto.types.KeyType.ED25519),
161
+ ethereum: (0, _ocap_mcrypto.getSigner)(_ocap_mcrypto.types.KeyType.ETHEREUM),
162
+ passkey: (0, _ocap_mcrypto.getSigner)(_ocap_mcrypto.types.KeyType.PASSKEY)
163
+ };
164
+ const alg = header.alg.toLowerCase();
165
+ if (signers[alg]) {
166
+ const msgHex = (0, _ocap_util.toHex)(`${headerB64}.${bodyB64}`);
167
+ const version = body.version && semver.default.coerce(body.version) ? semver.default.coerce(body.version).version : "";
168
+ if (version && version === JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN) return signers[alg].verify(hasher(msgHex), signature, signerPk);
169
+ return signers[alg].verify(msgHex, signature, signerPk);
170
+ }
171
+ debug$1("verify.error.crypto");
172
+ return false;
173
+ } catch (err) {
174
+ debug$1("verify.error.exception");
175
+ debug$1(err);
176
+ return false;
177
+ }
196
178
  }
179
+
180
+ //#endregion
181
+ exports.decode = decode;
182
+ exports.sign = sign;
183
+ exports.signV2 = signV2;
184
+ exports.verify = verify;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@arcblock/jwt",
3
3
  "description": "JSON Web Token variant for arcblock DID solutions",
4
- "version": "1.27.16",
4
+ "version": "1.28.1",
5
5
  "author": {
6
6
  "name": "wangshijun",
7
7
  "email": "shijun@arcblock.io",
@@ -21,10 +21,10 @@
21
21
  "debug": "^4.3.6",
22
22
  "json-stable-stringify": "^1.0.1",
23
23
  "semver": "^7.6.3",
24
- "@arcblock/did": "1.27.16",
25
- "@ocap/mcrypto": "1.27.16",
26
- "@ocap/util": "1.27.16",
27
- "@ocap/wallet": "1.27.16"
24
+ "@arcblock/did": "1.28.1",
25
+ "@ocap/util": "1.28.1",
26
+ "@ocap/wallet": "1.28.1",
27
+ "@ocap/mcrypto": "1.28.1"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@arcblock/eslint-config-ts": "0.3.3",
@@ -35,6 +35,7 @@
35
35
  "eslint": "^8.57.0",
36
36
  "jest": "^29.7.0",
37
37
  "ts-jest": "^29.2.5",
38
+ "tsdown": "^0.18.4",
38
39
  "tslib": "^2.4.0",
39
40
  "typescript": "^5.6.2"
40
41
  },
@@ -46,8 +47,17 @@
46
47
  "nodejs"
47
48
  ],
48
49
  "license": "Apache-2.0",
50
+ "sideEffects": false,
49
51
  "main": "./lib/index.js",
50
- "types": "./lib/index.d.ts",
52
+ "module": "./esm/index.js",
53
+ "types": "./esm/index.d.ts",
54
+ "exports": {
55
+ ".": {
56
+ "types": "./esm/index.d.ts",
57
+ "import": "./esm/index.js",
58
+ "default": "./lib/index.js"
59
+ }
60
+ },
51
61
  "files": [
52
62
  "lib",
53
63
  "esm"
@@ -62,11 +72,7 @@
62
72
  "lint:fix": "eslint src tests --fix",
63
73
  "test": "jest --forceExit --detectOpenHandles",
64
74
  "coverage": "npm run test -- --coverage",
65
- "clean": "rm -fr lib esm",
66
- "prebuild": "npm run clean",
67
- "build:watch": "npm run build -- -w",
68
- "build:cjs": "tsc -p tsconfig.cjs.json",
69
- "build:esm": "tsc -p tsconfig.esm.json",
70
- "build": "npm run build:cjs && npm run build:esm"
75
+ "build": "tsdown",
76
+ "build:watch": "tsdown --watch"
71
77
  }
72
78
  }