@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.
Files changed (44) hide show
  1. package/README.md +94 -33
  2. package/dist/src/ethers/index.d.ts +25 -5
  3. package/dist/src/ethers/index.js +58 -16
  4. package/dist/src/fido.d.ts +76 -0
  5. package/dist/src/fido.js +148 -0
  6. package/dist/src/index.d.ts +148 -35
  7. package/dist/src/index.js +320 -53
  8. package/dist/src/key.d.ts +64 -8
  9. package/dist/src/key.js +91 -19
  10. package/dist/src/org.d.ts +98 -9
  11. package/dist/src/org.js +144 -29
  12. package/dist/src/paginator.d.ts +76 -0
  13. package/dist/src/paginator.js +99 -0
  14. package/dist/src/role.d.ts +20 -8
  15. package/dist/src/role.js +7 -5
  16. package/dist/src/schema.d.ts +2395 -393
  17. package/dist/src/schema.js +1 -1
  18. package/dist/src/session/cognito_manager.d.ts +59 -0
  19. package/dist/src/session/cognito_manager.js +111 -0
  20. package/dist/src/session/session_manager.d.ts +15 -0
  21. package/dist/src/session/session_manager.js +21 -2
  22. package/dist/src/session/session_storage.js +1 -1
  23. package/dist/src/session/signer_session_manager.d.ts +24 -12
  24. package/dist/src/session/signer_session_manager.js +45 -20
  25. package/dist/src/signer_session.d.ts +136 -38
  26. package/dist/src/signer_session.js +187 -80
  27. package/dist/src/util.d.ts +20 -0
  28. package/dist/src/util.js +31 -2
  29. package/package.json +12 -7
  30. package/src/ethers/index.ts +88 -16
  31. package/src/fido.ts +166 -0
  32. package/src/index.ts +366 -77
  33. package/src/key.ts +112 -16
  34. package/src/org.ts +200 -37
  35. package/src/paginator.ts +122 -0
  36. package/src/role.ts +24 -11
  37. package/src/schema.ts +2458 -449
  38. package/src/session/{management_session_manager.ts → cognito_manager.ts} +13 -15
  39. package/src/session/session_manager.ts +25 -1
  40. package/src/session/session_storage.ts +1 -1
  41. package/src/session/signer_session_manager.ts +57 -27
  42. package/src/signer_session.ts +266 -89
  43. package/src/util.ts +41 -0
  44. package/src/session/oidc_session_manager.ts +0 -193
