diff --git a/packages/stack/src/components-page/auth-page.tsx b/packages/stack/src/components-page/auth-page.tsx index 8f075aced..45ee9b605 100644 --- a/packages/stack/src/components-page/auth-page.tsx +++ b/packages/stack/src/components-page/auth-page.tsx @@ -16,10 +16,12 @@ import { useEffect } from 'react'; export function AuthPage({ fullPage=false, type, + automaticRedirect, mockProject, }: { fullPage?: boolean, type: 'sign-in' | 'sign-up', + automaticRedirect?: boolean, mockProject?: { config: { credentialEnabled: boolean, @@ -36,10 +38,12 @@ export function AuthPage({ const project = mockProject || projectFromHook; useEffect(() => { - if (user && !mockProject) { - runAsynchronously(type === 'sign-in' ? stackApp.redirectToAfterSignIn() : stackApp.redirectToAfterSignUp()); + if (automaticRedirect) { + if (user && !mockProject) { + runAsynchronously(type === 'sign-in' ? stackApp.redirectToAfterSignIn() : stackApp.redirectToAfterSignUp()); + } } - }, [user, mockProject, stackApp]); + }, [user, mockProject, stackApp, automaticRedirect]); if (user && !mockProject) { return ; diff --git a/packages/stack/src/components-page/oauth-callback.tsx b/packages/stack/src/components-page/oauth-callback.tsx index 183d66ee8..e9a0115cd 100644 --- a/packages/stack/src/components-page/oauth-callback.tsx +++ b/packages/stack/src/components-page/oauth-callback.tsx @@ -5,6 +5,7 @@ import { useStackApp } from ".."; import { runAsynchronously } from "@stackframe/stack-shared/dist/utils/promises"; import { MessageCard } from "../components/message-cards/message-card"; import { StyledLink } from "@stackframe/stack-ui"; +import { captureError } from "@stackframe/stack-shared/dist/utils/errors"; export function OAuthCallback(props: { fullPage?: boolean }) { const app = useStackApp(); @@ -19,10 +20,11 @@ export function OAuthCallback(props: { fullPage?: boolean }) { try { hasRedirected = await app.callOAuthCallback(); } catch (e: any) { + captureError("", e); setError(e); } if (!hasRedirected && (!error || process.env.NODE_ENV === 'production')) { - await app.redirectToSignIn(); + await app.redirectToSignIn({ noRedirectBack: true }); } }), []); diff --git a/packages/stack/src/components-page/stack-handler.tsx b/packages/stack/src/components-page/stack-handler.tsx index cd562441a..d57c67509 100644 --- a/packages/stack/src/components-page/stack-handler.tsx +++ b/packages/stack/src/components-page/stack-handler.tsx @@ -2,7 +2,7 @@ import { SignUp } from "./sign-up"; import { SignIn } from "./sign-in"; import { RedirectType, notFound, redirect } from 'next/navigation'; import { EmailVerification } from "./email-verification"; -import { StackServerApp } from ".."; +import { AuthPage, StackServerApp } from ".."; import { MessageCard } from "../components/message-cards/message-card"; import { HandlerUrls } from "../lib/stack-app"; import { SignOut } from "./sign-out"; @@ -67,11 +67,11 @@ export default async function StackHandler({ switch (path) { case availablePaths.signIn: { redirectIfNotHandler('signIn'); - return ; + return ; } case availablePaths.signUp: { redirectIfNotHandler('signUp'); - return ; + return ; } case availablePaths.emailVerification: { redirectIfNotHandler('emailVerification'); diff --git a/packages/stack/src/components/message-cards/predefined-message-card.tsx b/packages/stack/src/components/message-cards/predefined-message-card.tsx index f2c37b692..8c21c01b1 100644 --- a/packages/stack/src/components/message-cards/predefined-message-card.tsx +++ b/packages/stack/src/components/message-cards/predefined-message-card.tsx @@ -45,14 +45,14 @@ export function PredefinedMessageCard({ case 'passwordReset': { title = "Password reset successfully!"; message = 'Your password has been reset. You can now sign in with your new password.'; - primaryAction = () => stackApp.redirectToSignIn(); + primaryAction = () => stackApp.redirectToSignIn({ noRedirectBack: true }); primaryButton = "Sign in"; break; } case 'emailVerified': { title = "Email verified!"; message = 'Your have successfully verified your email.'; - primaryAction = () => stackApp.redirectToSignIn(); + primaryAction = () => stackApp.redirectToSignIn({ noRedirectBack: true }); primaryButton = "Sign in"; break; } diff --git a/packages/stack/src/lib/auth.ts b/packages/stack/src/lib/auth.ts index 81818d516..9b9ad9410 100644 --- a/packages/stack/src/lib/auth.ts +++ b/packages/stack/src/lib/auth.ts @@ -1,6 +1,6 @@ import { StackClientInterface } from "@stackframe/stack-shared"; import { InternalSession } from "@stackframe/stack-shared/dist/sessions"; -import { StackAssertionError } from "@stackframe/stack-shared/dist/utils/errors"; +import { StackAssertionError, captureError } from "@stackframe/stack-shared/dist/utils/errors"; import { neverResolve } from "@stackframe/stack-shared/dist/utils/promises"; import { constructRedirectUrl } from "../utils/url"; import { getVerifierAndState, saveVerifierAndState } from "./cookie"; @@ -64,6 +64,7 @@ function consumeOAuthCallbackQueryParams(expectedState: string): null | URL { const originalUrl = new URL(window.location.href); for (const param of requiredParams) { if (!originalUrl.searchParams.has(param)) { + captureError("consumeOAuthCallbackQueryParams", new Error(`Missing required query parameter on OAuth callback: ${param}`)); return null; } } @@ -71,6 +72,7 @@ function consumeOAuthCallbackQueryParams(expectedState: string): null | URL { if (expectedState !== originalUrl.searchParams.get("state")) { // If the state doesn't match, then the callback wasn't meant for us. // Maybe the website uses another OAuth library? + captureError("consumeOAuthCallbackQueryParams", new Error(`Invalid OAuth callback state: Was this meant for someone else, or did cookies fail?`)); return null; } diff --git a/packages/stack/src/lib/stack-app.ts b/packages/stack/src/lib/stack-app.ts index 50c8282cc..492f27706 100644 --- a/packages/stack/src/lib/stack-app.ts +++ b/packages/stack/src/lib/stack-app.ts @@ -881,29 +881,31 @@ class _StackClientAppImpl =