From a052f94976c886771e568811dde1f2da55919c94 Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Thu, 27 Feb 2025 15:29:03 -0800 Subject: [PATCH] Permit signUpWithCredential in non-browser environments --- packages/template/src/lib/cookie.ts | 16 +++++++--------- packages/template/src/lib/stack-app.ts | 8 +++++--- packages/template/src/utils/url.ts | 19 +++++++------------ 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/packages/template/src/lib/cookie.ts b/packages/template/src/lib/cookie.ts index 0ca800e95..9f0ad6740 100644 --- a/packages/template/src/lib/cookie.ts +++ b/packages/template/src/lib/cookie.ts @@ -21,15 +21,13 @@ export type CookieHelper = { delete: (name: string, options: DeleteCookieOptions) => void, }; -export async function createEmptyCookieHelper(): Promise { - function throwError() { - throw new StackAssertionError("Empty cookie helper is just a placeholder. This should never be called"); +const placeholderCookieHelperIdentity = { "placeholder cookie helper identity": true }; +export async function createPlaceholderCookieHelper(): Promise { + function throwError(): never { + throw new StackAssertionError("Throwing cookie helper is just a placeholder. This should never be called"); } return { - get: () => { - throwError(); - return null; - }, + get: throwError, set: throwError, setOrDelete: throwError, delete: throwError, @@ -46,7 +44,7 @@ export async function createCookieHelper(): Promise { await rscHeaders(), ); // ELSE_PLATFORM - return await createEmptyCookieHelper(); + return await createPlaceholderCookieHelper(); // END_PLATFORM } } @@ -76,7 +74,7 @@ function handleCookieError(e: unknown, options: DeleteCookieOptions | SetCookieO function createNextCookieHelper( rscCookiesAwaited: Awaited>, rscHeadersAwaited: Awaited>, -) { +): CookieHelper { const cookieHelper = { get: (name: string) => { // set a helper cookie, see comment in `NextCookieHelper.set` below diff --git a/packages/template/src/lib/stack-app.ts b/packages/template/src/lib/stack-app.ts index 5ebd133bc..67afa8910 100644 --- a/packages/template/src/lib/stack-app.ts +++ b/packages/template/src/lib/stack-app.ts @@ -36,7 +36,7 @@ import * as NextNavigationUnscrambled from "next/navigation"; // import the enti import React, { useCallback, useMemo } from "react"; import { constructRedirectUrl } from "../utils/url"; import { addNewOAuthProviderOrScope, callOAuthCallback, signInWithOAuth } from "./auth"; -import { CookieHelper, createBrowserCookieHelper, createCookieHelper, createEmptyCookieHelper, deleteCookieClient, getCookieClient, setOrDeleteCookie, setOrDeleteCookieClient } from "./cookie"; +import { CookieHelper, createBrowserCookieHelper, createCookieHelper, createPlaceholderCookieHelper, deleteCookieClient, getCookieClient, setOrDeleteCookie, setOrDeleteCookieClient } from "./cookie"; let isReactServer = false; // IF_PLATFORM next @@ -426,7 +426,7 @@ class _StackClientAppImpl>(); protected _requestTokenStores = new WeakMap>(); protected _storedBrowserCookieTokenStore: Store | null = null; protected get _refreshTokenCookieName() { @@ -1558,10 +1559,11 @@ class _StackClientAppImpl> { this._ensurePersistentTokenStore(); const session = await this._getSession(); - const emailVerificationRedirectUrl = constructRedirectUrl(this.urls.emailVerification); + const emailVerificationRedirectUrl = options.verificationCallbackUrl ?? constructRedirectUrl(this.urls.emailVerification); const result = await this._interface.signUpWithCredential( options.email, options.password, diff --git a/packages/template/src/utils/url.ts b/packages/template/src/utils/url.ts index 48cacdd9e..31e9ae1d2 100644 --- a/packages/template/src/utils/url.ts +++ b/packages/template/src/utils/url.ts @@ -1,17 +1,12 @@ -export function autoRedirect() { - const url = new URL(window.location.href); - const redirectUrl = url.searchParams.get("auto-redirect-url"); - if (redirectUrl) { - const urlObject = new URL(redirectUrl); - if (urlObject.origin !== window.location.origin) { - throw new Error("auto-redirect-url is not same origin (" + urlObject.origin + " !== " + window.location.origin + ")"); - } - url.searchParams.delete("auto-redirect-url"); - window.location.replace(urlObject.href); - } -} +import { StackAssertionError } from "@stackframe/stack-shared/dist/utils/errors"; + export function constructRedirectUrl(redirectUrl: URL | string | undefined) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (typeof window === 'undefined' || !window.location) { + throw new StackAssertionError("Attempted to call constructRedirectUrl in a non-browser environment. You may be able to fix this by passing the `callbackUrl` option with your function call.", { redirectUrl }); + } + const retainedQueryParams = ["after_auth_return_to"]; const currentUrl = new URL(window.location.href); const url = redirectUrl ? new URL(redirectUrl, window.location.href) : new URL(window.location.href);