@@ -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
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsMkNBQTZCO0FBRTdCOzs7R0FHRztBQUNILFNBQWdCLFNBQVM7SUFDdkIsTUFBTSxTQUFTLEdBQ2IsT0FBTyxDQUFDLFFBQVEsS0FBSyxRQUFRO1FBQzNCLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSw4QkFBOEI7UUFDbkQsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLFVBQVUsQ0FBQztJQUNwQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDO0FBQzVDLENBQUM7QUFORCw4QkFNQztBQUlEOztHQUVHO0FBQ0gsTUFBYSxXQUFZLFNBQVEsS0FBSztJQVFwQzs7O09BR0c7SUFDSCxZQUFZLElBQTBCO1FBQ3BDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDcEIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDNUIsQ0FBQztDQUNGO0FBaEJELGtDQWdCQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLFFBQVEsQ0FBTyxJQUF3QixFQUFFLFdBQW9CO0lBQzNFLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRTtRQUNkLE1BQU0sSUFBSSxXQUFXLENBQUM7WUFDcEIsV0FBVztZQUNYLE9BQU8sRUFBRyxJQUFJLENBQUMsS0FBYSxDQUFDLE9BQU87WUFDcEMsVUFBVSxFQUFFLElBQUksQ0FBQyxRQUFRLEVBQUUsVUFBVTtZQUNyQyxNQUFNLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxNQUFNO1NBQzlCLENBQUMsQ0FBQztLQUNKO0lBQ0QsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFNBQVMsRUFBRTtRQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7S0FDL0M7SUFDRCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUM7QUFDbkIsQ0FBQztBQWJELDRCQWFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwicGF0aFwiO1xuXG4vKipcbiAqIERpcmVjdG9yeSB3aGVyZSBDdWJlU2lnbmVyIHN0b3JlcyBjb25maWcgZmlsZXMuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IENvbmZpZyBkaXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbmZpZ0RpcigpOiBzdHJpbmcge1xuICBjb25zdCBjb25maWdEaXIgPVxuICAgIHByb2Nlc3MucGxhdGZvcm0gPT09IFwiZGFyd2luXCJcbiAgICAgID8gYCR7cHJvY2Vzcy5lbnYuSE9NRX0vTGlicmFyeS9BcHBsaWNhdGlvbiBTdXBwb3J0YFxuICAgICAgOiBgJHtwcm9jZXNzLmVudi5IT01FfS8uY29uZmlnYDtcbiAgcmV0dXJuIHBhdGguam9pbihjb25maWdEaXIsIFwiY3ViZXNpZ25lclwiKTtcbn1cblxudHlwZSBSZXNwb25zZVR5cGU8RCwgVD4gPSB7IGRhdGE/OiBEOyBlcnJvcj86IFQ7IHJlc3BvbnNlPzogUmVzcG9uc2UgfTtcblxuLyoqXG4gKiBFcnJvciByZXNwb25zZSB0eXBlLCB0aHJvd24gb24gbm9uLXN1Y2Nlc3NmdWwgcmVzcG9uc2VzLlxuICovXG5leHBvcnQgY2xhc3MgRXJyUmVzcG9uc2UgZXh0ZW5kcyBFcnJvciB7XG4gIC8qKiBEZXNjcmlwdGlvbiAqL1xuICByZWFkb25seSBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgLyoqIEhUVFAgc3RhdHVzIGNvZGUgdGV4dCAoZGVyaXZlZCBmcm9tIGB0aGlzLnN0YXR1c2ApICovXG4gIHJlYWRvbmx5IHN0YXR1c1RleHQ/OiBzdHJpbmc7XG4gIC8qKiBIVFRQIHN0YXR1cyBjb2RlICovXG4gIHJlYWRvbmx5IHN0YXR1cz86IG51bWJlcjtcblxuICAvKipcbiAgICogQ29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtQYXJ0aWFsPEVyclJlc3BvbnNlPn0gaW5pdCBJbml0aWFsaXplclxuICAgKi9cbiAgY29uc3RydWN0b3IoaW5pdDogUGFydGlhbDxFcnJSZXNwb25zZT4pIHtcbiAgICBzdXBlcihpbml0Lm1lc3NhZ2UpO1xuICAgIE9iamVjdC5hc3NpZ24odGhpcywgaW5pdCk7XG4gIH1cbn1cblxuLyoqXG4gKiBUaHJvdyBpZiBvbiBlcnJvciByZXNwb25zZS4gT3RoZXJ3aXNlLCByZXR1cm4gdGhlIHJlc3BvbnNlIGRhdGEuXG4gKiBAcGFyYW0ge1Jlc3BvbnNlVHlwZX0gcmVzcCBUaGUgcmVzcG9uc2UgdG8gY2hlY2tcbiAqIEBwYXJhbSB7c3RyaW5nfSBkZXNjcmlwdGlvbiBEZXNjcmlwdGlvbiB0byBpbmNsdWRlIGluIHRoZSB0aHJvd24gZXJyb3JcbiAqIEByZXR1cm4ge0R9IFRoZSByZXNwb25zZSBkYXRhLlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRPazxELCBUPihyZXNwOiBSZXNwb25zZVR5cGU8RCwgVD4sIGRlc2NyaXB0aW9uPzogc3RyaW5nKTogRCB7XG4gIGlmIChyZXNwLmVycm9yKSB7XG4gICAgdGhyb3cgbmV3IEVyclJlc3BvbnNlKHtcbiAgICAgIGRlc2NyaXB0aW9uLFxuICAgICAgbWVzc2FnZTogKHJlc3AuZXJyb3IgYXMgYW55KS5tZXNzYWdlLCAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgIHN0YXR1c1RleHQ6IHJlc3AucmVzcG9uc2U/LnN0YXR1c1RleHQsXG4gICAgICBzdGF0dXM6IHJlc3AucmVzcG9uc2U/LnN0YXR1cyxcbiAgICB9KTtcbiAgfVxuICBpZiAocmVzcC5kYXRhID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZXNwb25zZSBkYXRhIGlzIHVuZGVmaW5lZFwiKTtcbiAgfVxuICByZXR1cm4gcmVzcC5kYXRhO1xufVxuIl19
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.26",
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": "^6.7.1",
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.3.2",
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.2.8",
49
+ "openapi-typescript": "^6.7.0",
47
50
  "otplib": "^12.0.1",
48
- "prettier": "3.0.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.398.0"
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
  }
@@ -7,8 +7,33 @@ import {
7
7
  getBytes,
8
8
  toBeHex,
9
9
  } from "ethers";
10
- import { BlobSignRequest, EvmSignRequest, SignerSession } from "../signer_session";
11
- import { Key } from "../key";
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?: 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 {null | ethers.Provider} provider The optional provider instance to use.
66
+ * @param {SignerOptions} options The options to use for the Signer instance
30
67
  */
31
- constructor(address: string, signerSession: SignerSession, provider?: null | ethers.Provider) {
32
- super(provider);
33
- this.#address = address;
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
- const sig = await this.#signerSession.signEvm(this.#address, req);
79
- return sig.data().rlp_signed_tx;
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.materialId === this.#address);
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
- // sign
128
- const result = await this.#signerSession.signBlob(this.#key, blobReq);
129
- return result.data().signature;
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
+ }