@cubist-labs/cubesigner-sdk 0.2.21 → 0.2.24
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/dist/package.json +6 -6
- package/dist/src/api.js +3 -1
- package/dist/src/org.d.ts +1 -0
- package/dist/src/schema.d.ts +61 -26
- package/dist/src/schema.js +1 -1
- package/dist/src/session/cognito_manager.js +2 -2
- package/dist/src/session/session_manager.d.ts +10 -2
- package/dist/src/session/session_manager.js +46 -6
- package/dist/src/session/signer_session_manager.d.ts +2 -0
- package/dist/src/session/signer_session_manager.js +15 -6
- package/dist/src/util.d.ts +7 -0
- package/dist/src/util.js +12 -2
- package/package.json +6 -6
- package/src/api.ts +2 -0
- package/src/schema.ts +61 -26
- package/src/session/cognito_manager.ts +1 -1
- package/src/session/session_manager.ts +32 -5
- package/src/session/signer_session_manager.ts +19 -6
- package/src/util.ts +10 -0
package/src/schema.ts
CHANGED
|
@@ -886,7 +886,7 @@ export interface components {
|
|
|
886
886
|
* https://www.w3.org/TR/webauthn-2/#dictdef-authenticatorselectioncriteria
|
|
887
887
|
*/
|
|
888
888
|
AuthenticatorSelectionCriteria: {
|
|
889
|
-
|
|
889
|
+
authenticatorAttachment?: components["schemas"]["AuthenticatorAttachment"] | null;
|
|
890
890
|
/**
|
|
891
891
|
* @description This member is retained for backwards compatibility with WebAuthn Level
|
|
892
892
|
* 1 and, for historical reasons, its naming retains the deprecated
|
|
@@ -895,9 +895,9 @@ export interface components {
|
|
|
895
895
|
*
|
|
896
896
|
* https://www.w3.org/TR/webauthn-2/#dom-authenticatorselectioncriteria-requireresidentkey
|
|
897
897
|
*/
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
898
|
+
requireResidentKey?: boolean;
|
|
899
|
+
residentKey?: components["schemas"]["ResidentKeyRequirement"] | null;
|
|
900
|
+
userVerification?: components["schemas"]["UserVerificationRequirement"];
|
|
901
901
|
};
|
|
902
902
|
/**
|
|
903
903
|
* @description Authenticators may implement various transports for communicating with
|
|
@@ -1580,25 +1580,6 @@ export interface components {
|
|
|
1580
1580
|
*/
|
|
1581
1581
|
skip_email: boolean;
|
|
1582
1582
|
};
|
|
1583
|
-
/**
|
|
1584
|
-
* @description Key material contained inside a [`JsonKeyPackage`], which can be either
|
|
1585
|
-
* a raw secret or a mnemonic, password, and derivation path.
|
|
1586
|
-
*/
|
|
1587
|
-
JsonKeyMaterial: {
|
|
1588
|
-
/** @enum {string} */
|
|
1589
|
-
material_type: "raw_secret";
|
|
1590
|
-
/** @description The value of the raw secret */
|
|
1591
|
-
secret: string;
|
|
1592
|
-
} | {
|
|
1593
|
-
/** @description The derivation path */
|
|
1594
|
-
derivation_path: string;
|
|
1595
|
-
/** @enum {string} */
|
|
1596
|
-
material_type: "english_mnemonic";
|
|
1597
|
-
/** @description The mnemonic */
|
|
1598
|
-
mnemonic: string;
|
|
1599
|
-
/** @description The password (which may be empty) */
|
|
1600
|
-
password: string;
|
|
1601
|
-
};
|
|
1602
1583
|
/**
|
|
1603
1584
|
* @description A [`KeyPackage`] serialized into a format that gives a tidier JSON
|
|
1604
1585
|
* representation suitable for encryption in the user-export flow.
|
|
@@ -1669,9 +1650,21 @@ export interface components {
|
|
|
1669
1650
|
* );
|
|
1670
1651
|
* ```
|
|
1671
1652
|
*/
|
|
1672
|
-
JsonKeyPackage: {
|
|
1673
|
-
|
|
1674
|
-
|
|
1653
|
+
JsonKeyPackage: ({
|
|
1654
|
+
/** @enum {string} */
|
|
1655
|
+
material_type: "raw_secret";
|
|
1656
|
+
/** @description The value of the raw secret */
|
|
1657
|
+
secret: string;
|
|
1658
|
+
} | {
|
|
1659
|
+
/** @description The derivation path */
|
|
1660
|
+
derivation_path: string;
|
|
1661
|
+
/** @enum {string} */
|
|
1662
|
+
material_type: "english_mnemonic";
|
|
1663
|
+
/** @description The mnemonic */
|
|
1664
|
+
mnemonic: string;
|
|
1665
|
+
/** @description The password (which may be empty) */
|
|
1666
|
+
password: string;
|
|
1667
|
+
}) & {
|
|
1675
1668
|
/** @description The type of key this package represents */
|
|
1676
1669
|
key_type: string;
|
|
1677
1670
|
};
|
|
@@ -1811,6 +1804,12 @@ export interface components {
|
|
|
1811
1804
|
Network: "mainnet" | "prater" | "goerli" | "holesky";
|
|
1812
1805
|
/** @description Information about a new session, returned from multiple endpoints (e.g., login, refresh, etc.). */
|
|
1813
1806
|
NewSessionResponse: {
|
|
1807
|
+
/**
|
|
1808
|
+
* Format: int64
|
|
1809
|
+
* @description Session expiration (in seconds since UNIX epoch), beyond which it cannot be refreshed.
|
|
1810
|
+
* @example 1701879640
|
|
1811
|
+
*/
|
|
1812
|
+
expiration?: number;
|
|
1814
1813
|
session_info: components["schemas"]["ClientSessionInfo"];
|
|
1815
1814
|
/**
|
|
1816
1815
|
* @description New token to be used for authentication. Requests to signing endpoints
|
|
@@ -1901,6 +1900,13 @@ export interface components {
|
|
|
1901
1900
|
* ]
|
|
1902
1901
|
*/
|
|
1903
1902
|
policy?: Record<string, never>[];
|
|
1903
|
+
/**
|
|
1904
|
+
* Format: int32
|
|
1905
|
+
* @description The organization's currently configured TOTP failure limit, i.e., the number
|
|
1906
|
+
* of times a user can provide an incorrect TOTP code before being rate limited.
|
|
1907
|
+
* This value can be between 1 and 5 (inclusive).
|
|
1908
|
+
*/
|
|
1909
|
+
totp_failure_limit: number;
|
|
1904
1910
|
/**
|
|
1905
1911
|
* Format: int64
|
|
1906
1912
|
* @description The organization's currently configured user-export delay, i.e., the minimum
|
|
@@ -2659,6 +2665,12 @@ export interface components {
|
|
|
2659
2665
|
* ]
|
|
2660
2666
|
*/
|
|
2661
2667
|
policy?: Record<string, never>[] | null;
|
|
2668
|
+
/**
|
|
2669
|
+
* Format: int32
|
|
2670
|
+
* @description If set, update this org's TOTP failure limit. After this many failures,
|
|
2671
|
+
* the user is rate limited until the next 30-second TOTP window.
|
|
2672
|
+
*/
|
|
2673
|
+
totp_failure_limit?: number | null;
|
|
2662
2674
|
/**
|
|
2663
2675
|
* Format: int64
|
|
2664
2676
|
* @description If set, update this org's user-export delay, i.e., the amount of time
|
|
@@ -2704,6 +2716,11 @@ export interface components {
|
|
|
2704
2716
|
* ]
|
|
2705
2717
|
*/
|
|
2706
2718
|
policy?: Record<string, never>[] | null;
|
|
2719
|
+
/**
|
|
2720
|
+
* Format: int32
|
|
2721
|
+
* @description The new value of the TOTP failure limit
|
|
2722
|
+
*/
|
|
2723
|
+
totp_failure_limit?: number | null;
|
|
2707
2724
|
/**
|
|
2708
2725
|
* Format: int64
|
|
2709
2726
|
* @description The new value of user-export delay
|
|
@@ -3183,6 +3200,12 @@ export interface components {
|
|
|
3183
3200
|
NewSessionResponse: {
|
|
3184
3201
|
content: {
|
|
3185
3202
|
"application/json": {
|
|
3203
|
+
/**
|
|
3204
|
+
* Format: int64
|
|
3205
|
+
* @description Session expiration (in seconds since UNIX epoch), beyond which it cannot be refreshed.
|
|
3206
|
+
* @example 1701879640
|
|
3207
|
+
*/
|
|
3208
|
+
expiration?: number;
|
|
3186
3209
|
session_info: components["schemas"]["ClientSessionInfo"];
|
|
3187
3210
|
/**
|
|
3188
3211
|
* @description New token to be used for authentication. Requests to signing endpoints
|
|
@@ -3234,6 +3257,13 @@ export interface components {
|
|
|
3234
3257
|
* ]
|
|
3235
3258
|
*/
|
|
3236
3259
|
policy?: Record<string, never>[];
|
|
3260
|
+
/**
|
|
3261
|
+
* Format: int32
|
|
3262
|
+
* @description The organization's currently configured TOTP failure limit, i.e., the number
|
|
3263
|
+
* of times a user can provide an incorrect TOTP code before being rate limited.
|
|
3264
|
+
* This value can be between 1 and 5 (inclusive).
|
|
3265
|
+
*/
|
|
3266
|
+
totp_failure_limit: number;
|
|
3237
3267
|
/**
|
|
3238
3268
|
* Format: int64
|
|
3239
3269
|
* @description The organization's currently configured user-export delay, i.e., the minimum
|
|
@@ -3517,6 +3547,11 @@ export interface components {
|
|
|
3517
3547
|
* ]
|
|
3518
3548
|
*/
|
|
3519
3549
|
policy?: Record<string, never>[] | null;
|
|
3550
|
+
/**
|
|
3551
|
+
* Format: int32
|
|
3552
|
+
* @description The new value of the TOTP failure limit
|
|
3553
|
+
*/
|
|
3554
|
+
totp_failure_limit?: number | null;
|
|
3520
3555
|
/**
|
|
3521
3556
|
* Format: int64
|
|
3522
3557
|
* @description The new value of user-export delay
|
|
@@ -70,7 +70,7 @@ export class CognitoSessionManager extends OrgSessionManager<CognitoSessionInfo>
|
|
|
70
70
|
*/
|
|
71
71
|
async isStale(): Promise<boolean> {
|
|
72
72
|
const session = await this.storage.retrieve();
|
|
73
|
-
return SessionManager.
|
|
73
|
+
return SessionManager.isStale(new Date(session.expiration));
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
/**
|
|
@@ -2,6 +2,7 @@ import { Events } from "../events";
|
|
|
2
2
|
import { EnvInterface } from "../env";
|
|
3
3
|
import { Client, createHttpClient } from "../api";
|
|
4
4
|
import { SessionStorage } from "./session_storage";
|
|
5
|
+
import { delay } from "../util";
|
|
5
6
|
|
|
6
7
|
const DEFAULT_EXPIRATION_BUFFER_SECS = 30;
|
|
7
8
|
|
|
@@ -10,6 +11,7 @@ export abstract class SessionManager<U> {
|
|
|
10
11
|
readonly env: EnvInterface;
|
|
11
12
|
readonly storage: SessionStorage<U>;
|
|
12
13
|
readonly events = new Events();
|
|
14
|
+
#refreshing: boolean = false;
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* @return {string} The current auth token.
|
|
@@ -40,9 +42,24 @@ export abstract class SessionManager<U> {
|
|
|
40
42
|
*/
|
|
41
43
|
async refreshIfNeeded(): Promise<boolean> {
|
|
42
44
|
if (await this.isStale()) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
if (this.#refreshing) {
|
|
46
|
+
// wait until done refreshing
|
|
47
|
+
while (this.#refreshing) {
|
|
48
|
+
await delay(100);
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
} else {
|
|
52
|
+
// refresh
|
|
53
|
+
this.#refreshing = true;
|
|
54
|
+
try {
|
|
55
|
+
await this.refresh();
|
|
56
|
+
return true;
|
|
57
|
+
} finally {
|
|
58
|
+
this.#refreshing = false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
45
61
|
}
|
|
62
|
+
|
|
46
63
|
return false;
|
|
47
64
|
}
|
|
48
65
|
|
|
@@ -88,19 +105,29 @@ export abstract class SessionManager<U> {
|
|
|
88
105
|
}
|
|
89
106
|
|
|
90
107
|
/**
|
|
91
|
-
* Check if a timestamp
|
|
108
|
+
* Check if a timestamp is within {@link bufferSeconds} seconds from expiration.
|
|
92
109
|
* @param {Date} exp The timestamp to check
|
|
93
|
-
* @param {number} bufferSeconds Time buffer in seconds (defaults to
|
|
110
|
+
* @param {number} bufferSeconds Time buffer in seconds (defaults to 0s)
|
|
94
111
|
* @return {boolean} True if the timestamp has expired
|
|
95
112
|
*/
|
|
96
113
|
protected static hasExpired(exp: Date, bufferSeconds?: number): boolean {
|
|
97
|
-
bufferSeconds ??=
|
|
114
|
+
bufferSeconds ??= 0;
|
|
98
115
|
const expMsSinceEpoch = exp.getTime();
|
|
99
116
|
const nowMsSinceEpoch = new Date().getTime();
|
|
100
117
|
const bufferMs = bufferSeconds * 1000;
|
|
101
118
|
return expMsSinceEpoch < nowMsSinceEpoch + bufferMs;
|
|
102
119
|
}
|
|
103
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Check if a timestamp is stale, i.e., it's within {@link bufferSeconds} seconds from expiration.
|
|
123
|
+
* @param {Date} exp The timestamp to check
|
|
124
|
+
* @param {number} bufferSeconds Time buffer in seconds (defaults to 30s)
|
|
125
|
+
* @return {boolean} True if the timestamp is stale
|
|
126
|
+
*/
|
|
127
|
+
protected static isStale(exp: Date, bufferSeconds?: number): boolean {
|
|
128
|
+
return this.hasExpired(exp, bufferSeconds ?? DEFAULT_EXPIRATION_BUFFER_SECS);
|
|
129
|
+
}
|
|
130
|
+
|
|
104
131
|
/**
|
|
105
132
|
* Throws an error that says that some feature is unsupported.
|
|
106
133
|
* @param {string} name The name of the feature that is not supported
|
|
@@ -21,6 +21,8 @@ export interface SignerSessionObject {
|
|
|
21
21
|
token: string;
|
|
22
22
|
/** Session info */
|
|
23
23
|
session_info: ClientSessionInfo;
|
|
24
|
+
/** Session expiration (in seconds since UNIX epoch) beyond which it cannot be refreshed */
|
|
25
|
+
session_exp: number | undefined; // may be missing in legacy session files
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
/**
|
|
@@ -51,7 +53,7 @@ export interface SignerSessionLifetime {
|
|
|
51
53
|
/** Manager for signer sessions. */
|
|
52
54
|
export class SignerSessionManager extends OrgSessionManager<SignerSessionData> {
|
|
53
55
|
readonly #eventEmitter: EventEmitter;
|
|
54
|
-
#client: { client: Client;
|
|
56
|
+
#client: { client: Client; token_exp: Date; session_exp?: Date };
|
|
55
57
|
|
|
56
58
|
/**
|
|
57
59
|
* @return {string} The current auth token.
|
|
@@ -70,8 +72,12 @@ export class SignerSessionManager extends OrgSessionManager<SignerSessionData> {
|
|
|
70
72
|
async client(): Promise<Client> {
|
|
71
73
|
await this.refreshIfNeeded();
|
|
72
74
|
|
|
73
|
-
// trigger "session expired" if
|
|
74
|
-
if (
|
|
75
|
+
// trigger "session expired" if the session as a whole has expired
|
|
76
|
+
// or if (for whatever reason) the token is still stale
|
|
77
|
+
if (
|
|
78
|
+
SessionManager.hasExpired(this.#client.token_exp) ||
|
|
79
|
+
(this.#client.session_exp && SessionManager.hasExpired(this.#client.session_exp))
|
|
80
|
+
) {
|
|
75
81
|
await this.#eventEmitter.emitSessionExpired();
|
|
76
82
|
}
|
|
77
83
|
|
|
@@ -92,7 +98,7 @@ export class SignerSessionManager extends OrgSessionManager<SignerSessionData> {
|
|
|
92
98
|
* @internal
|
|
93
99
|
*/
|
|
94
100
|
async isStale(): Promise<boolean> {
|
|
95
|
-
return SessionManager.
|
|
101
|
+
return SessionManager.isStale(this.#client.token_exp);
|
|
96
102
|
}
|
|
97
103
|
|
|
98
104
|
/**
|
|
@@ -120,7 +126,10 @@ export class SignerSessionManager extends OrgSessionManager<SignerSessionData> {
|
|
|
120
126
|
await this.storage.save(newSession);
|
|
121
127
|
this.#client = {
|
|
122
128
|
client: this.createClient(newSession.token),
|
|
123
|
-
|
|
129
|
+
token_exp: secondsSinceEpochToDate(newSession.session_info.auth_token_exp),
|
|
130
|
+
session_exp: newSession.session_exp
|
|
131
|
+
? secondsSinceEpochToDate(newSession.session_exp)
|
|
132
|
+
: undefined,
|
|
124
133
|
};
|
|
125
134
|
}
|
|
126
135
|
|
|
@@ -145,6 +154,7 @@ export class SignerSessionManager extends OrgSessionManager<SignerSessionData> {
|
|
|
145
154
|
token: session.token,
|
|
146
155
|
purpose: "sign via oidc",
|
|
147
156
|
session_info: session.session_info,
|
|
157
|
+
session_exp: session.expiration!,
|
|
148
158
|
};
|
|
149
159
|
storage ??= new MemorySessionStorage();
|
|
150
160
|
await storage.save(sessionData);
|
|
@@ -187,7 +197,10 @@ export class SignerSessionManager extends OrgSessionManager<SignerSessionData> {
|
|
|
187
197
|
this.#eventEmitter = new EventEmitter([this.events]);
|
|
188
198
|
this.#client = {
|
|
189
199
|
client: this.createClient(sessionData.token),
|
|
190
|
-
|
|
200
|
+
token_exp: secondsSinceEpochToDate(sessionData.session_info.auth_token_exp),
|
|
201
|
+
session_exp: sessionData.session_exp
|
|
202
|
+
? secondsSinceEpochToDate(sessionData.session_exp)
|
|
203
|
+
: undefined,
|
|
191
204
|
};
|
|
192
205
|
}
|
|
193
206
|
}
|
package/src/util.ts
CHANGED
|
@@ -71,3 +71,13 @@ export function encodeToBase64Url(buffer: Iterable<number>): string {
|
|
|
71
71
|
// NOTE: there is no "base64url" encoding in the "buffer" module for the browser (unlike in node.js)
|
|
72
72
|
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=*$/g, "");
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Sleeps for `ms` milliseconds.
|
|
77
|
+
*
|
|
78
|
+
* @param {number} ms Milliseconds to sleep
|
|
79
|
+
* @return {Promise<void>} A promise that is resolved after `ms` milliseconds.
|
|
80
|
+
*/
|
|
81
|
+
export function delay(ms: number): Promise<void> {
|
|
82
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
83
|
+
}
|