@fourt/sdk 1.2.2 → 1.3.0
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/index.cjs +227 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +120 -14
- package/dist/index.d.ts +120 -14
- package/dist/index.js +234 -90
- package/dist/index.js.map +1 -1
- package/package.json +3 -9
package/dist/index.cjs
CHANGED
|
@@ -172,34 +172,95 @@ var SessionStore = class {
|
|
|
172
172
|
}
|
|
173
173
|
};
|
|
174
174
|
|
|
175
|
-
// src/modules/auth/email.ts
|
|
176
|
-
var
|
|
175
|
+
// src/modules/auth/email/magicLink.ts
|
|
176
|
+
var MagicLinkModule = class {
|
|
177
177
|
constructor(_webSignerClient) {
|
|
178
178
|
this._webSignerClient = _webSignerClient;
|
|
179
179
|
}
|
|
180
180
|
/**
|
|
181
|
-
*
|
|
181
|
+
* Completes authentication with magic link that contains a bundle.
|
|
182
182
|
*
|
|
183
|
-
* @param params {
|
|
184
|
-
* @returns {Promise<void>} promise that
|
|
183
|
+
* @param params {CompleteAuthWithBundleParams} params received as URL params necessary to complete authentication process.
|
|
184
|
+
* @returns {Promise<void>} promise that completes the authentication process.
|
|
185
185
|
*/
|
|
186
|
-
async
|
|
187
|
-
return this._webSignerClient.
|
|
186
|
+
async complete(params) {
|
|
187
|
+
return this._webSignerClient.completeAuthWithBundle({
|
|
188
|
+
...params,
|
|
189
|
+
sessionType: "email" /* Email */
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// src/errors/SDKError.ts
|
|
195
|
+
var SDKError = class extends Error {
|
|
196
|
+
_props;
|
|
197
|
+
constructor(message, props) {
|
|
198
|
+
super(message);
|
|
199
|
+
this._props = props;
|
|
200
|
+
}
|
|
201
|
+
get message() {
|
|
202
|
+
return this._props.message;
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// src/errors/NotFoundError.ts
|
|
207
|
+
var NotFoundError = class _NotFoundError extends SDKError {
|
|
208
|
+
constructor(props) {
|
|
209
|
+
super(_NotFoundError.name, props);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// src/modules/auth/email/otp.ts
|
|
214
|
+
var OtpModule = class {
|
|
215
|
+
constructor(_webSignerClient) {
|
|
216
|
+
this._webSignerClient = _webSignerClient;
|
|
188
217
|
}
|
|
189
218
|
/**
|
|
190
|
-
* Completes authentication with
|
|
219
|
+
* Completes authentication with OTP code after user receives the bundle and subOrgId.
|
|
191
220
|
*
|
|
192
|
-
* @param params {
|
|
221
|
+
* @param params {OtpAuthParams} params to complete the authentication process.
|
|
193
222
|
* @returns {Promise<void>} promise that completes the authentication process.
|
|
194
223
|
*/
|
|
195
224
|
async complete(params) {
|
|
225
|
+
const { auth } = await this._webSignerClient.otpAuth(params);
|
|
226
|
+
if (!auth)
|
|
227
|
+
throw new NotFoundError({
|
|
228
|
+
message: "No OTP authentication response returned."
|
|
229
|
+
});
|
|
196
230
|
return this._webSignerClient.completeAuthWithBundle({
|
|
197
|
-
|
|
231
|
+
bundle: auth.credentialBundle,
|
|
232
|
+
subOrgId: auth.subOrgId,
|
|
198
233
|
sessionType: "email" /* Email */
|
|
199
234
|
});
|
|
200
235
|
}
|
|
201
236
|
};
|
|
202
237
|
|
|
238
|
+
// src/modules/auth/email.ts
|
|
239
|
+
var EmailModule = class {
|
|
240
|
+
constructor(_webSignerClient) {
|
|
241
|
+
this._webSignerClient = _webSignerClient;
|
|
242
|
+
this._magicLinkModule = new MagicLinkModule(this._webSignerClient);
|
|
243
|
+
this._otpModule = new OtpModule(this._webSignerClient);
|
|
244
|
+
}
|
|
245
|
+
_magicLinkModule;
|
|
246
|
+
_otpModule;
|
|
247
|
+
/**
|
|
248
|
+
* Initialize user authentication process using email.
|
|
249
|
+
*
|
|
250
|
+
* @param params {EmailInitializeAuthParams} params to initialize the user authentication process.
|
|
251
|
+
* @returns {Promise<void>} promise that resolves to the result of the authentication process.
|
|
252
|
+
*/
|
|
253
|
+
async initialize(params) {
|
|
254
|
+
return this._webSignerClient.emailAuth(params);
|
|
255
|
+
}
|
|
256
|
+
get magicLink() {
|
|
257
|
+
return this._magicLinkModule;
|
|
258
|
+
}
|
|
259
|
+
get otp() {
|
|
260
|
+
return this._otpModule;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
203
264
|
// src/modules/auth/passkeys.ts
|
|
204
265
|
var PasskeysModule = class {
|
|
205
266
|
constructor(_webSignerClient) {
|
|
@@ -209,7 +270,6 @@ var PasskeysModule = class {
|
|
|
209
270
|
* Signs in a user using Passkeys.
|
|
210
271
|
*
|
|
211
272
|
* @param params {WebauthnSignInParams} params for the sign-in process.
|
|
212
|
-
* @returns {Promise<void>} promise that resolves to the result of the sign-in process.
|
|
213
273
|
*/
|
|
214
274
|
async signIn(params) {
|
|
215
275
|
return this._webSignerClient.webauthnSignIn(params);
|
|
@@ -218,7 +278,40 @@ var PasskeysModule = class {
|
|
|
218
278
|
|
|
219
279
|
// src/modules/auth/oauth/google.ts
|
|
220
280
|
var jose = __toESM(require("jose"), 1);
|
|
221
|
-
|
|
281
|
+
|
|
282
|
+
// src/lib/sha256.ts
|
|
283
|
+
var LibSha256 = class {
|
|
284
|
+
/**
|
|
285
|
+
* Compute SHA-256 and return hex string using Web Crypto when available.
|
|
286
|
+
* Falls back to Node's crypto.createHash when running in Node.
|
|
287
|
+
*/
|
|
288
|
+
static async sha256Hex(input) {
|
|
289
|
+
let data;
|
|
290
|
+
if (typeof input === "string") {
|
|
291
|
+
data = new TextEncoder().encode(input);
|
|
292
|
+
} else if (input instanceof Uint8Array) {
|
|
293
|
+
data = input;
|
|
294
|
+
} else {
|
|
295
|
+
data = new Uint8Array(input);
|
|
296
|
+
}
|
|
297
|
+
const subtle = typeof globalThis !== "undefined" && globalThis.crypto?.subtle ? globalThis.crypto.subtle : void 0;
|
|
298
|
+
if (subtle) {
|
|
299
|
+
const hash = await subtle.digest("SHA-256", data);
|
|
300
|
+
return Array.from(new Uint8Array(hash)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
301
|
+
}
|
|
302
|
+
try {
|
|
303
|
+
const nodeCrypto = require("crypto");
|
|
304
|
+
const hash = nodeCrypto.createHash("sha256").update(data).digest("hex");
|
|
305
|
+
return hash;
|
|
306
|
+
} catch {
|
|
307
|
+
throw new Error(
|
|
308
|
+
"No crypto provider available. Provide a global crypto.subtle or run in Node 18+."
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// src/modules/auth/oauth/google.ts
|
|
222
315
|
var GoogleModule = class {
|
|
223
316
|
constructor(_webSignerClient) {
|
|
224
317
|
this._webSignerClient = _webSignerClient;
|
|
@@ -236,7 +329,7 @@ var GoogleModule = class {
|
|
|
236
329
|
).href;
|
|
237
330
|
url.searchParams.set("redirect_uri", internalUrl);
|
|
238
331
|
const publicKey = await this._webSignerClient.getIframePublicKey();
|
|
239
|
-
const nonce =
|
|
332
|
+
const nonce = await LibSha256.sha256Hex(publicKey);
|
|
240
333
|
url.searchParams.set("nonce", nonce);
|
|
241
334
|
const state = new jose.UnsecuredJWT({
|
|
242
335
|
apiKey: this._webSignerClient.configuration.apiKey,
|
|
@@ -250,18 +343,6 @@ var GoogleModule = class {
|
|
|
250
343
|
}
|
|
251
344
|
};
|
|
252
345
|
|
|
253
|
-
// src/errors/SDKError.ts
|
|
254
|
-
var SDKError = class extends Error {
|
|
255
|
-
_props;
|
|
256
|
-
constructor(message, props) {
|
|
257
|
-
super(message);
|
|
258
|
-
this._props = props;
|
|
259
|
-
}
|
|
260
|
-
get message() {
|
|
261
|
-
return this._props.message;
|
|
262
|
-
}
|
|
263
|
-
};
|
|
264
|
-
|
|
265
346
|
// src/errors/BadRequestError.ts
|
|
266
347
|
var BadRequestError = class _BadRequestError extends SDKError {
|
|
267
348
|
constructor(props) {
|
|
@@ -312,7 +393,6 @@ var FacebookModule = class {
|
|
|
312
393
|
|
|
313
394
|
// src/modules/auth/oauth/apple.ts
|
|
314
395
|
var jose3 = __toESM(require("jose"), 1);
|
|
315
|
-
var import_sha2 = require("sha.js");
|
|
316
396
|
var AppleModule = class {
|
|
317
397
|
constructor(_webSignerClient) {
|
|
318
398
|
this._webSignerClient = _webSignerClient;
|
|
@@ -330,7 +410,7 @@ var AppleModule = class {
|
|
|
330
410
|
).href;
|
|
331
411
|
url.searchParams.set("redirect_uri", internalUrl);
|
|
332
412
|
const publicKey = await this._webSignerClient.getIframePublicKey();
|
|
333
|
-
const nonce =
|
|
413
|
+
const nonce = await LibSha256.sha256Hex(publicKey);
|
|
334
414
|
url.searchParams.set("nonce", nonce);
|
|
335
415
|
const state = new jose3.UnsecuredJWT({
|
|
336
416
|
apiKey: this._webSignerClient.configuration.apiKey,
|
|
@@ -450,13 +530,29 @@ var import_iframe_stamper = require("@turnkey/iframe-stamper");
|
|
|
450
530
|
var import_webauthn_stamper = require("@turnkey/webauthn-stamper");
|
|
451
531
|
|
|
452
532
|
// src/lib/base64.ts
|
|
453
|
-
var import_buffer = require("buffer");
|
|
454
533
|
var LibBase64 = class {
|
|
534
|
+
// Convert an ArrayBuffer to base64url (no padding)
|
|
455
535
|
static fromBuffer(buffer) {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
536
|
+
const bytes = new Uint8Array(buffer);
|
|
537
|
+
const CHUNK_SIZE = 32768;
|
|
538
|
+
let binary = "";
|
|
539
|
+
for (let i = 0; i < bytes.length; i += CHUNK_SIZE) {
|
|
540
|
+
const chunk = bytes.subarray(i, i + CHUNK_SIZE);
|
|
541
|
+
binary += String.fromCharCode(...chunk);
|
|
542
|
+
}
|
|
543
|
+
const base64 = typeof btoa === "function" ? btoa(binary) : Buffer.from(bytes).toString("base64");
|
|
544
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
545
|
+
}
|
|
546
|
+
// Convert base64url (no padding) to ArrayBuffer
|
|
547
|
+
static toBuffer(base64url) {
|
|
548
|
+
let base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
|
|
549
|
+
const pad = base64.length % 4;
|
|
550
|
+
if (pad) base64 += "=".repeat(4 - pad);
|
|
551
|
+
const binary = typeof atob === "function" ? atob(base64) : Buffer.from(base64, "base64").toString("binary");
|
|
552
|
+
const len = binary.length;
|
|
553
|
+
const bytes = new Uint8Array(len);
|
|
554
|
+
for (let i = 0; i < len; i++) bytes[i] = binary.charCodeAt(i);
|
|
555
|
+
return bytes.buffer;
|
|
460
556
|
}
|
|
461
557
|
};
|
|
462
558
|
|
|
@@ -485,13 +581,6 @@ var UnauthorizedError = class _UnauthorizedError extends SDKError {
|
|
|
485
581
|
}
|
|
486
582
|
};
|
|
487
583
|
|
|
488
|
-
// src/errors/NotFoundError.ts
|
|
489
|
-
var NotFoundError = class _NotFoundError extends SDKError {
|
|
490
|
-
constructor(props) {
|
|
491
|
-
super(_NotFoundError.name, props);
|
|
492
|
-
}
|
|
493
|
-
};
|
|
494
|
-
|
|
495
584
|
// src/errors/GenericError.ts
|
|
496
585
|
var GenericError = class _GenericError extends SDKError {
|
|
497
586
|
constructor(props) {
|
|
@@ -506,23 +595,8 @@ var UnauthenticatedError = class _UnauthenticatedError extends SDKError {
|
|
|
506
595
|
}
|
|
507
596
|
};
|
|
508
597
|
|
|
509
|
-
// src/types/routes.ts
|
|
510
|
-
var ROUTE_METHOD_MAP = {
|
|
511
|
-
"/v1/signup": "POST",
|
|
512
|
-
"/v1/email-auth": "POST",
|
|
513
|
-
"/v1/lookup": "POST",
|
|
514
|
-
"/v1/signin": "POST",
|
|
515
|
-
"/v1/sign": "POST",
|
|
516
|
-
"/v1/oauth/init": "POST",
|
|
517
|
-
"/v1/refresh": "POST",
|
|
518
|
-
"/v1/csrf-token": "GET",
|
|
519
|
-
"/v1/logout": "POST",
|
|
520
|
-
"/v1/me": "GET"
|
|
521
|
-
};
|
|
522
|
-
|
|
523
598
|
// src/signer/index.ts
|
|
524
|
-
var
|
|
525
|
-
var import_date_fns = require("date-fns");
|
|
599
|
+
var import_jose = require("jose");
|
|
526
600
|
var SignerClient = class {
|
|
527
601
|
_turnkeyClient;
|
|
528
602
|
_configuration;
|
|
@@ -550,14 +624,14 @@ var SignerClient = class {
|
|
|
550
624
|
async getUser() {
|
|
551
625
|
if (this._sessionStore.user) return this._sessionStore.user;
|
|
552
626
|
try {
|
|
553
|
-
const user = await this.request("/v1/me");
|
|
627
|
+
const user = await this.request("/v1/me", "GET");
|
|
554
628
|
this._sessionStore.user = user;
|
|
555
629
|
return user;
|
|
556
630
|
} catch (error) {
|
|
557
631
|
if (error instanceof UnauthorizedError) {
|
|
558
632
|
try {
|
|
559
633
|
await this._refreshToken();
|
|
560
|
-
const user = await this.request("/v1/me");
|
|
634
|
+
const user = await this.request("/v1/me", "GET");
|
|
561
635
|
this._sessionStore.user = user;
|
|
562
636
|
return user;
|
|
563
637
|
} catch (error2) {
|
|
@@ -605,8 +679,8 @@ var SignerClient = class {
|
|
|
605
679
|
}
|
|
606
680
|
_isTokenExpired(token) {
|
|
607
681
|
try {
|
|
608
|
-
const decoded = (0,
|
|
609
|
-
if (decoded.exp) {
|
|
682
|
+
const decoded = (0, import_jose.decodeJwt)(token);
|
|
683
|
+
if (typeof decoded.exp === "number") {
|
|
610
684
|
return decoded.exp * 1e3 <= Date.now();
|
|
611
685
|
}
|
|
612
686
|
return true;
|
|
@@ -617,7 +691,7 @@ var SignerClient = class {
|
|
|
617
691
|
async logout() {
|
|
618
692
|
if (this._refreshTimer) clearTimeout(this._refreshTimer);
|
|
619
693
|
this._refreshTimer = void 0;
|
|
620
|
-
await this.request("/v1/logout");
|
|
694
|
+
await this.request("/v1/logout", "POST");
|
|
621
695
|
this._sessionStore.clearAll();
|
|
622
696
|
}
|
|
623
697
|
async signRawMessage(msg) {
|
|
@@ -637,7 +711,7 @@ var SignerClient = class {
|
|
|
637
711
|
signWith: this._sessionStore.user.walletAddress
|
|
638
712
|
}
|
|
639
713
|
});
|
|
640
|
-
const { signature } = await this.request("/v1/sign", {
|
|
714
|
+
const { signature } = await this.request("/v1/sign", "POST", {
|
|
641
715
|
stampedRequest
|
|
642
716
|
});
|
|
643
717
|
return signature;
|
|
@@ -650,7 +724,7 @@ var SignerClient = class {
|
|
|
650
724
|
}
|
|
651
725
|
async lookUpUser(email) {
|
|
652
726
|
try {
|
|
653
|
-
const { subOrgId } = await this.request("/v1/lookup", { email });
|
|
727
|
+
const { subOrgId } = await this.request("/v1/lookup", "POST", { email });
|
|
654
728
|
return subOrgId;
|
|
655
729
|
} catch (error) {
|
|
656
730
|
if (!(error instanceof SDKError)) throw error;
|
|
@@ -671,9 +745,13 @@ var SignerClient = class {
|
|
|
671
745
|
const stampedRequest = await this._turnkeyClient.stampGetWhoami({
|
|
672
746
|
organizationId: orgId
|
|
673
747
|
});
|
|
674
|
-
const { user, token, csrfToken } = await this.request(
|
|
675
|
-
|
|
676
|
-
|
|
748
|
+
const { user, token, csrfToken } = await this.request(
|
|
749
|
+
"/v1/signin",
|
|
750
|
+
"POST",
|
|
751
|
+
{
|
|
752
|
+
stampedRequest
|
|
753
|
+
}
|
|
754
|
+
);
|
|
677
755
|
const credentialId = (() => {
|
|
678
756
|
try {
|
|
679
757
|
return JSON.parse(stampedRequest?.stamp.stampHeaderValue).credentialId;
|
|
@@ -689,7 +767,7 @@ var SignerClient = class {
|
|
|
689
767
|
this._sessionStore.csrfToken = csrfToken;
|
|
690
768
|
this._scheduleRefresh(token);
|
|
691
769
|
}
|
|
692
|
-
async request(route, body) {
|
|
770
|
+
async request(route, method, body) {
|
|
693
771
|
const url = new URL(`${route}`, this._configuration.apiUrl);
|
|
694
772
|
const token = this._sessionStore.token;
|
|
695
773
|
const csrfToken = this._sessionStore.csrfToken;
|
|
@@ -704,8 +782,8 @@ var SignerClient = class {
|
|
|
704
782
|
headers["X-CSRF-Token"] = csrfToken;
|
|
705
783
|
}
|
|
706
784
|
const response = await fetch(url, {
|
|
707
|
-
method
|
|
708
|
-
body: JSON.stringify(body),
|
|
785
|
+
method,
|
|
786
|
+
body: method === "POST" ? JSON.stringify(body) : void 0,
|
|
709
787
|
headers,
|
|
710
788
|
credentials: "include"
|
|
711
789
|
});
|
|
@@ -728,13 +806,24 @@ var SignerClient = class {
|
|
|
728
806
|
}
|
|
729
807
|
return { ...data };
|
|
730
808
|
}
|
|
809
|
+
/**
|
|
810
|
+
* Compute milliseconds until refresh time.
|
|
811
|
+
* - expSeconds is the JWT exp claim (seconds).
|
|
812
|
+
* - earlyMinutes is how many minutes before exp to refresh (default 2).
|
|
813
|
+
* Returns 0 if refresh time is already past.
|
|
814
|
+
*/
|
|
815
|
+
_computeRefreshDelayMs(expSeconds, earlyMinutes = 2) {
|
|
816
|
+
const expiryMs = expSeconds * 1e3;
|
|
817
|
+
const refreshMs = expiryMs - earlyMinutes * 60 * 1e3;
|
|
818
|
+
const now = Date.now();
|
|
819
|
+
const delay = refreshMs - now;
|
|
820
|
+
return delay <= 0 ? 0 : delay;
|
|
821
|
+
}
|
|
731
822
|
_scheduleRefresh(token) {
|
|
732
823
|
try {
|
|
733
|
-
const decoded = (0,
|
|
824
|
+
const decoded = (0, import_jose.decodeJwt)(token);
|
|
734
825
|
if (!decoded.exp) return;
|
|
735
|
-
const
|
|
736
|
-
const refreshDate = (0, import_date_fns.subMinutes)(expiryDate, 2);
|
|
737
|
-
const delay = (0, import_date_fns.isBefore)(refreshDate, /* @__PURE__ */ new Date()) ? 0 : (0, import_date_fns.differenceInMilliseconds)(refreshDate, /* @__PURE__ */ new Date());
|
|
826
|
+
const delay = this._computeRefreshDelayMs(decoded.exp, 2);
|
|
738
827
|
if (this._refreshTimer) clearTimeout(this._refreshTimer);
|
|
739
828
|
this._refreshTimer = setTimeout(() => {
|
|
740
829
|
this._refreshTimer = void 0;
|
|
@@ -750,10 +839,10 @@ var SignerClient = class {
|
|
|
750
839
|
const RETRY_DELAY_MS = 5e3;
|
|
751
840
|
try {
|
|
752
841
|
if (!this._sessionStore.csrfToken) {
|
|
753
|
-
const { csrfToken } = await this.request("/v1/csrf-token");
|
|
842
|
+
const { csrfToken } = await this.request("/v1/csrf-token", "GET");
|
|
754
843
|
this._sessionStore.csrfToken = csrfToken;
|
|
755
844
|
}
|
|
756
|
-
const refreshPromise = this.request("/v1/refresh");
|
|
845
|
+
const refreshPromise = this.request("/v1/refresh", "POST");
|
|
757
846
|
const data = await Promise.race([
|
|
758
847
|
refreshPromise,
|
|
759
848
|
new Promise(
|
|
@@ -868,7 +957,7 @@ var WebSignerClient = class extends SignerClient {
|
|
|
868
957
|
* @param {string} provider provider for which we are getting the URL, currently google or apple
|
|
869
958
|
*/
|
|
870
959
|
async getOAuthInitUrl(provider) {
|
|
871
|
-
const { url } = await this.request("/v1/oauth/init", {
|
|
960
|
+
const { url } = await this.request("/v1/oauth/init", "POST", {
|
|
872
961
|
provider
|
|
873
962
|
});
|
|
874
963
|
return url;
|
|
@@ -899,21 +988,65 @@ var WebSignerClient = class extends SignerClient {
|
|
|
899
988
|
}
|
|
900
989
|
}
|
|
901
990
|
/**
|
|
902
|
-
*
|
|
991
|
+
* Handles auth user process with email according to the method of the used app.
|
|
903
992
|
*
|
|
904
|
-
* @param {EmailInitializeAuthParams} params
|
|
993
|
+
* @param {EmailInitializeAuthParams} params params needed for the initialization of the auth process
|
|
905
994
|
*/
|
|
906
995
|
async emailAuth(params) {
|
|
907
|
-
const
|
|
908
|
-
if (
|
|
909
|
-
await this.
|
|
996
|
+
const method = await this._getEmailAuthMethod();
|
|
997
|
+
if (method === "magiclink") {
|
|
998
|
+
const existingUserSubOrgId = await this.lookUpUser(params.email);
|
|
999
|
+
if (!existingUserSubOrgId) {
|
|
1000
|
+
await this._createAccount({ method: "email", ...params });
|
|
1001
|
+
} else {
|
|
1002
|
+
await this._signInWithEmail(params);
|
|
1003
|
+
}
|
|
1004
|
+
return { method };
|
|
1005
|
+
} else if (method === "otp") {
|
|
1006
|
+
const { init } = await this._initOtpAuth({ email: params.email });
|
|
1007
|
+
if (!init?.otpId)
|
|
1008
|
+
throw new NotFoundError({ message: "No OTP init response returned." });
|
|
1009
|
+
return {
|
|
1010
|
+
method,
|
|
1011
|
+
otpId: init.otpId
|
|
1012
|
+
};
|
|
910
1013
|
} else {
|
|
911
|
-
|
|
1014
|
+
throw new Error("Invalid email authentication method.");
|
|
912
1015
|
}
|
|
913
1016
|
}
|
|
914
1017
|
async getIframePublicKey() {
|
|
915
1018
|
return await this._initIframeStamper();
|
|
916
1019
|
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Verifies the provided otp code.
|
|
1022
|
+
*
|
|
1023
|
+
* @param {OtpAuthParams} params params needed for otp code verification
|
|
1024
|
+
*/
|
|
1025
|
+
async otpAuth(params) {
|
|
1026
|
+
return this.request("/v1/otp-auth", "POST", {
|
|
1027
|
+
auth: {
|
|
1028
|
+
email: params.email,
|
|
1029
|
+
otpCode: params.otpCode,
|
|
1030
|
+
otpId: params.otpId,
|
|
1031
|
+
targetPublicKey: await this.getIframePublicKey()
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Gets the email authentication method of the app.
|
|
1037
|
+
*/
|
|
1038
|
+
async _getEmailAuthMethod() {
|
|
1039
|
+
const { method } = await this.request("/v1/email-auth", "GET");
|
|
1040
|
+
return method;
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Starts email authentication process via otp.
|
|
1044
|
+
*/
|
|
1045
|
+
async _initOtpAuth(params) {
|
|
1046
|
+
return this.request("/v1/otp-auth", "POST", {
|
|
1047
|
+
init: { email: params.email }
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
917
1050
|
/**
|
|
918
1051
|
* Completes the authentication process with a credential bundle.
|
|
919
1052
|
*
|
|
@@ -960,7 +1093,7 @@ var WebSignerClient = class extends SignerClient {
|
|
|
960
1093
|
expirationSeconds,
|
|
961
1094
|
redirectUrl
|
|
962
1095
|
}) {
|
|
963
|
-
return this.request("/v1/email-auth", {
|
|
1096
|
+
return this.request("/v1/email-auth", "POST", {
|
|
964
1097
|
email,
|
|
965
1098
|
targetPublicKey: await this.getIframePublicKey(),
|
|
966
1099
|
expirationSeconds,
|
|
@@ -976,13 +1109,17 @@ var WebSignerClient = class extends SignerClient {
|
|
|
976
1109
|
const { challenge, attestation } = await this._webauthnGenerateAttestation(
|
|
977
1110
|
params.email
|
|
978
1111
|
);
|
|
979
|
-
const { user, token, csrfToken } = await this.request(
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1112
|
+
const { user, token, csrfToken } = await this.request(
|
|
1113
|
+
"/v1/signup",
|
|
1114
|
+
"POST",
|
|
1115
|
+
{
|
|
1116
|
+
passkey: {
|
|
1117
|
+
challenge: LibBase64.fromBuffer(challenge),
|
|
1118
|
+
attestation
|
|
1119
|
+
},
|
|
1120
|
+
email: params.email
|
|
1121
|
+
}
|
|
1122
|
+
);
|
|
986
1123
|
this._sessionStore.user = {
|
|
987
1124
|
...user,
|
|
988
1125
|
credentialId: attestation.credentialId
|
|
@@ -999,7 +1136,7 @@ var WebSignerClient = class extends SignerClient {
|
|
|
999
1136
|
*/
|
|
1000
1137
|
async _createEmailAccount(params) {
|
|
1001
1138
|
const { email, expirationSeconds, redirectUrl } = params;
|
|
1002
|
-
const response = await this.request("/v1/signup", {
|
|
1139
|
+
const response = await this.request("/v1/signup", "POST", {
|
|
1003
1140
|
email,
|
|
1004
1141
|
iframe: {
|
|
1005
1142
|
targetPublicKey: await this.getIframePublicKey(),
|