@cubist-labs/cubesigner-sdk 0.1.26 → 0.1.77
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/README.md +94 -33
- package/dist/src/ethers/index.d.ts +25 -5
- package/dist/src/ethers/index.js +58 -16
- package/dist/src/fido.d.ts +76 -0
- package/dist/src/fido.js +148 -0
- package/dist/src/index.d.ts +148 -35
- package/dist/src/index.js +320 -53
- package/dist/src/key.d.ts +64 -8
- package/dist/src/key.js +91 -19
- package/dist/src/org.d.ts +98 -9
- package/dist/src/org.js +144 -29
- package/dist/src/paginator.d.ts +76 -0
- package/dist/src/paginator.js +99 -0
- package/dist/src/role.d.ts +20 -8
- package/dist/src/role.js +7 -5
- package/dist/src/schema.d.ts +2395 -393
- package/dist/src/schema.js +1 -1
- package/dist/src/session/cognito_manager.d.ts +59 -0
- package/dist/src/session/cognito_manager.js +111 -0
- package/dist/src/session/session_manager.d.ts +15 -0
- package/dist/src/session/session_manager.js +21 -2
- package/dist/src/session/session_storage.js +1 -1
- package/dist/src/session/signer_session_manager.d.ts +24 -12
- package/dist/src/session/signer_session_manager.js +45 -20
- package/dist/src/signer_session.d.ts +136 -38
- package/dist/src/signer_session.js +187 -80
- package/dist/src/util.d.ts +20 -0
- package/dist/src/util.js +31 -2
- package/package.json +12 -7
- package/src/ethers/index.ts +88 -16
- package/src/fido.ts +166 -0
- package/src/index.ts +366 -77
- package/src/key.ts +112 -16
- package/src/org.ts +200 -37
- package/src/paginator.ts +122 -0
- package/src/role.ts +24 -11
- package/src/schema.ts +2458 -449
- package/src/session/{management_session_manager.ts → cognito_manager.ts} +13 -15
- package/src/session/session_manager.ts +25 -1
- package/src/session/session_storage.ts +1 -1
- package/src/session/signer_session_manager.ts +57 -27
- package/src/signer_session.ts +266 -89
- package/src/util.ts +41 -0
- package/src/session/oidc_session_manager.ts +0 -193
package/dist/src/util.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/** JSON map type */
|
|
2
|
+
export interface JsonMap {
|
|
3
|
+
[member: string]: string | number | boolean | null | JsonArray | JsonMap;
|
|
4
|
+
}
|
|
5
|
+
/** JSON array type */
|
|
6
|
+
export type JsonArray = Array<string | number | boolean | null | JsonArray | JsonMap>;
|
|
1
7
|
/**
|
|
2
8
|
* Directory where CubeSigner stores config files.
|
|
3
9
|
* @return {string} Config dir
|
|
@@ -32,4 +38,18 @@ export declare class ErrResponse extends Error {
|
|
|
32
38
|
* @internal
|
|
33
39
|
*/
|
|
34
40
|
export declare function assertOk<D, T>(resp: ResponseType<D, T>, description?: string): D;
|
|
41
|
+
/**
|
|
42
|
+
* Browser-friendly helper for decoding a 'base64url'-encoded string into a byte array.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} b64url The 'base64url'-encoded string to decode
|
|
45
|
+
* @return {Uint8Array} Decoded byte array
|
|
46
|
+
*/
|
|
47
|
+
export declare function decodeBase64Url(b64url: string): Uint8Array;
|
|
48
|
+
/**
|
|
49
|
+
* Browser-friendly helper for encoding a byte array into a 'base64url`-encoded string.
|
|
50
|
+
*
|
|
51
|
+
* @param {Iterable<number>} buffer The byte array to encode
|
|
52
|
+
* @return {string} The 'base64url' encoding of the byte array.
|
|
53
|
+
*/
|
|
54
|
+
export declare function encodeToBase64Url(buffer: Iterable<number>): string;
|
|
35
55
|
export {};
|
package/dist/src/util.js
CHANGED
|
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.assertOk = exports.ErrResponse = exports.configDir = void 0;
|
|
26
|
+
exports.encodeToBase64Url = exports.decodeBase64Url = exports.assertOk = exports.ErrResponse = exports.configDir = void 0;
|
|
27
27
|
const path = __importStar(require("path"));
|
|
28
28
|
/**
|
|
29
29
|
* Directory where CubeSigner stores config files.
|
|
@@ -72,4 +72,33 @@ function assertOk(resp, description) {
|
|
|
72
72
|
return resp.data;
|
|
73
73
|
}
|
|
74
74
|
exports.assertOk = assertOk;
|
|
75
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Browser-friendly helper for decoding a 'base64url'-encoded string into a byte array.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} b64url The 'base64url'-encoded string to decode
|
|
79
|
+
* @return {Uint8Array} Decoded byte array
|
|
80
|
+
*/
|
|
81
|
+
function decodeBase64Url(b64url) {
|
|
82
|
+
const b64 = b64url.replace(/-/g, "+").replace(/_/g, "/").replace(/=*$/g, "");
|
|
83
|
+
// NOTE: there is no "base64url" encoding in the "buffer" module for the browser (unlike in node.js)
|
|
84
|
+
return typeof Buffer === "function"
|
|
85
|
+
? Buffer.from(b64, "base64")
|
|
86
|
+
: Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
87
|
+
}
|
|
88
|
+
exports.decodeBase64Url = decodeBase64Url;
|
|
89
|
+
/**
|
|
90
|
+
* Browser-friendly helper for encoding a byte array into a 'base64url`-encoded string.
|
|
91
|
+
*
|
|
92
|
+
* @param {Iterable<number>} buffer The byte array to encode
|
|
93
|
+
* @return {string} The 'base64url' encoding of the byte array.
|
|
94
|
+
*/
|
|
95
|
+
function encodeToBase64Url(buffer) {
|
|
96
|
+
const bytes = new Uint8Array(buffer);
|
|
97
|
+
// NOTE: there is no "base64url" encoding in the "buffer" module for the browser (unlike in node.js)
|
|
98
|
+
const b64 = typeof Buffer === "function"
|
|
99
|
+
? Buffer.from(bytes).toString("base64")
|
|
100
|
+
: btoa(bytes.reduce((s, b) => s + String.fromCharCode(b), ""));
|
|
101
|
+
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=*$/g, "");
|
|
102
|
+
}
|
|
103
|
+
exports.encodeToBase64Url = encodeToBase64Url;
|
|
104
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsMkNBQTZCO0FBVTdCOzs7R0FHRztBQUNILFNBQWdCLFNBQVM7SUFDdkIsTUFBTSxTQUFTLEdBQ2IsT0FBTyxDQUFDLFFBQVEsS0FBSyxRQUFRO1FBQzNCLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSw4QkFBOEI7UUFDbkQsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLFVBQVUsQ0FBQztJQUNwQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDO0FBQzVDLENBQUM7QUFORCw4QkFNQztBQUlEOztHQUVHO0FBQ0gsTUFBYSxXQUFZLFNBQVEsS0FBSztJQVFwQzs7O09BR0c7SUFDSCxZQUFZLElBQTBCO1FBQ3BDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDcEIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDNUIsQ0FBQztDQUNGO0FBaEJELGtDQWdCQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLFFBQVEsQ0FBTyxJQUF3QixFQUFFLFdBQW9CO0lBQzNFLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRTtRQUNkLE1BQU0sSUFBSSxXQUFXLENBQUM7WUFDcEIsV0FBVztZQUNYLE9BQU8sRUFBRyxJQUFJLENBQUMsS0FBYSxDQUFDLE9BQU87WUFDcEMsVUFBVSxFQUFFLElBQUksQ0FBQyxRQUFRLEVBQUUsVUFBVTtZQUNyQyxNQUFNLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxNQUFNO1NBQzlCLENBQUMsQ0FBQztLQUNKO0lBQ0QsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFNBQVMsRUFBRTtRQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7S0FDL0M7SUFDRCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUM7QUFDbkIsQ0FBQztBQWJELDRCQWFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixlQUFlLENBQUMsTUFBYztJQUM1QyxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFN0Usb0dBQW9HO0lBQ3BHLE9BQU8sT0FBTyxNQUFNLEtBQUssVUFBVTtRQUNqQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDO1FBQzVCLENBQUMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3pELENBQUM7QUFQRCwwQ0FPQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsaUJBQWlCLENBQUMsTUFBd0I7SUFDeEQsTUFBTSxLQUFLLEdBQUcsSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFckMsb0dBQW9HO0lBQ3BHLE1BQU0sR0FBRyxHQUNQLE9BQU8sTUFBTSxLQUFLLFVBQVU7UUFDMUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztRQUN2QyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRW5FLE9BQU8sR0FBRyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ3pFLENBQUM7QUFWRCw4Q0FVQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcblxuLyoqIEpTT04gbWFwIHR5cGUgKi9cbmV4cG9ydCBpbnRlcmZhY2UgSnNvbk1hcCB7XG4gIFttZW1iZXI6IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBudWxsIHwgSnNvbkFycmF5IHwgSnNvbk1hcDtcbn1cblxuLyoqIEpTT04gYXJyYXkgdHlwZSAqL1xuZXhwb3J0IHR5cGUgSnNvbkFycmF5ID0gQXJyYXk8c3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IG51bGwgfCBKc29uQXJyYXkgfCBKc29uTWFwPjtcblxuLyoqXG4gKiBEaXJlY3Rvcnkgd2hlcmUgQ3ViZVNpZ25lciBzdG9yZXMgY29uZmlnIGZpbGVzLlxuICogQHJldHVybiB7c3RyaW5nfSBDb25maWcgZGlyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25maWdEaXIoKTogc3RyaW5nIHtcbiAgY29uc3QgY29uZmlnRGlyID1cbiAgICBwcm9jZXNzLnBsYXRmb3JtID09PSBcImRhcndpblwiXG4gICAgICA/IGAke3Byb2Nlc3MuZW52LkhPTUV9L0xpYnJhcnkvQXBwbGljYXRpb24gU3VwcG9ydGBcbiAgICAgIDogYCR7cHJvY2Vzcy5lbnYuSE9NRX0vLmNvbmZpZ2A7XG4gIHJldHVybiBwYXRoLmpvaW4oY29uZmlnRGlyLCBcImN1YmVzaWduZXJcIik7XG59XG5cbnR5cGUgUmVzcG9uc2VUeXBlPEQsIFQ+ID0geyBkYXRhPzogRDsgZXJyb3I/OiBUOyByZXNwb25zZT86IFJlc3BvbnNlIH07XG5cbi8qKlxuICogRXJyb3IgcmVzcG9uc2UgdHlwZSwgdGhyb3duIG9uIG5vbi1zdWNjZXNzZnVsIHJlc3BvbnNlcy5cbiAqL1xuZXhwb3J0IGNsYXNzIEVyclJlc3BvbnNlIGV4dGVuZHMgRXJyb3Ige1xuICAvKiogRGVzY3JpcHRpb24gKi9cbiAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIC8qKiBIVFRQIHN0YXR1cyBjb2RlIHRleHQgKGRlcml2ZWQgZnJvbSBgdGhpcy5zdGF0dXNgKSAqL1xuICByZWFkb25seSBzdGF0dXNUZXh0Pzogc3RyaW5nO1xuICAvKiogSFRUUCBzdGF0dXMgY29kZSAqL1xuICByZWFkb25seSBzdGF0dXM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7UGFydGlhbDxFcnJSZXNwb25zZT59IGluaXQgSW5pdGlhbGl6ZXJcbiAgICovXG4gIGNvbnN0cnVjdG9yKGluaXQ6IFBhcnRpYWw8RXJyUmVzcG9uc2U+KSB7XG4gICAgc3VwZXIoaW5pdC5tZXNzYWdlKTtcbiAgICBPYmplY3QuYXNzaWduKHRoaXMsIGluaXQpO1xuICB9XG59XG5cbi8qKlxuICogVGhyb3cgaWYgb24gZXJyb3IgcmVzcG9uc2UuIE90aGVyd2lzZSwgcmV0dXJuIHRoZSByZXNwb25zZSBkYXRhLlxuICogQHBhcmFtIHtSZXNwb25zZVR5cGV9IHJlc3AgVGhlIHJlc3BvbnNlIHRvIGNoZWNrXG4gKiBAcGFyYW0ge3N0cmluZ30gZGVzY3JpcHRpb24gRGVzY3JpcHRpb24gdG8gaW5jbHVkZSBpbiB0aGUgdGhyb3duIGVycm9yXG4gKiBAcmV0dXJuIHtEfSBUaGUgcmVzcG9uc2UgZGF0YS5cbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0T2s8RCwgVD4ocmVzcDogUmVzcG9uc2VUeXBlPEQsIFQ+LCBkZXNjcmlwdGlvbj86IHN0cmluZyk6IEQge1xuICBpZiAocmVzcC5lcnJvcikge1xuICAgIHRocm93IG5ldyBFcnJSZXNwb25zZSh7XG4gICAgICBkZXNjcmlwdGlvbixcbiAgICAgIG1lc3NhZ2U6IChyZXNwLmVycm9yIGFzIGFueSkubWVzc2FnZSwgLy8gZXNsaW50LWRpc2FibGUtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICBzdGF0dXNUZXh0OiByZXNwLnJlc3BvbnNlPy5zdGF0dXNUZXh0LFxuICAgICAgc3RhdHVzOiByZXNwLnJlc3BvbnNlPy5zdGF0dXMsXG4gICAgfSk7XG4gIH1cbiAgaWYgKHJlc3AuZGF0YSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiUmVzcG9uc2UgZGF0YSBpcyB1bmRlZmluZWRcIik7XG4gIH1cbiAgcmV0dXJuIHJlc3AuZGF0YTtcbn1cblxuLyoqXG4gKiBCcm93c2VyLWZyaWVuZGx5IGhlbHBlciBmb3IgZGVjb2RpbmcgYSAnYmFzZTY0dXJsJy1lbmNvZGVkIHN0cmluZyBpbnRvIGEgYnl0ZSBhcnJheS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gYjY0dXJsIFRoZSAnYmFzZTY0dXJsJy1lbmNvZGVkIHN0cmluZyB0byBkZWNvZGVcbiAqIEByZXR1cm4ge1VpbnQ4QXJyYXl9IERlY29kZWQgYnl0ZSBhcnJheVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlQmFzZTY0VXJsKGI2NHVybDogc3RyaW5nKTogVWludDhBcnJheSB7XG4gIGNvbnN0IGI2NCA9IGI2NHVybC5yZXBsYWNlKC8tL2csIFwiK1wiKS5yZXBsYWNlKC9fL2csIFwiL1wiKS5yZXBsYWNlKC89KiQvZywgXCJcIik7XG5cbiAgLy8gTk9URTogdGhlcmUgaXMgbm8gXCJiYXNlNjR1cmxcIiBlbmNvZGluZyBpbiB0aGUgXCJidWZmZXJcIiBtb2R1bGUgZm9yIHRoZSBicm93c2VyICh1bmxpa2UgaW4gbm9kZS5qcylcbiAgcmV0dXJuIHR5cGVvZiBCdWZmZXIgPT09IFwiZnVuY3Rpb25cIlxuICAgID8gQnVmZmVyLmZyb20oYjY0LCBcImJhc2U2NFwiKVxuICAgIDogVWludDhBcnJheS5mcm9tKGF0b2IoYjY0KSwgKGMpID0+IGMuY2hhckNvZGVBdCgwKSk7XG59XG5cbi8qKlxuICogQnJvd3Nlci1mcmllbmRseSBoZWxwZXIgZm9yIGVuY29kaW5nIGEgYnl0ZSBhcnJheSBpbnRvIGEgJ2Jhc2U2NHVybGAtZW5jb2RlZCBzdHJpbmcuXG4gKlxuICogQHBhcmFtIHtJdGVyYWJsZTxudW1iZXI+fSBidWZmZXIgVGhlIGJ5dGUgYXJyYXkgdG8gZW5jb2RlXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSAnYmFzZTY0dXJsJyBlbmNvZGluZyBvZiB0aGUgYnl0ZSBhcnJheS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZVRvQmFzZTY0VXJsKGJ1ZmZlcjogSXRlcmFibGU8bnVtYmVyPik6IHN0cmluZyB7XG4gIGNvbnN0IGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyKTtcblxuICAvLyBOT1RFOiB0aGVyZSBpcyBubyBcImJhc2U2NHVybFwiIGVuY29kaW5nIGluIHRoZSBcImJ1ZmZlclwiIG1vZHVsZSBmb3IgdGhlIGJyb3dzZXIgKHVubGlrZSBpbiBub2RlLmpzKVxuICBjb25zdCBiNjQgPVxuICAgIHR5cGVvZiBCdWZmZXIgPT09IFwiZnVuY3Rpb25cIlxuICAgICAgPyBCdWZmZXIuZnJvbShieXRlcykudG9TdHJpbmcoXCJiYXNlNjRcIilcbiAgICAgIDogYnRvYShieXRlcy5yZWR1Y2UoKHMsIGIpID0+IHMgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKGIpLCBcIlwiKSk7XG5cbiAgcmV0dXJuIGI2NC5yZXBsYWNlKC9cXCsvZywgXCItXCIpLnJlcGxhY2UoL1xcLy9nLCBcIl9cIikucmVwbGFjZSgvPSokL2csIFwiXCIpO1xufVxuIl19
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cubist-labs/cubesigner-sdk",
|
|
3
3
|
"author": "Cubist, Inc.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.77",
|
|
5
5
|
"description": "CubeSigner TypeScript SDK",
|
|
6
6
|
"homepage": "https://github.com/cubist-labs/CubeSigner-TypeScript-SDK",
|
|
7
7
|
"bugs": "https://github.com/cubist-labs/CubeSigner-TypeScript-SDK/issues",
|
|
@@ -28,34 +28,39 @@
|
|
|
28
28
|
"gen-schema": "npx openapi-typescript ./spec/openapi.json --output ./src/schema.ts"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"ethers": "
|
|
31
|
+
"ethers": "6.7.1",
|
|
32
32
|
"openapi-fetch": "0.6.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/chai": "^4.3.5",
|
|
36
|
+
"@types/chai-as-promised": "^7.1.8",
|
|
36
37
|
"@types/jest": "^29.5.2",
|
|
37
|
-
"@types/node": "^20.
|
|
38
|
+
"@types/node": "^20.9.0",
|
|
38
39
|
"@types/node-fetch": "^2.6.4",
|
|
39
40
|
"@types/tmp": "^0.2.3",
|
|
40
41
|
"@typescript-eslint/eslint-plugin": "^5.60.1",
|
|
41
42
|
"chai": "^4.3.7",
|
|
43
|
+
"chai-as-promised": "^7.1.1",
|
|
44
|
+
"dotenv": "^16.3.1",
|
|
42
45
|
"eslint": "^8.43.0",
|
|
43
46
|
"eslint-config-google": "^0.14.0",
|
|
44
47
|
"eslint-config-prettier": "^8.8.0",
|
|
45
48
|
"jest": "^29.5.0",
|
|
46
|
-
"openapi-typescript": "^6.
|
|
49
|
+
"openapi-typescript": "^6.7.0",
|
|
47
50
|
"otplib": "^12.0.1",
|
|
48
|
-
"prettier": "3.0.
|
|
51
|
+
"prettier": "3.0.3",
|
|
49
52
|
"tmp": "^0.2.1",
|
|
50
53
|
"ts-jest": "^29.1.0",
|
|
51
54
|
"ts-node": "^10.9.1",
|
|
52
|
-
"typedoc": "^0.24.8",
|
|
53
55
|
"typescript": "^5.1.6"
|
|
54
56
|
},
|
|
55
57
|
"optionalDependencies": {
|
|
56
|
-
"@aws-sdk/client-cognito-identity-provider": "^3.
|
|
58
|
+
"@aws-sdk/client-cognito-identity-provider": "^3.445.0"
|
|
57
59
|
},
|
|
58
60
|
"prettier": {
|
|
59
61
|
"printWidth": 100
|
|
62
|
+
},
|
|
63
|
+
"engines": {
|
|
64
|
+
"node": ">=18.0.0"
|
|
60
65
|
}
|
|
61
66
|
}
|
package/src/ethers/index.ts
CHANGED
|
@@ -7,8 +7,33 @@ import {
|
|
|
7
7
|
getBytes,
|
|
8
8
|
toBeHex,
|
|
9
9
|
} from "ethers";
|
|
10
|
-
import {
|
|
11
|
-
|
|
10
|
+
import {
|
|
11
|
+
BlobSignRequest,
|
|
12
|
+
EvmSignRequest,
|
|
13
|
+
MfaRequestInfo,
|
|
14
|
+
SignerSession,
|
|
15
|
+
SignResponse,
|
|
16
|
+
} from "../signer_session";
|
|
17
|
+
import { KeyInfo } from "../key";
|
|
18
|
+
import { CubeSigner } from "..";
|
|
19
|
+
|
|
20
|
+
/** Options for the signer */
|
|
21
|
+
interface SignerOptions {
|
|
22
|
+
/** Optional provider to use */
|
|
23
|
+
provider?: null | ethers.Provider;
|
|
24
|
+
/**
|
|
25
|
+
* The function to call when MFA information is retrieved. If this callback
|
|
26
|
+
* throws, no transaction is broadcast.
|
|
27
|
+
*/
|
|
28
|
+
onMfaPoll?: (arg0: MfaRequestInfo) => void;
|
|
29
|
+
/**
|
|
30
|
+
* The amount of time (in milliseconds) to wait between checks for MFA
|
|
31
|
+
* updates. Default is 1000ms
|
|
32
|
+
*/
|
|
33
|
+
mfaPollIntervalMs?: number;
|
|
34
|
+
/** Optional management session. Used to check for MFA updates */
|
|
35
|
+
managementSession?: CubeSigner;
|
|
36
|
+
}
|
|
12
37
|
|
|
13
38
|
/**
|
|
14
39
|
* A ethers.js Signer using CubeSigner
|
|
@@ -18,20 +43,40 @@ export class Signer extends ethers.AbstractSigner {
|
|
|
18
43
|
readonly #address: string;
|
|
19
44
|
|
|
20
45
|
/** The key to use for signing */
|
|
21
|
-
#key?:
|
|
46
|
+
#key?: KeyInfo;
|
|
22
47
|
|
|
23
48
|
/** The underlying session */
|
|
24
49
|
readonly #signerSession: SignerSession;
|
|
25
50
|
|
|
51
|
+
/**
|
|
52
|
+
* The function to call when MFA information is retrieved. If this callback
|
|
53
|
+
* throws, no transaction is broadcast.
|
|
54
|
+
*/
|
|
55
|
+
readonly #onMfaPoll: (arg0: MfaRequestInfo) => void;
|
|
56
|
+
|
|
57
|
+
/** The amount of time to wait between checks for MFA updates */
|
|
58
|
+
readonly #mfaPollIntervalMs: number;
|
|
59
|
+
|
|
60
|
+
/** Optional management session, used for MFA flows */
|
|
61
|
+
readonly #managementSession?: CubeSigner;
|
|
62
|
+
|
|
26
63
|
/** Create new Signer instance
|
|
27
|
-
* @param {string} address The address of the account to use.
|
|
64
|
+
* @param {KeyInfo | string} address The key or the eth address of the account to use.
|
|
28
65
|
* @param {SignerSession} signerSession The underlying Signer session.
|
|
29
|
-
* @param {
|
|
66
|
+
* @param {SignerOptions} options The options to use for the Signer instance
|
|
30
67
|
*/
|
|
31
|
-
constructor(address: string, signerSession: SignerSession,
|
|
32
|
-
super(provider);
|
|
33
|
-
|
|
68
|
+
constructor(address: KeyInfo | string, signerSession: SignerSession, options?: SignerOptions) {
|
|
69
|
+
super(options?.provider);
|
|
70
|
+
if (typeof address === "string") {
|
|
71
|
+
this.#address = address;
|
|
72
|
+
} else {
|
|
73
|
+
this.#address = address.materialId;
|
|
74
|
+
this.#key = address as KeyInfo;
|
|
75
|
+
}
|
|
34
76
|
this.#signerSession = signerSession;
|
|
77
|
+
this.#onMfaPoll = options?.onMfaPoll ?? ((/* _mfaInfo: MfaRequestInfo */) => {}); // eslint-disable-line @typescript-eslint/no-empty-function
|
|
78
|
+
this.#mfaPollIntervalMs = options?.mfaPollIntervalMs ?? 1000;
|
|
79
|
+
this.#managementSession = options?.managementSession;
|
|
35
80
|
}
|
|
36
81
|
|
|
37
82
|
/** Resolves to the signer address. */
|
|
@@ -45,11 +90,11 @@ export class Signer extends ethers.AbstractSigner {
|
|
|
45
90
|
* @return {Signer} The signer connected to signer.
|
|
46
91
|
*/
|
|
47
92
|
connect(provider: null | ethers.Provider): Signer {
|
|
48
|
-
return new Signer(this.#address, this.#signerSession, provider);
|
|
93
|
+
return new Signer(this.#address, this.#signerSession, { provider });
|
|
49
94
|
}
|
|
50
95
|
|
|
51
96
|
/**
|
|
52
|
-
* Signs a transaction. This populates the transaction type to `0x02` (EIP-1559) unless set.
|
|
97
|
+
* Signs a transaction. This populates the transaction type to `0x02` (EIP-1559) unless set. This method will block if the key requires MFA approval.
|
|
53
98
|
* @param {ethers.TransactionRequest} tx The transaction to sign.
|
|
54
99
|
* @return {Promise<string>} Hex-encoded RLP encoding of the transaction and its signature.
|
|
55
100
|
*/
|
|
@@ -75,8 +120,10 @@ export class Signer extends ethers.AbstractSigner {
|
|
|
75
120
|
chain_id: Number(chainId),
|
|
76
121
|
tx: rpcTx,
|
|
77
122
|
};
|
|
78
|
-
|
|
79
|
-
|
|
123
|
+
|
|
124
|
+
const res = await this.#signerSession.signEvm(this.#address, req);
|
|
125
|
+
const data = await this.#handleMfa(res);
|
|
126
|
+
return data.rlp_signed_tx;
|
|
80
127
|
}
|
|
81
128
|
|
|
82
129
|
/** Signs arbitrary messages. This uses ethers.js's [hashMessage](https://docs.ethers.org/v6/api/hashing/#hashMessage)
|
|
@@ -118,14 +165,39 @@ export class Signer extends ethers.AbstractSigner {
|
|
|
118
165
|
};
|
|
119
166
|
// Get the key corresponding to this address
|
|
120
167
|
if (this.#key === undefined) {
|
|
121
|
-
const key = (await this.#signerSession.keys()).find((k) => k.
|
|
168
|
+
const key = (await this.#signerSession.keys()).find((k) => k.material_id === this.#address);
|
|
122
169
|
if (key === undefined) {
|
|
123
170
|
throw new Error(`Cannot access key '${this.#address}'`);
|
|
124
171
|
}
|
|
125
172
|
this.#key = key;
|
|
126
173
|
}
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
174
|
+
|
|
175
|
+
const res = await this.#signerSession.signBlob(this.#key.key_id, blobReq);
|
|
176
|
+
const data = await this.#handleMfa(res);
|
|
177
|
+
return data.signature;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* If the sign request requires MFA, this method waits for approvals
|
|
182
|
+
*
|
|
183
|
+
* @param {SignResponse<U>} res The response of a sign request
|
|
184
|
+
* @return {Promise<U>} The sign data after MFA approvals
|
|
185
|
+
*/
|
|
186
|
+
async #handleMfa<U>(res: SignResponse<U>): Promise<U> {
|
|
187
|
+
while (res.requiresMfa()) {
|
|
188
|
+
await new Promise((resolve) => setTimeout(resolve, this.#mfaPollIntervalMs));
|
|
189
|
+
|
|
190
|
+
const mfaId = res.mfaId();
|
|
191
|
+
const mfaInfo = await this.#signerSession.getMfaInfo(this.#managementSession!, mfaId);
|
|
192
|
+
this.#onMfaPoll(mfaInfo);
|
|
193
|
+
if (mfaInfo.receipt) {
|
|
194
|
+
res = await res.signWithMfaApproval({
|
|
195
|
+
mfaId,
|
|
196
|
+
mfaOrgId: this.#signerSession.orgId,
|
|
197
|
+
mfaConf: mfaInfo.receipt.confirmation,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return res.data();
|
|
130
202
|
}
|
|
131
203
|
}
|
package/src/fido.ts
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
|
|
3
|
+
import { CubeSigner, MfaRequestInfo, SignerSession } from ".";
|
|
4
|
+
import { components } from "./schema";
|
|
5
|
+
import { decodeBase64Url, encodeToBase64Url } from "./util";
|
|
6
|
+
|
|
7
|
+
export type ApiAddFidoChallenge =
|
|
8
|
+
components["responses"]["FidoCreateChallengeResponse"]["content"]["application/json"];
|
|
9
|
+
|
|
10
|
+
export type ApiMfaFidoChallenge =
|
|
11
|
+
components["responses"]["FidoAssertChallenge"]["content"]["application/json"];
|
|
12
|
+
|
|
13
|
+
export type PublicKeyCredentialCreationOptions =
|
|
14
|
+
components["schemas"]["PublicKeyCredentialCreationOptions"];
|
|
15
|
+
export type PublicKeyCredentialRequestOptions =
|
|
16
|
+
components["schemas"]["PublicKeyCredentialRequestOptions"];
|
|
17
|
+
export type PublicKeyCredentialParameters = components["schemas"]["PublicKeyCredentialParameters"];
|
|
18
|
+
export type PublicKeyCredentialDescriptor = components["schemas"]["PublicKeyCredentialDescriptor"];
|
|
19
|
+
export type AuthenticatorSelectionCriteria =
|
|
20
|
+
components["schemas"]["AuthenticatorSelectionCriteria"];
|
|
21
|
+
export type PublicKeyCredentialUserEntity = components["schemas"]["PublicKeyCredentialUserEntity"];
|
|
22
|
+
export type PublicKeyCredential = components["schemas"]["PublicKeyCredential"];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Returned after creating a request to add a new FIDO device.
|
|
26
|
+
* Provides some helper methods for answering this challenge.
|
|
27
|
+
*/
|
|
28
|
+
export class AddFidoChallenge {
|
|
29
|
+
readonly #cs: CubeSigner;
|
|
30
|
+
readonly challengeId: string;
|
|
31
|
+
readonly options: any;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Constructor
|
|
35
|
+
* @param {CubeSigner} cs CubeSigner instance used to request to add a FIDO device
|
|
36
|
+
* @param {ApiAddFidoChallenge} challenge The challenge returned by the remote end.
|
|
37
|
+
*/
|
|
38
|
+
constructor(cs: CubeSigner, challenge: ApiAddFidoChallenge) {
|
|
39
|
+
this.#cs = cs;
|
|
40
|
+
this.challengeId = challenge.challenge_id;
|
|
41
|
+
|
|
42
|
+
// fix options returned from the server: rename fields and decode base64 fields to uint8[]
|
|
43
|
+
this.options = {
|
|
44
|
+
...challenge.options,
|
|
45
|
+
challenge: decodeBase64Url(challenge.options.challenge),
|
|
46
|
+
};
|
|
47
|
+
this.options.pubKeyCredParams ??= challenge.options.pub_key_cred_params;
|
|
48
|
+
this.options.excludeCredentials ??= challenge.options.exclude_credentials;
|
|
49
|
+
this.options.authenticatorSelection ??= challenge.options.authenticator_selection;
|
|
50
|
+
delete this.options.pub_key_cred_params;
|
|
51
|
+
delete this.options.exclude_credentials;
|
|
52
|
+
delete this.options.authenticator_selection;
|
|
53
|
+
|
|
54
|
+
if (challenge.options.user) {
|
|
55
|
+
this.options.user.id = decodeBase64Url(challenge.options.user.id);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
for (const credential of this.options.excludeCredentials ?? []) {
|
|
59
|
+
credential.id = decodeBase64Url(credential.id);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Answers this challenge by using the `CredentialsContainer` API to create a credential
|
|
65
|
+
* based on the the public key credential creation options from this challenge.
|
|
66
|
+
*/
|
|
67
|
+
async createCredentialAndAnswer() {
|
|
68
|
+
const cred = await navigator.credentials.create({ publicKey: this.options });
|
|
69
|
+
await this.answer(cred);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Answers this challenge using a given credential `cred`;
|
|
74
|
+
* the credential should be obtained by calling
|
|
75
|
+
*
|
|
76
|
+
* ```
|
|
77
|
+
* const cred = await navigator.credentials.create({ publicKey: this.options });
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @param {any} cred Credential created by calling the `CredentialContainer`'s `create` method
|
|
81
|
+
* based on the public key creation options from this challenge.
|
|
82
|
+
*/
|
|
83
|
+
async answer(cred: any) {
|
|
84
|
+
const answer = <PublicKeyCredential>{
|
|
85
|
+
id: cred.id,
|
|
86
|
+
response: {
|
|
87
|
+
clientDataJSON: encodeToBase64Url(cred.response.clientDataJSON),
|
|
88
|
+
attestationObject: encodeToBase64Url(cred.response.attestationObject),
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
await this.#cs.addFidoComplete(this.challengeId, answer);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Returned after initiating MFA approval using FIDO.
|
|
97
|
+
* Provides some helper methods for answering this challenge.
|
|
98
|
+
*/
|
|
99
|
+
export class MfaFidoChallenge {
|
|
100
|
+
readonly #ss: SignerSession;
|
|
101
|
+
readonly mfaId: string;
|
|
102
|
+
readonly challengeId: string;
|
|
103
|
+
readonly options: any;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @param {SignerSession} ss The session used to initiate MFA approval using FIDO
|
|
107
|
+
* @param {string} mfaId The MFA request id.
|
|
108
|
+
* @param {ApiMfaFidoChallenge} challenge The challenge returned by the remote end
|
|
109
|
+
*/
|
|
110
|
+
constructor(ss: SignerSession, mfaId: string, challenge: ApiMfaFidoChallenge) {
|
|
111
|
+
this.#ss = ss;
|
|
112
|
+
this.mfaId = mfaId;
|
|
113
|
+
this.challengeId = challenge.challenge_id;
|
|
114
|
+
|
|
115
|
+
// fix options returned from the server: rename fields and decode base64 fields into uint8[]
|
|
116
|
+
this.options = {
|
|
117
|
+
...challenge.options,
|
|
118
|
+
challenge: decodeBase64Url(challenge.options.challenge),
|
|
119
|
+
};
|
|
120
|
+
this.options.rpId ??= challenge.options.rp_id;
|
|
121
|
+
this.options.allowCredentials ??= challenge.options.allow_credentials;
|
|
122
|
+
this.options.userVerification ??= challenge.options.user_verification;
|
|
123
|
+
delete this.options.rp_id;
|
|
124
|
+
delete this.options.allow_credentials;
|
|
125
|
+
delete this.options.user_verification;
|
|
126
|
+
|
|
127
|
+
for (const credential of this.options.allowCredentials ?? []) {
|
|
128
|
+
credential.id = decodeBase64Url(credential.id);
|
|
129
|
+
if (credential.transports === null) {
|
|
130
|
+
delete credential.transports;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Answers this challenge by using the `CredentialsContainer` API to get a credential
|
|
137
|
+
* based on the the public key credential request options from this challenge.
|
|
138
|
+
*/
|
|
139
|
+
async createCredentialAndAnswer(): Promise<MfaRequestInfo> {
|
|
140
|
+
const cred = await navigator.credentials.get({ publicKey: this.options });
|
|
141
|
+
return await this.answer(cred);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Answers this challenge using a given credential `cred`.
|
|
146
|
+
* To obtain this credential, for example, call
|
|
147
|
+
*
|
|
148
|
+
* ```
|
|
149
|
+
* const cred = await navigator.credentials.get({ publicKey: this.options });
|
|
150
|
+
* ```
|
|
151
|
+
*
|
|
152
|
+
* @param {any} cred Credential created by calling the `CredentialContainer`'s `get` method
|
|
153
|
+
* based on the public key credential request options from this challenge.
|
|
154
|
+
*/
|
|
155
|
+
async answer(cred: any): Promise<MfaRequestInfo> {
|
|
156
|
+
const answer = <PublicKeyCredential>{
|
|
157
|
+
id: cred.id,
|
|
158
|
+
response: {
|
|
159
|
+
clientDataJSON: encodeToBase64Url(cred.response.clientDataJSON),
|
|
160
|
+
authenticatorData: encodeToBase64Url(cred.response.authenticatorData),
|
|
161
|
+
signature: encodeToBase64Url(cred.response.signature),
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
return await this.#ss.fidoApproveComplete(this.mfaId, this.challengeId, answer);
|
|
165
|
+
}
|
|
166
|
+
}
|