@stackframe/stack 2.8.47 → 2.8.49
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/CHANGELOG.md +20 -0
- package/dist/esm/integrations/convex.js +6 -0
- package/dist/esm/integrations/convex.js.map +1 -1
- package/dist/esm/lib/cookie.js +57 -14
- package/dist/esm/lib/cookie.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js +10 -0
- package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js +222 -26
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/common.js +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/common.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
- package/dist/index.d.mts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/integrations/convex.js +6 -0
- package/dist/integrations/convex.js.map +1 -1
- package/dist/lib/cookie.js +59 -14
- package/dist/lib/cookie.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.js +10 -0
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/client-app-impl.js +221 -25
- package/dist/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/common.js +1 -1
- package/dist/lib/stack-app/apps/implementations/common.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/server-app-impl.js +1 -1
- package/dist/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
- package/package.json +4 -4
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { WebAuthnError, startAuthentication, startRegistration } from "@simplewebauthn/browser";
|
|
3
3
|
import { KnownErrors, StackClientInterface } from "@stackframe/stack-shared";
|
|
4
4
|
import { InternalSession } from "@stackframe/stack-shared/dist/sessions";
|
|
5
|
+
import { encodeBase32 } from "@stackframe/stack-shared/dist/utils/bytes";
|
|
5
6
|
import { scrambleDuringCompileTime } from "@stackframe/stack-shared/dist/utils/compile-time";
|
|
6
7
|
import { isBrowserLike } from "@stackframe/stack-shared/dist/utils/env";
|
|
7
8
|
import { StackAssertionError, captureError, throwErr } from "@stackframe/stack-shared/dist/utils/errors";
|
|
@@ -19,7 +20,7 @@ import * as NextNavigationUnscrambled from "next/navigation";
|
|
|
19
20
|
import React, { useCallback, useMemo } from "react";
|
|
20
21
|
import { constructRedirectUrl } from "../../../../utils/url.js";
|
|
21
22
|
import { addNewOAuthProviderOrScope, callOAuthCallback, signInWithOAuth } from "../../../auth.js";
|
|
22
|
-
import { createBrowserCookieHelper, createCookieHelper, createPlaceholderCookieHelper, deleteCookieClient,
|
|
23
|
+
import { createBrowserCookieHelper, createCookieHelper, createPlaceholderCookieHelper, deleteCookieClient, isSecure as isSecureCookieContext, setOrDeleteCookie, setOrDeleteCookieClient } from "../../../cookie.js";
|
|
23
24
|
import { apiKeyCreationOptionsToCrud } from "../../api-keys/index.js";
|
|
24
25
|
import { stackAppInternalsSymbol } from "../../common.js";
|
|
25
26
|
import { contactChannelCreateOptionsToCrud, contactChannelUpdateOptionsToCrud } from "../../contact-channels/index.js";
|
|
@@ -27,6 +28,7 @@ import { adminProjectCreateOptionsToCrud } from "../../projects/index.js";
|
|
|
27
28
|
import { teamCreateOptionsToCrud, teamUpdateOptionsToCrud } from "../../teams/index.js";
|
|
28
29
|
import { attachUserDestructureGuard, userUpdateOptionsToCrud } from "../../users/index.js";
|
|
29
30
|
import { clientVersion, createCache, createCacheBySession, createEmptyTokenStore, getBaseUrl, getDefaultExtraRequestHeaders, getDefaultProjectId, getDefaultPublishableClientKey, getUrls, resolveConstructorOptions } from "./common.js";
|
|
31
|
+
import { parseJson } from "@stackframe/stack-shared/dist/utils/json";
|
|
30
32
|
import { useAsyncCache } from "./common.js";
|
|
31
33
|
import * as sc from "@stackframe/stack-sc";
|
|
32
34
|
import { cookies } from "@stackframe/stack-sc";
|
|
@@ -180,11 +182,15 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
180
182
|
this._convexPartialUserCache = createCache(
|
|
181
183
|
async ([ctx]) => await this._getPartialUserFromConvex(ctx)
|
|
182
184
|
);
|
|
185
|
+
this._trustedParentDomainCache = createCache(
|
|
186
|
+
async ([domain]) => await this._getTrustedParentDomain(domain)
|
|
187
|
+
);
|
|
183
188
|
this._anonymousSignUpInProgress = null;
|
|
184
189
|
this._memoryTokenStore = createEmptyTokenStore();
|
|
185
190
|
this._nextServerCookiesTokenStores = /* @__PURE__ */ new WeakMap();
|
|
186
191
|
this._requestTokenStores = /* @__PURE__ */ new WeakMap();
|
|
187
192
|
this._storedBrowserCookieTokenStore = null;
|
|
193
|
+
this._mostRecentQueuedCookieRefreshIndex = 0;
|
|
188
194
|
/**
|
|
189
195
|
* A map from token stores and session keys to sessions.
|
|
190
196
|
*
|
|
@@ -309,13 +315,90 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
309
315
|
runAsynchronously(this._checkFeatureSupport(name, options));
|
|
310
316
|
throw new StackAssertionError(`${name} is not currently supported. Please reach out to Stack support for more information.`);
|
|
311
317
|
}
|
|
318
|
+
get _legacyRefreshTokenCookieName() {
|
|
319
|
+
return `stack-refresh-${this.projectId}`;
|
|
320
|
+
}
|
|
312
321
|
get _refreshTokenCookieName() {
|
|
313
322
|
return `stack-refresh-${this.projectId}`;
|
|
314
323
|
}
|
|
324
|
+
_getRefreshTokenDefaultCookieNameForSecure(secure) {
|
|
325
|
+
return `${secure ? "__Host-" : ""}${this._refreshTokenCookieName}--default`;
|
|
326
|
+
}
|
|
327
|
+
_getCustomRefreshCookieName(domain) {
|
|
328
|
+
const encoded = encodeBase32(new TextEncoder().encode(domain.toLowerCase()));
|
|
329
|
+
return `${this._refreshTokenCookieName}--custom-${encoded}`;
|
|
330
|
+
}
|
|
331
|
+
_formatRefreshCookieValue(refreshToken, updatedAt) {
|
|
332
|
+
return JSON.stringify({
|
|
333
|
+
refresh_token: refreshToken,
|
|
334
|
+
updated_at_millis: updatedAt
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
_formatAccessCookieValue(refreshToken, accessToken) {
|
|
338
|
+
return refreshToken && accessToken ? JSON.stringify([refreshToken, accessToken]) : null;
|
|
339
|
+
}
|
|
340
|
+
_parseStructuredRefreshCookie(value) {
|
|
341
|
+
if (!value) {
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
const parsed = parseJson(value);
|
|
345
|
+
if (parsed.status !== "ok" || typeof parsed.data !== "object" || parsed.data === null) {
|
|
346
|
+
console.warn("Failed to parse structured refresh cookie");
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
const data = parsed.data;
|
|
350
|
+
const refreshToken = "refresh_token" in data && typeof data.refresh_token === "string" ? data.refresh_token : null;
|
|
351
|
+
const updatedAt = "updated_at_millis" in data && typeof data.updated_at_millis === "number" ? data.updated_at_millis : null;
|
|
352
|
+
if (!refreshToken) {
|
|
353
|
+
console.warn("Refresh token not found in structured refresh cookie");
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
refreshToken,
|
|
358
|
+
updatedAt
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
_extractRefreshTokenFromCookieMap(cookies2) {
|
|
362
|
+
const { legacyNames, structuredPrefixes } = this._getRefreshTokenCookieNamePatterns();
|
|
363
|
+
for (const name of legacyNames) {
|
|
364
|
+
const value = cookies2[name];
|
|
365
|
+
if (value) {
|
|
366
|
+
return { refreshToken: value, updatedAt: null };
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
let selected = null;
|
|
370
|
+
for (const [name, value] of Object.entries(cookies2)) {
|
|
371
|
+
if (!structuredPrefixes.some((prefix) => name.startsWith(prefix))) continue;
|
|
372
|
+
const parsed = this._parseStructuredRefreshCookie(value);
|
|
373
|
+
if (!parsed) continue;
|
|
374
|
+
const candidateUpdatedAt = parsed.updatedAt ?? Number.NEGATIVE_INFINITY;
|
|
375
|
+
const selectedUpdatedAt = selected?.updatedAt ?? Number.NEGATIVE_INFINITY;
|
|
376
|
+
if (!selected || candidateUpdatedAt > selectedUpdatedAt) {
|
|
377
|
+
selected = parsed;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (!selected) {
|
|
381
|
+
return { refreshToken: null, updatedAt: null };
|
|
382
|
+
}
|
|
383
|
+
return {
|
|
384
|
+
refreshToken: selected.refreshToken,
|
|
385
|
+
updatedAt: selected.updatedAt ?? null
|
|
386
|
+
};
|
|
387
|
+
}
|
|
315
388
|
_getTokensFromCookies(cookies2) {
|
|
316
|
-
const refreshToken = cookies2
|
|
317
|
-
const
|
|
318
|
-
|
|
389
|
+
const { refreshToken } = this._extractRefreshTokenFromCookieMap(cookies2);
|
|
390
|
+
const accessTokenCookie = cookies2[this._accessTokenCookieName] ?? null;
|
|
391
|
+
let accessToken = null;
|
|
392
|
+
if (accessTokenCookie && accessTokenCookie.startsWith('["')) {
|
|
393
|
+
const parsed = parseJson(accessTokenCookie);
|
|
394
|
+
if (parsed.status === "ok" && typeof parsed.data === "object" && parsed.data !== null && Array.isArray(parsed.data) && parsed.data.length === 2 && typeof parsed.data[0] === "string" && typeof parsed.data[1] === "string") {
|
|
395
|
+
if (parsed.data[0] === refreshToken) {
|
|
396
|
+
accessToken = parsed.data[1];
|
|
397
|
+
}
|
|
398
|
+
} else {
|
|
399
|
+
console.warn("Access token cookie has invalid format");
|
|
400
|
+
}
|
|
401
|
+
}
|
|
319
402
|
return {
|
|
320
403
|
refreshToken,
|
|
321
404
|
accessToken
|
|
@@ -324,17 +407,98 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
324
407
|
get _accessTokenCookieName() {
|
|
325
408
|
return `stack-access`;
|
|
326
409
|
}
|
|
410
|
+
_getAllBrowserCookies() {
|
|
411
|
+
if (!isBrowserLike()) {
|
|
412
|
+
throw new StackAssertionError("Cannot get browser cookies on the server!");
|
|
413
|
+
}
|
|
414
|
+
return cookie.parse(document.cookie || "");
|
|
415
|
+
}
|
|
416
|
+
_getRefreshTokenCookieNamePatterns() {
|
|
417
|
+
return {
|
|
418
|
+
legacyNames: [this._legacyRefreshTokenCookieName, "stack-refresh"],
|
|
419
|
+
structuredPrefixes: [
|
|
420
|
+
`${this._refreshTokenCookieName}--`,
|
|
421
|
+
`__Host-${this._refreshTokenCookieName}--`
|
|
422
|
+
]
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
_collectRefreshTokenCookieNames(cookies2) {
|
|
426
|
+
const { legacyNames, structuredPrefixes } = this._getRefreshTokenCookieNamePatterns();
|
|
427
|
+
const names = /* @__PURE__ */ new Set();
|
|
428
|
+
for (const name of legacyNames) {
|
|
429
|
+
if (cookies2[name]) {
|
|
430
|
+
names.add(name);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
for (const name of Object.keys(cookies2)) {
|
|
434
|
+
if (structuredPrefixes.some((prefix) => name.startsWith(prefix))) {
|
|
435
|
+
names.add(name);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return names;
|
|
439
|
+
}
|
|
440
|
+
_prepareRefreshCookieUpdate(existingCookies, refreshToken, accessToken, defaultCookieName) {
|
|
441
|
+
const cookieNames = this._collectRefreshTokenCookieNames(existingCookies);
|
|
442
|
+
cookieNames.delete(defaultCookieName);
|
|
443
|
+
const updatedAt = refreshToken ? Date.now() : null;
|
|
444
|
+
const refreshCookieValue = refreshToken && updatedAt !== null ? this._formatRefreshCookieValue(refreshToken, updatedAt) : null;
|
|
445
|
+
const accessTokenPayload = this._formatAccessCookieValue(refreshToken, accessToken);
|
|
446
|
+
return {
|
|
447
|
+
updatedAt,
|
|
448
|
+
refreshCookieValue,
|
|
449
|
+
accessTokenPayload,
|
|
450
|
+
cookieNamesToDelete: [...cookieNames]
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
_queueCustomRefreshCookieUpdate(refreshToken, updatedAt, context) {
|
|
454
|
+
runAsynchronously(async () => {
|
|
455
|
+
this._mostRecentQueuedCookieRefreshIndex++;
|
|
456
|
+
const updateIndex = this._mostRecentQueuedCookieRefreshIndex;
|
|
457
|
+
let hostname;
|
|
458
|
+
if (isBrowserLike()) {
|
|
459
|
+
hostname = window.location.hostname;
|
|
460
|
+
}
|
|
461
|
+
hostname = (await sc.headers?.())?.get("host");
|
|
462
|
+
if (!hostname) {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
const domain = await this._trustedParentDomainCache.getOrWait([hostname], "read-write");
|
|
466
|
+
const setCookie = async (targetDomain, value2) => {
|
|
467
|
+
const name = this._getCustomRefreshCookieName(targetDomain);
|
|
468
|
+
const options = { maxAge: 60 * 60 * 24 * 365, domain: targetDomain, noOpIfServerComponent: true };
|
|
469
|
+
if (context === "browser") {
|
|
470
|
+
setOrDeleteCookieClient(name, value2, options);
|
|
471
|
+
} else {
|
|
472
|
+
await setOrDeleteCookie(name, value2, options);
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
if (domain.status === "error" || !domain.data || updateIndex !== this._mostRecentQueuedCookieRefreshIndex) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
const value = refreshToken && updatedAt ? this._formatRefreshCookieValue(refreshToken, updatedAt) : null;
|
|
479
|
+
await setCookie(domain.data, value);
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
async _getTrustedParentDomain(currentDomain) {
|
|
483
|
+
const project = Result.orThrow(await this._interface.getClientProject());
|
|
484
|
+
const domains = project.config.domains.map((d) => d.domain.trim().replace(/^https?:\/\//, "").split("/")[0]?.toLowerCase());
|
|
485
|
+
const trustedWildcards = domains.filter((d) => d.startsWith("**."));
|
|
486
|
+
const parts = currentDomain.split(".");
|
|
487
|
+
for (let i = parts.length - 2; i >= 0; i--) {
|
|
488
|
+
const parentDomain = parts.slice(i).join(".");
|
|
489
|
+
if (domains.includes(parentDomain) && trustedWildcards.includes("**." + parentDomain)) {
|
|
490
|
+
return parentDomain;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return null;
|
|
494
|
+
}
|
|
327
495
|
_getBrowserCookieTokenStore() {
|
|
328
496
|
if (!isBrowserLike()) {
|
|
329
497
|
throw new Error("Cannot use cookie token store on the server!");
|
|
330
498
|
}
|
|
331
499
|
if (this._storedBrowserCookieTokenStore === null) {
|
|
332
500
|
const getCurrentValue = (old) => {
|
|
333
|
-
const tokens = this._getTokensFromCookies(
|
|
334
|
-
refreshTokenCookie: getCookieClient(this._refreshTokenCookieName) ?? getCookieClient("stack-refresh"),
|
|
335
|
-
// keep old cookie name for backwards-compatibility
|
|
336
|
-
accessTokenCookie: getCookieClient(this._accessTokenCookieName)
|
|
337
|
-
});
|
|
501
|
+
const tokens = this._getTokensFromCookies(this._getAllBrowserCookies());
|
|
338
502
|
return {
|
|
339
503
|
refreshToken: tokens.refreshToken,
|
|
340
504
|
accessToken: tokens.accessToken ?? (old?.refreshToken === tokens.refreshToken ? old.accessToken : null)
|
|
@@ -353,9 +517,19 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
353
517
|
}, 100);
|
|
354
518
|
this._storedBrowserCookieTokenStore.onChange((value) => {
|
|
355
519
|
try {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
520
|
+
const refreshToken = value.refreshToken;
|
|
521
|
+
const secure = window.location.protocol === "https:";
|
|
522
|
+
const defaultName = this._getRefreshTokenDefaultCookieNameForSecure(secure);
|
|
523
|
+
const { updatedAt, refreshCookieValue, accessTokenPayload, cookieNamesToDelete } = this._prepareRefreshCookieUpdate(
|
|
524
|
+
this._getAllBrowserCookies(),
|
|
525
|
+
refreshToken,
|
|
526
|
+
value.accessToken ?? null,
|
|
527
|
+
defaultName
|
|
528
|
+
);
|
|
529
|
+
setOrDeleteCookieClient(defaultName, refreshCookieValue, { maxAge: 60 * 60 * 24 * 365, secure });
|
|
530
|
+
setOrDeleteCookieClient(this._accessTokenCookieName, accessTokenPayload, { maxAge: 60 * 60 * 24 });
|
|
531
|
+
cookieNamesToDelete.forEach((name) => deleteCookieClient(name));
|
|
532
|
+
this._queueCustomRefreshCookieUpdate(refreshToken, updatedAt, "browser");
|
|
359
533
|
hasSucceededInWriting = true;
|
|
360
534
|
} catch (e) {
|
|
361
535
|
if (!isBrowserLike()) {
|
|
@@ -378,18 +552,31 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
378
552
|
if (isBrowserLike()) {
|
|
379
553
|
return this._getBrowserCookieTokenStore();
|
|
380
554
|
} else {
|
|
381
|
-
const tokens = this._getTokensFromCookies(
|
|
382
|
-
refreshTokenCookie: cookieHelper.get(this._refreshTokenCookieName) ?? cookieHelper.get("stack-refresh"),
|
|
383
|
-
// keep old cookie name for backwards-compatibility
|
|
384
|
-
accessTokenCookie: cookieHelper.get(this._accessTokenCookieName)
|
|
385
|
-
});
|
|
555
|
+
const tokens = this._getTokensFromCookies(cookieHelper.getAll());
|
|
386
556
|
const store = new Store(tokens);
|
|
387
557
|
store.onChange((value) => {
|
|
388
558
|
runAsynchronously(async () => {
|
|
559
|
+
const refreshToken = value.refreshToken;
|
|
560
|
+
const secure = await isSecureCookieContext();
|
|
561
|
+
const defaultName = this._getRefreshTokenDefaultCookieNameForSecure(secure);
|
|
562
|
+
const { updatedAt, refreshCookieValue, accessTokenPayload, cookieNamesToDelete } = this._prepareRefreshCookieUpdate(
|
|
563
|
+
cookieHelper.getAll(),
|
|
564
|
+
refreshToken,
|
|
565
|
+
value.accessToken ?? null,
|
|
566
|
+
defaultName
|
|
567
|
+
);
|
|
389
568
|
await Promise.all([
|
|
390
|
-
setOrDeleteCookie(
|
|
391
|
-
setOrDeleteCookie(this._accessTokenCookieName,
|
|
569
|
+
setOrDeleteCookie(defaultName, refreshCookieValue, { maxAge: 60 * 60 * 24 * 365, noOpIfServerComponent: true }),
|
|
570
|
+
setOrDeleteCookie(this._accessTokenCookieName, accessTokenPayload, { maxAge: 60 * 60 * 24, noOpIfServerComponent: true })
|
|
392
571
|
]);
|
|
572
|
+
if (cookieNamesToDelete.length > 0) {
|
|
573
|
+
await Promise.all(
|
|
574
|
+
cookieNamesToDelete.map(
|
|
575
|
+
(name) => setOrDeleteCookie(name, null, { noOpIfServerComponent: true })
|
|
576
|
+
)
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
this._queueCustomRefreshCookieUpdate(refreshToken, updatedAt, "server");
|
|
393
580
|
});
|
|
394
581
|
});
|
|
395
582
|
return store;
|
|
@@ -420,11 +607,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
420
607
|
}
|
|
421
608
|
const cookieHeader = tokenStoreInit.headers.get("cookie");
|
|
422
609
|
const parsed = cookie.parse(cookieHeader || "");
|
|
423
|
-
const res = new Store(
|
|
424
|
-
refreshToken: parsed[this._refreshTokenCookieName] || parsed["stack-refresh"] || null,
|
|
425
|
-
// keep old cookie name for backwards-compatibility
|
|
426
|
-
accessToken: parsed[this._accessTokenCookieName] || null
|
|
427
|
-
});
|
|
610
|
+
const res = new Store(this._getTokensFromCookies(parsed));
|
|
428
611
|
this._requestTokenStores.set(tokenStoreInit, res);
|
|
429
612
|
return res;
|
|
430
613
|
} else if ("accessToken" in tokenStoreInit || "refreshToken" in tokenStoreInit) {
|
|
@@ -1552,15 +1735,28 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1552
1735
|
}
|
|
1553
1736
|
}
|
|
1554
1737
|
async signUpWithCredential(options) {
|
|
1738
|
+
if (options.noVerificationCallback && options.verificationCallbackUrl) {
|
|
1739
|
+
throw new StackAssertionError("verificationCallbackUrl is not allowed when noVerificationCallback is true");
|
|
1740
|
+
}
|
|
1555
1741
|
this._ensurePersistentTokenStore();
|
|
1556
1742
|
const session = await this._getSession();
|
|
1557
|
-
const emailVerificationRedirectUrl = options.verificationCallbackUrl ?? constructRedirectUrl(this.urls.emailVerification, "verificationCallbackUrl");
|
|
1558
|
-
|
|
1743
|
+
const emailVerificationRedirectUrl = options.noVerificationCallback ? void 0 : options.verificationCallbackUrl ?? constructRedirectUrl(this.urls.emailVerification, "verificationCallbackUrl");
|
|
1744
|
+
let result = await this._interface.signUpWithCredential(
|
|
1559
1745
|
options.email,
|
|
1560
1746
|
options.password,
|
|
1561
1747
|
emailVerificationRedirectUrl,
|
|
1562
1748
|
session
|
|
1563
1749
|
);
|
|
1750
|
+
if (result.status === "error" && result.error instanceof KnownErrors.RedirectUrlNotWhitelisted && !options.noVerificationCallback && emailVerificationRedirectUrl !== void 0) {
|
|
1751
|
+
console.error("Warning: The verification callback URL is not trusted. Proceeding with signup without email verification. Please add your domain to the trusted domains list in your Stack Auth dashboard.", { url: emailVerificationRedirectUrl });
|
|
1752
|
+
result = await this._interface.signUpWithCredential(
|
|
1753
|
+
options.email,
|
|
1754
|
+
options.password,
|
|
1755
|
+
void 0,
|
|
1756
|
+
// No email verification
|
|
1757
|
+
session
|
|
1758
|
+
);
|
|
1759
|
+
}
|
|
1564
1760
|
if (result.status === "ok") {
|
|
1565
1761
|
await this._signInToAccountWithTokens(result.data);
|
|
1566
1762
|
if (!options.noRedirect) {
|