@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.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
1
8
|
// src/session/index.ts
|
|
2
9
|
import { createStore } from "zustand";
|
|
3
10
|
import { persist, createJSONStorage } from "zustand/middleware";
|
|
@@ -136,34 +143,95 @@ var SessionStore = class {
|
|
|
136
143
|
}
|
|
137
144
|
};
|
|
138
145
|
|
|
139
|
-
// src/modules/auth/email.ts
|
|
140
|
-
var
|
|
146
|
+
// src/modules/auth/email/magicLink.ts
|
|
147
|
+
var MagicLinkModule = class {
|
|
141
148
|
constructor(_webSignerClient) {
|
|
142
149
|
this._webSignerClient = _webSignerClient;
|
|
143
150
|
}
|
|
144
151
|
/**
|
|
145
|
-
*
|
|
152
|
+
* Completes authentication with magic link that contains a bundle.
|
|
146
153
|
*
|
|
147
|
-
* @param params {
|
|
148
|
-
* @returns {Promise<void>} promise that
|
|
154
|
+
* @param params {CompleteAuthWithBundleParams} params received as URL params necessary to complete authentication process.
|
|
155
|
+
* @returns {Promise<void>} promise that completes the authentication process.
|
|
149
156
|
*/
|
|
150
|
-
async
|
|
151
|
-
return this._webSignerClient.
|
|
157
|
+
async complete(params) {
|
|
158
|
+
return this._webSignerClient.completeAuthWithBundle({
|
|
159
|
+
...params,
|
|
160
|
+
sessionType: "email" /* Email */
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// src/errors/SDKError.ts
|
|
166
|
+
var SDKError = class extends Error {
|
|
167
|
+
_props;
|
|
168
|
+
constructor(message, props) {
|
|
169
|
+
super(message);
|
|
170
|
+
this._props = props;
|
|
171
|
+
}
|
|
172
|
+
get message() {
|
|
173
|
+
return this._props.message;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// src/errors/NotFoundError.ts
|
|
178
|
+
var NotFoundError = class _NotFoundError extends SDKError {
|
|
179
|
+
constructor(props) {
|
|
180
|
+
super(_NotFoundError.name, props);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// src/modules/auth/email/otp.ts
|
|
185
|
+
var OtpModule = class {
|
|
186
|
+
constructor(_webSignerClient) {
|
|
187
|
+
this._webSignerClient = _webSignerClient;
|
|
152
188
|
}
|
|
153
189
|
/**
|
|
154
|
-
* Completes authentication with
|
|
190
|
+
* Completes authentication with OTP code after user receives the bundle and subOrgId.
|
|
155
191
|
*
|
|
156
|
-
* @param params {
|
|
192
|
+
* @param params {OtpAuthParams} params to complete the authentication process.
|
|
157
193
|
* @returns {Promise<void>} promise that completes the authentication process.
|
|
158
194
|
*/
|
|
159
195
|
async complete(params) {
|
|
196
|
+
const { auth } = await this._webSignerClient.otpAuth(params);
|
|
197
|
+
if (!auth)
|
|
198
|
+
throw new NotFoundError({
|
|
199
|
+
message: "No OTP authentication response returned."
|
|
200
|
+
});
|
|
160
201
|
return this._webSignerClient.completeAuthWithBundle({
|
|
161
|
-
|
|
202
|
+
bundle: auth.credentialBundle,
|
|
203
|
+
subOrgId: auth.subOrgId,
|
|
162
204
|
sessionType: "email" /* Email */
|
|
163
205
|
});
|
|
164
206
|
}
|
|
165
207
|
};
|
|
166
208
|
|
|
209
|
+
// src/modules/auth/email.ts
|
|
210
|
+
var EmailModule = class {
|
|
211
|
+
constructor(_webSignerClient) {
|
|
212
|
+
this._webSignerClient = _webSignerClient;
|
|
213
|
+
this._magicLinkModule = new MagicLinkModule(this._webSignerClient);
|
|
214
|
+
this._otpModule = new OtpModule(this._webSignerClient);
|
|
215
|
+
}
|
|
216
|
+
_magicLinkModule;
|
|
217
|
+
_otpModule;
|
|
218
|
+
/**
|
|
219
|
+
* Initialize user authentication process using email.
|
|
220
|
+
*
|
|
221
|
+
* @param params {EmailInitializeAuthParams} params to initialize the user authentication process.
|
|
222
|
+
* @returns {Promise<void>} promise that resolves to the result of the authentication process.
|
|
223
|
+
*/
|
|
224
|
+
async initialize(params) {
|
|
225
|
+
return this._webSignerClient.emailAuth(params);
|
|
226
|
+
}
|
|
227
|
+
get magicLink() {
|
|
228
|
+
return this._magicLinkModule;
|
|
229
|
+
}
|
|
230
|
+
get otp() {
|
|
231
|
+
return this._otpModule;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
167
235
|
// src/modules/auth/passkeys.ts
|
|
168
236
|
var PasskeysModule = class {
|
|
169
237
|
constructor(_webSignerClient) {
|
|
@@ -173,7 +241,6 @@ var PasskeysModule = class {
|
|
|
173
241
|
* Signs in a user using Passkeys.
|
|
174
242
|
*
|
|
175
243
|
* @param params {WebauthnSignInParams} params for the sign-in process.
|
|
176
|
-
* @returns {Promise<void>} promise that resolves to the result of the sign-in process.
|
|
177
244
|
*/
|
|
178
245
|
async signIn(params) {
|
|
179
246
|
return this._webSignerClient.webauthnSignIn(params);
|
|
@@ -182,7 +249,40 @@ var PasskeysModule = class {
|
|
|
182
249
|
|
|
183
250
|
// src/modules/auth/oauth/google.ts
|
|
184
251
|
import * as jose from "jose";
|
|
185
|
-
|
|
252
|
+
|
|
253
|
+
// src/lib/sha256.ts
|
|
254
|
+
var LibSha256 = class {
|
|
255
|
+
/**
|
|
256
|
+
* Compute SHA-256 and return hex string using Web Crypto when available.
|
|
257
|
+
* Falls back to Node's crypto.createHash when running in Node.
|
|
258
|
+
*/
|
|
259
|
+
static async sha256Hex(input) {
|
|
260
|
+
let data;
|
|
261
|
+
if (typeof input === "string") {
|
|
262
|
+
data = new TextEncoder().encode(input);
|
|
263
|
+
} else if (input instanceof Uint8Array) {
|
|
264
|
+
data = input;
|
|
265
|
+
} else {
|
|
266
|
+
data = new Uint8Array(input);
|
|
267
|
+
}
|
|
268
|
+
const subtle = typeof globalThis !== "undefined" && globalThis.crypto?.subtle ? globalThis.crypto.subtle : void 0;
|
|
269
|
+
if (subtle) {
|
|
270
|
+
const hash = await subtle.digest("SHA-256", data);
|
|
271
|
+
return Array.from(new Uint8Array(hash)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
272
|
+
}
|
|
273
|
+
try {
|
|
274
|
+
const nodeCrypto = __require("crypto");
|
|
275
|
+
const hash = nodeCrypto.createHash("sha256").update(data).digest("hex");
|
|
276
|
+
return hash;
|
|
277
|
+
} catch {
|
|
278
|
+
throw new Error(
|
|
279
|
+
"No crypto provider available. Provide a global crypto.subtle or run in Node 18+."
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
// src/modules/auth/oauth/google.ts
|
|
186
286
|
var GoogleModule = class {
|
|
187
287
|
constructor(_webSignerClient) {
|
|
188
288
|
this._webSignerClient = _webSignerClient;
|
|
@@ -200,7 +300,7 @@ var GoogleModule = class {
|
|
|
200
300
|
).href;
|
|
201
301
|
url.searchParams.set("redirect_uri", internalUrl);
|
|
202
302
|
const publicKey = await this._webSignerClient.getIframePublicKey();
|
|
203
|
-
const nonce =
|
|
303
|
+
const nonce = await LibSha256.sha256Hex(publicKey);
|
|
204
304
|
url.searchParams.set("nonce", nonce);
|
|
205
305
|
const state = new jose.UnsecuredJWT({
|
|
206
306
|
apiKey: this._webSignerClient.configuration.apiKey,
|
|
@@ -214,18 +314,6 @@ var GoogleModule = class {
|
|
|
214
314
|
}
|
|
215
315
|
};
|
|
216
316
|
|
|
217
|
-
// src/errors/SDKError.ts
|
|
218
|
-
var SDKError = class extends Error {
|
|
219
|
-
_props;
|
|
220
|
-
constructor(message, props) {
|
|
221
|
-
super(message);
|
|
222
|
-
this._props = props;
|
|
223
|
-
}
|
|
224
|
-
get message() {
|
|
225
|
-
return this._props.message;
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
|
|
229
317
|
// src/errors/BadRequestError.ts
|
|
230
318
|
var BadRequestError = class _BadRequestError extends SDKError {
|
|
231
319
|
constructor(props) {
|
|
@@ -276,7 +364,6 @@ var FacebookModule = class {
|
|
|
276
364
|
|
|
277
365
|
// src/modules/auth/oauth/apple.ts
|
|
278
366
|
import * as jose3 from "jose";
|
|
279
|
-
import { sha256 as sha2562 } from "sha.js";
|
|
280
367
|
var AppleModule = class {
|
|
281
368
|
constructor(_webSignerClient) {
|
|
282
369
|
this._webSignerClient = _webSignerClient;
|
|
@@ -294,7 +381,7 @@ var AppleModule = class {
|
|
|
294
381
|
).href;
|
|
295
382
|
url.searchParams.set("redirect_uri", internalUrl);
|
|
296
383
|
const publicKey = await this._webSignerClient.getIframePublicKey();
|
|
297
|
-
const nonce =
|
|
384
|
+
const nonce = await LibSha256.sha256Hex(publicKey);
|
|
298
385
|
url.searchParams.set("nonce", nonce);
|
|
299
386
|
const state = new jose3.UnsecuredJWT({
|
|
300
387
|
apiKey: this._webSignerClient.configuration.apiKey,
|
|
@@ -414,13 +501,29 @@ import { IframeStamper } from "@turnkey/iframe-stamper";
|
|
|
414
501
|
import { WebauthnStamper } from "@turnkey/webauthn-stamper";
|
|
415
502
|
|
|
416
503
|
// src/lib/base64.ts
|
|
417
|
-
import { Buffer } from "buffer";
|
|
418
504
|
var LibBase64 = class {
|
|
505
|
+
// Convert an ArrayBuffer to base64url (no padding)
|
|
419
506
|
static fromBuffer(buffer) {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
507
|
+
const bytes = new Uint8Array(buffer);
|
|
508
|
+
const CHUNK_SIZE = 32768;
|
|
509
|
+
let binary = "";
|
|
510
|
+
for (let i = 0; i < bytes.length; i += CHUNK_SIZE) {
|
|
511
|
+
const chunk = bytes.subarray(i, i + CHUNK_SIZE);
|
|
512
|
+
binary += String.fromCharCode(...chunk);
|
|
513
|
+
}
|
|
514
|
+
const base64 = typeof btoa === "function" ? btoa(binary) : Buffer.from(bytes).toString("base64");
|
|
515
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
516
|
+
}
|
|
517
|
+
// Convert base64url (no padding) to ArrayBuffer
|
|
518
|
+
static toBuffer(base64url) {
|
|
519
|
+
let base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
|
|
520
|
+
const pad = base64.length % 4;
|
|
521
|
+
if (pad) base64 += "=".repeat(4 - pad);
|
|
522
|
+
const binary = typeof atob === "function" ? atob(base64) : Buffer.from(base64, "base64").toString("binary");
|
|
523
|
+
const len = binary.length;
|
|
524
|
+
const bytes = new Uint8Array(len);
|
|
525
|
+
for (let i = 0; i < len; i++) bytes[i] = binary.charCodeAt(i);
|
|
526
|
+
return bytes.buffer;
|
|
424
527
|
}
|
|
425
528
|
};
|
|
426
529
|
|
|
@@ -449,13 +552,6 @@ var UnauthorizedError = class _UnauthorizedError extends SDKError {
|
|
|
449
552
|
}
|
|
450
553
|
};
|
|
451
554
|
|
|
452
|
-
// src/errors/NotFoundError.ts
|
|
453
|
-
var NotFoundError = class _NotFoundError extends SDKError {
|
|
454
|
-
constructor(props) {
|
|
455
|
-
super(_NotFoundError.name, props);
|
|
456
|
-
}
|
|
457
|
-
};
|
|
458
|
-
|
|
459
555
|
// src/errors/GenericError.ts
|
|
460
556
|
var GenericError = class _GenericError extends SDKError {
|
|
461
557
|
constructor(props) {
|
|
@@ -470,23 +566,8 @@ var UnauthenticatedError = class _UnauthenticatedError extends SDKError {
|
|
|
470
566
|
}
|
|
471
567
|
};
|
|
472
568
|
|
|
473
|
-
// src/types/routes.ts
|
|
474
|
-
var ROUTE_METHOD_MAP = {
|
|
475
|
-
"/v1/signup": "POST",
|
|
476
|
-
"/v1/email-auth": "POST",
|
|
477
|
-
"/v1/lookup": "POST",
|
|
478
|
-
"/v1/signin": "POST",
|
|
479
|
-
"/v1/sign": "POST",
|
|
480
|
-
"/v1/oauth/init": "POST",
|
|
481
|
-
"/v1/refresh": "POST",
|
|
482
|
-
"/v1/csrf-token": "GET",
|
|
483
|
-
"/v1/logout": "POST",
|
|
484
|
-
"/v1/me": "GET"
|
|
485
|
-
};
|
|
486
|
-
|
|
487
569
|
// src/signer/index.ts
|
|
488
|
-
import {
|
|
489
|
-
import { differenceInMilliseconds, isBefore, subMinutes } from "date-fns";
|
|
570
|
+
import { decodeJwt } from "jose";
|
|
490
571
|
var SignerClient = class {
|
|
491
572
|
_turnkeyClient;
|
|
492
573
|
_configuration;
|
|
@@ -514,14 +595,14 @@ var SignerClient = class {
|
|
|
514
595
|
async getUser() {
|
|
515
596
|
if (this._sessionStore.user) return this._sessionStore.user;
|
|
516
597
|
try {
|
|
517
|
-
const user = await this.request("/v1/me");
|
|
598
|
+
const user = await this.request("/v1/me", "GET");
|
|
518
599
|
this._sessionStore.user = user;
|
|
519
600
|
return user;
|
|
520
601
|
} catch (error) {
|
|
521
602
|
if (error instanceof UnauthorizedError) {
|
|
522
603
|
try {
|
|
523
604
|
await this._refreshToken();
|
|
524
|
-
const user = await this.request("/v1/me");
|
|
605
|
+
const user = await this.request("/v1/me", "GET");
|
|
525
606
|
this._sessionStore.user = user;
|
|
526
607
|
return user;
|
|
527
608
|
} catch (error2) {
|
|
@@ -569,8 +650,8 @@ var SignerClient = class {
|
|
|
569
650
|
}
|
|
570
651
|
_isTokenExpired(token) {
|
|
571
652
|
try {
|
|
572
|
-
const decoded =
|
|
573
|
-
if (decoded.exp) {
|
|
653
|
+
const decoded = decodeJwt(token);
|
|
654
|
+
if (typeof decoded.exp === "number") {
|
|
574
655
|
return decoded.exp * 1e3 <= Date.now();
|
|
575
656
|
}
|
|
576
657
|
return true;
|
|
@@ -581,7 +662,7 @@ var SignerClient = class {
|
|
|
581
662
|
async logout() {
|
|
582
663
|
if (this._refreshTimer) clearTimeout(this._refreshTimer);
|
|
583
664
|
this._refreshTimer = void 0;
|
|
584
|
-
await this.request("/v1/logout");
|
|
665
|
+
await this.request("/v1/logout", "POST");
|
|
585
666
|
this._sessionStore.clearAll();
|
|
586
667
|
}
|
|
587
668
|
async signRawMessage(msg) {
|
|
@@ -601,7 +682,7 @@ var SignerClient = class {
|
|
|
601
682
|
signWith: this._sessionStore.user.walletAddress
|
|
602
683
|
}
|
|
603
684
|
});
|
|
604
|
-
const { signature } = await this.request("/v1/sign", {
|
|
685
|
+
const { signature } = await this.request("/v1/sign", "POST", {
|
|
605
686
|
stampedRequest
|
|
606
687
|
});
|
|
607
688
|
return signature;
|
|
@@ -614,7 +695,7 @@ var SignerClient = class {
|
|
|
614
695
|
}
|
|
615
696
|
async lookUpUser(email) {
|
|
616
697
|
try {
|
|
617
|
-
const { subOrgId } = await this.request("/v1/lookup", { email });
|
|
698
|
+
const { subOrgId } = await this.request("/v1/lookup", "POST", { email });
|
|
618
699
|
return subOrgId;
|
|
619
700
|
} catch (error) {
|
|
620
701
|
if (!(error instanceof SDKError)) throw error;
|
|
@@ -635,9 +716,13 @@ var SignerClient = class {
|
|
|
635
716
|
const stampedRequest = await this._turnkeyClient.stampGetWhoami({
|
|
636
717
|
organizationId: orgId
|
|
637
718
|
});
|
|
638
|
-
const { user, token, csrfToken } = await this.request(
|
|
639
|
-
|
|
640
|
-
|
|
719
|
+
const { user, token, csrfToken } = await this.request(
|
|
720
|
+
"/v1/signin",
|
|
721
|
+
"POST",
|
|
722
|
+
{
|
|
723
|
+
stampedRequest
|
|
724
|
+
}
|
|
725
|
+
);
|
|
641
726
|
const credentialId = (() => {
|
|
642
727
|
try {
|
|
643
728
|
return JSON.parse(stampedRequest?.stamp.stampHeaderValue).credentialId;
|
|
@@ -653,7 +738,7 @@ var SignerClient = class {
|
|
|
653
738
|
this._sessionStore.csrfToken = csrfToken;
|
|
654
739
|
this._scheduleRefresh(token);
|
|
655
740
|
}
|
|
656
|
-
async request(route, body) {
|
|
741
|
+
async request(route, method, body) {
|
|
657
742
|
const url = new URL(`${route}`, this._configuration.apiUrl);
|
|
658
743
|
const token = this._sessionStore.token;
|
|
659
744
|
const csrfToken = this._sessionStore.csrfToken;
|
|
@@ -668,8 +753,8 @@ var SignerClient = class {
|
|
|
668
753
|
headers["X-CSRF-Token"] = csrfToken;
|
|
669
754
|
}
|
|
670
755
|
const response = await fetch(url, {
|
|
671
|
-
method
|
|
672
|
-
body: JSON.stringify(body),
|
|
756
|
+
method,
|
|
757
|
+
body: method === "POST" ? JSON.stringify(body) : void 0,
|
|
673
758
|
headers,
|
|
674
759
|
credentials: "include"
|
|
675
760
|
});
|
|
@@ -692,13 +777,24 @@ var SignerClient = class {
|
|
|
692
777
|
}
|
|
693
778
|
return { ...data };
|
|
694
779
|
}
|
|
780
|
+
/**
|
|
781
|
+
* Compute milliseconds until refresh time.
|
|
782
|
+
* - expSeconds is the JWT exp claim (seconds).
|
|
783
|
+
* - earlyMinutes is how many minutes before exp to refresh (default 2).
|
|
784
|
+
* Returns 0 if refresh time is already past.
|
|
785
|
+
*/
|
|
786
|
+
_computeRefreshDelayMs(expSeconds, earlyMinutes = 2) {
|
|
787
|
+
const expiryMs = expSeconds * 1e3;
|
|
788
|
+
const refreshMs = expiryMs - earlyMinutes * 60 * 1e3;
|
|
789
|
+
const now = Date.now();
|
|
790
|
+
const delay = refreshMs - now;
|
|
791
|
+
return delay <= 0 ? 0 : delay;
|
|
792
|
+
}
|
|
695
793
|
_scheduleRefresh(token) {
|
|
696
794
|
try {
|
|
697
|
-
const decoded =
|
|
795
|
+
const decoded = decodeJwt(token);
|
|
698
796
|
if (!decoded.exp) return;
|
|
699
|
-
const
|
|
700
|
-
const refreshDate = subMinutes(expiryDate, 2);
|
|
701
|
-
const delay = isBefore(refreshDate, /* @__PURE__ */ new Date()) ? 0 : differenceInMilliseconds(refreshDate, /* @__PURE__ */ new Date());
|
|
797
|
+
const delay = this._computeRefreshDelayMs(decoded.exp, 2);
|
|
702
798
|
if (this._refreshTimer) clearTimeout(this._refreshTimer);
|
|
703
799
|
this._refreshTimer = setTimeout(() => {
|
|
704
800
|
this._refreshTimer = void 0;
|
|
@@ -714,10 +810,10 @@ var SignerClient = class {
|
|
|
714
810
|
const RETRY_DELAY_MS = 5e3;
|
|
715
811
|
try {
|
|
716
812
|
if (!this._sessionStore.csrfToken) {
|
|
717
|
-
const { csrfToken } = await this.request("/v1/csrf-token");
|
|
813
|
+
const { csrfToken } = await this.request("/v1/csrf-token", "GET");
|
|
718
814
|
this._sessionStore.csrfToken = csrfToken;
|
|
719
815
|
}
|
|
720
|
-
const refreshPromise = this.request("/v1/refresh");
|
|
816
|
+
const refreshPromise = this.request("/v1/refresh", "POST");
|
|
721
817
|
const data = await Promise.race([
|
|
722
818
|
refreshPromise,
|
|
723
819
|
new Promise(
|
|
@@ -832,7 +928,7 @@ var WebSignerClient = class extends SignerClient {
|
|
|
832
928
|
* @param {string} provider provider for which we are getting the URL, currently google or apple
|
|
833
929
|
*/
|
|
834
930
|
async getOAuthInitUrl(provider) {
|
|
835
|
-
const { url } = await this.request("/v1/oauth/init", {
|
|
931
|
+
const { url } = await this.request("/v1/oauth/init", "POST", {
|
|
836
932
|
provider
|
|
837
933
|
});
|
|
838
934
|
return url;
|
|
@@ -863,21 +959,65 @@ var WebSignerClient = class extends SignerClient {
|
|
|
863
959
|
}
|
|
864
960
|
}
|
|
865
961
|
/**
|
|
866
|
-
*
|
|
962
|
+
* Handles auth user process with email according to the method of the used app.
|
|
867
963
|
*
|
|
868
|
-
* @param {EmailInitializeAuthParams} params
|
|
964
|
+
* @param {EmailInitializeAuthParams} params params needed for the initialization of the auth process
|
|
869
965
|
*/
|
|
870
966
|
async emailAuth(params) {
|
|
871
|
-
const
|
|
872
|
-
if (
|
|
873
|
-
await this.
|
|
967
|
+
const method = await this._getEmailAuthMethod();
|
|
968
|
+
if (method === "magiclink") {
|
|
969
|
+
const existingUserSubOrgId = await this.lookUpUser(params.email);
|
|
970
|
+
if (!existingUserSubOrgId) {
|
|
971
|
+
await this._createAccount({ method: "email", ...params });
|
|
972
|
+
} else {
|
|
973
|
+
await this._signInWithEmail(params);
|
|
974
|
+
}
|
|
975
|
+
return { method };
|
|
976
|
+
} else if (method === "otp") {
|
|
977
|
+
const { init } = await this._initOtpAuth({ email: params.email });
|
|
978
|
+
if (!init?.otpId)
|
|
979
|
+
throw new NotFoundError({ message: "No OTP init response returned." });
|
|
980
|
+
return {
|
|
981
|
+
method,
|
|
982
|
+
otpId: init.otpId
|
|
983
|
+
};
|
|
874
984
|
} else {
|
|
875
|
-
|
|
985
|
+
throw new Error("Invalid email authentication method.");
|
|
876
986
|
}
|
|
877
987
|
}
|
|
878
988
|
async getIframePublicKey() {
|
|
879
989
|
return await this._initIframeStamper();
|
|
880
990
|
}
|
|
991
|
+
/**
|
|
992
|
+
* Verifies the provided otp code.
|
|
993
|
+
*
|
|
994
|
+
* @param {OtpAuthParams} params params needed for otp code verification
|
|
995
|
+
*/
|
|
996
|
+
async otpAuth(params) {
|
|
997
|
+
return this.request("/v1/otp-auth", "POST", {
|
|
998
|
+
auth: {
|
|
999
|
+
email: params.email,
|
|
1000
|
+
otpCode: params.otpCode,
|
|
1001
|
+
otpId: params.otpId,
|
|
1002
|
+
targetPublicKey: await this.getIframePublicKey()
|
|
1003
|
+
}
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Gets the email authentication method of the app.
|
|
1008
|
+
*/
|
|
1009
|
+
async _getEmailAuthMethod() {
|
|
1010
|
+
const { method } = await this.request("/v1/email-auth", "GET");
|
|
1011
|
+
return method;
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
* Starts email authentication process via otp.
|
|
1015
|
+
*/
|
|
1016
|
+
async _initOtpAuth(params) {
|
|
1017
|
+
return this.request("/v1/otp-auth", "POST", {
|
|
1018
|
+
init: { email: params.email }
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
881
1021
|
/**
|
|
882
1022
|
* Completes the authentication process with a credential bundle.
|
|
883
1023
|
*
|
|
@@ -924,7 +1064,7 @@ var WebSignerClient = class extends SignerClient {
|
|
|
924
1064
|
expirationSeconds,
|
|
925
1065
|
redirectUrl
|
|
926
1066
|
}) {
|
|
927
|
-
return this.request("/v1/email-auth", {
|
|
1067
|
+
return this.request("/v1/email-auth", "POST", {
|
|
928
1068
|
email,
|
|
929
1069
|
targetPublicKey: await this.getIframePublicKey(),
|
|
930
1070
|
expirationSeconds,
|
|
@@ -940,13 +1080,17 @@ var WebSignerClient = class extends SignerClient {
|
|
|
940
1080
|
const { challenge, attestation } = await this._webauthnGenerateAttestation(
|
|
941
1081
|
params.email
|
|
942
1082
|
);
|
|
943
|
-
const { user, token, csrfToken } = await this.request(
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
1083
|
+
const { user, token, csrfToken } = await this.request(
|
|
1084
|
+
"/v1/signup",
|
|
1085
|
+
"POST",
|
|
1086
|
+
{
|
|
1087
|
+
passkey: {
|
|
1088
|
+
challenge: LibBase64.fromBuffer(challenge),
|
|
1089
|
+
attestation
|
|
1090
|
+
},
|
|
1091
|
+
email: params.email
|
|
1092
|
+
}
|
|
1093
|
+
);
|
|
950
1094
|
this._sessionStore.user = {
|
|
951
1095
|
...user,
|
|
952
1096
|
credentialId: attestation.credentialId
|
|
@@ -963,7 +1107,7 @@ var WebSignerClient = class extends SignerClient {
|
|
|
963
1107
|
*/
|
|
964
1108
|
async _createEmailAccount(params) {
|
|
965
1109
|
const { email, expirationSeconds, redirectUrl } = params;
|
|
966
|
-
const response = await this.request("/v1/signup", {
|
|
1110
|
+
const response = await this.request("/v1/signup", "POST", {
|
|
967
1111
|
email,
|
|
968
1112
|
iframe: {
|
|
969
1113
|
targetPublicKey: await this.getIframePublicKey(),
|